blob: a14d7a16b2dd1162fa8572d776f4adee8a0ce91f [file] [log] [blame]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
Paul Mackerras9e026d32005-09-27 10:29:41 +10003exec wish "$0" -- "$@"
Paul Mackerras1db95b02005-05-09 04:08:39 +00004
Paul Mackerrasfbf42642016-12-12 20:46:42 +11005# Copyright © 2005-2016 Paul Mackerras. All rights reserved.
Paul Mackerras1db95b02005-05-09 04:08:39 +00006# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
Pat Thoytsd93f1712009-04-17 01:24:35 +010010package require Tk
11
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012proc hasworktree {} {
13 return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
14 [exec git rev-parse --is-inside-git-dir] == "false"}]
15}
16
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010017proc reponame {} {
18 global gitdir
19 set n [file normalize $gitdir]
20 if {[string match "*/.git" $n]} {
21 set n [string range $n 0 end-5]
22 }
23 return [file tail $n]
24}
25
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000026proc gitworktree {} {
27 variable _gitworktree
28 if {[info exists _gitworktree]} {
29 return $_gitworktree
30 }
31 # v1.7.0 introduced --show-toplevel to return the canonical work-tree
32 if {[catch {set _gitworktree [exec git rev-parse --show-toplevel]}]} {
33 # try to set work tree from environment, core.worktree or use
34 # cdup to obtain a relative path to the top of the worktree. If
35 # run from the top, the ./ prefix ensures normalize expands pwd.
36 if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
37 catch {set _gitworktree [exec git config --get core.worktree]}
38 if {$_gitworktree eq ""} {
39 set _gitworktree [file normalize ./[exec git rev-parse --show-cdup]]
40 }
41 }
42 }
43 return $_gitworktree
44}
45
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100046# A simple scheduler for compute-intensive stuff.
47# The aim is to make sure that event handlers for GUI actions can
48# run at least every 50-100 ms. Unfortunately fileevent handlers are
49# run before X event handlers, so reading from a fast source can
50# make the GUI completely unresponsive.
51proc run args {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040052 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100053
54 set script $args
55 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040056 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100057 after idle dorunq
58 }
59 lappend runq [list {} $script]
60 set isonrunq($script) 1
61}
62
63proc filerun {fd script} {
64 fileevent $fd readable [list filereadable $fd $script]
65}
66
67proc filereadable {fd script} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040068 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100069
70 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040071 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 after idle dorunq
73 }
74 lappend runq [list $fd $script]
75}
76
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110077proc nukefile {fd} {
78 global runq
79
80 for {set i 0} {$i < [llength $runq]} {} {
81 if {[lindex $runq $i 0] eq $fd} {
82 set runq [lreplace $runq $i $i]
83 } else {
84 incr i
85 }
86 }
87}
88
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100089proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040090 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100091
92 set tstart [clock clicks -milliseconds]
93 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110094 while {[llength $runq] > 0} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100095 set fd [lindex $runq 0 0]
96 set script [lindex $runq 0 1]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040097 set currunq [lindex $runq 0]
98 set runq [lrange $runq 1 end]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100099 set repeat [eval $script]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +0400100 unset currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000101 set t1 [clock clicks -milliseconds]
102 set t [expr {$t1 - $t0}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000103 if {$repeat ne {} && $repeat} {
104 if {$fd eq {} || $repeat == 2} {
105 # script returns 1 if it wants to be readded
106 # file readers return 2 if they could do more straight away
107 lappend runq [list $fd $script]
108 } else {
109 fileevent $fd readable [list filereadable $fd $script]
110 }
111 } elseif {$fd eq {}} {
112 unset isonrunq($script)
113 }
114 set t0 $t1
115 if {$t1 - $tstart >= 80} break
116 }
117 if {$runq ne {}} {
118 after idle dorunq
119 }
120}
121
Alexander Gavrilove439e092008-07-13 16:40:47 +0400122proc reg_instance {fd} {
123 global commfd leftover loginstance
124
125 set i [incr loginstance]
126 set commfd($i) $fd
127 set leftover($i) {}
128 return $i
129}
130
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000131proc unmerged_files {files} {
132 global nr_unmerged
133
134 # find the list of unmerged files
135 set mlist {}
136 set nr_unmerged 0
137 if {[catch {
138 set fd [open "| git ls-files -u" r]
139 } err]} {
140 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
141 exit 1
142 }
143 while {[gets $fd line] >= 0} {
144 set i [string first "\t" $line]
145 if {$i < 0} continue
146 set fname [string range $line [expr {$i+1}] end]
147 if {[lsearch -exact $mlist $fname] >= 0} continue
148 incr nr_unmerged
149 if {$files eq {} || [path_filter $files $fname]} {
150 lappend mlist $fname
151 }
152 }
153 catch {close $fd}
154 return $mlist
155}
156
157proc parseviewargs {n arglist} {
Christian Couderc2f2dab2009-12-12 05:52:39 +0100158 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
Thomas Rast9403bd02013-11-16 18:37:43 +0100159 global vinlinediff
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200160 global worddiff git_version
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000161
162 set vdatemode($n) 0
163 set vmergeonly($n) 0
Thomas Rast9403bd02013-11-16 18:37:43 +0100164 set vinlinediff($n) 0
Paul Mackerrasee66e082008-05-09 10:14:07 +1000165 set glflags {}
166 set diffargs {}
167 set nextisval 0
168 set revargs {}
169 set origargs $arglist
170 set allknown 1
171 set filtered 0
172 set i -1
173 foreach arg $arglist {
174 incr i
175 if {$nextisval} {
176 lappend glflags $arg
177 set nextisval 0
178 continue
179 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000180 switch -glob -- $arg {
181 "-d" -
182 "--date-order" {
183 set vdatemode($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000184 # remove from origargs in case we hit an unknown option
185 set origargs [lreplace $origargs $i $i]
186 incr i -1
187 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000188 "-[puabwcrRBMC]" -
189 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
190 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
191 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
192 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
193 "--ignore-space-change" - "-U*" - "--unified=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100194 # These request or affect diff output, which we don't want.
195 # Some could be used to set our defaults for diff display.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000196 lappend diffargs $arg
197 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000198 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200199 "--name-only" - "--name-status" - "--color" -
Paul Mackerrasee66e082008-05-09 10:14:07 +1000200 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
201 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
202 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
203 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
204 "--objects" - "--objects-edge" - "--reverse" {
Paul Mackerras29582282008-11-18 19:44:20 +1100205 # These cause our parsing of git log's output to fail, or else
206 # they're options we want to set ourselves, so ignore them.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000207 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200208 "--color-words*" - "--word-diff=color" {
209 # These trigger a word diff in the console interface,
210 # so help the user by enabling our own support
211 if {[package vcompare $git_version "1.7.2"] >= 0} {
212 set worddiff [mc "Color words"]
213 }
214 }
215 "--word-diff*" {
216 if {[package vcompare $git_version "1.7.2"] >= 0} {
217 set worddiff [mc "Markup words"]
218 }
219 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000220 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
221 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
222 "--full-history" - "--dense" - "--sparse" -
223 "--follow" - "--left-right" - "--encoding=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100224 # These are harmless, and some are even useful
Paul Mackerrasee66e082008-05-09 10:14:07 +1000225 lappend glflags $arg
226 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000227 "--diff-filter=*" - "--no-merges" - "--unpacked" -
228 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
229 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
230 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
231 "--remove-empty" - "--first-parent" - "--cherry-pick" -
Thomas Rast71846c52013-11-16 18:37:40 +0100232 "-S*" - "-G*" - "--pickaxe-all" - "--pickaxe-regex" -
Dirk Suesserottf687aaa2009-05-21 15:35:40 +0200233 "--simplify-by-decoration" {
Paul Mackerras29582282008-11-18 19:44:20 +1100234 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000235 set filtered 1
236 lappend glflags $arg
237 }
Thomas Rastce2c58c2013-11-16 18:37:44 +0100238 "-L*" {
239 # Line-log with 'stuck' argument (unstuck form is
240 # not supported)
241 set filtered 1
242 set vinlinediff($n) 1
243 set allknown 0
244 lappend glflags $arg
245 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000246 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100247 # This appears to be the only one that has a value as a
248 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000249 set filtered 1
250 set nextisval 1
251 lappend glflags $arg
252 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100253 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000254 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000255 }
256 "--merge" {
257 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000258 # git rev-parse doesn't understand --merge
259 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000260 }
Christian Couderc2f2dab2009-12-12 05:52:39 +0100261 "--no-replace-objects" {
262 set env(GIT_NO_REPLACE_OBJECTS) "1"
263 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000264 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100265 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000266 if {[string is digit -strict [string range $arg 1 end]]} {
267 set filtered 1
268 } else {
269 # a flag argument that we don't recognize;
270 # that means we can't optimize
271 set allknown 0
272 }
273 lappend glflags $arg
274 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000275 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100276 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000277 if {[string match "*...*" $arg]} {
278 lappend revargs --gitk-symmetric-diff-marker
279 }
280 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000281 }
282 }
283 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000284 set vdflags($n) $diffargs
285 set vflags($n) $glflags
286 set vrevs($n) $revargs
287 set vfiltered($n) $filtered
288 set vorigargs($n) $origargs
289 return $allknown
290}
291
292proc parseviewrevs {view revs} {
293 global vposids vnegids
294
295 if {$revs eq {}} {
296 set revs HEAD
Max Kirillov4d5e1b12014-09-09 10:29:16 +0300297 } elseif {[lsearch -exact $revs --all] >= 0} {
298 lappend revs HEAD
Paul Mackerrasee66e082008-05-09 10:14:07 +1000299 }
300 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
301 # we get stdout followed by stderr in $err
302 # for an unknown rev, git rev-parse echoes it and then errors out
303 set errlines [split $err "\n"]
304 set badrev {}
305 for {set l 0} {$l < [llength $errlines]} {incr l} {
306 set line [lindex $errlines $l]
307 if {!([string length $line] == 40 && [string is xdigit $line])} {
308 if {[string match "fatal:*" $line]} {
309 if {[string match "fatal: ambiguous argument*" $line]
310 && $badrev ne {}} {
311 if {[llength $badrev] == 1} {
312 set err "unknown revision $badrev"
313 } else {
314 set err "unknown revisions: [join $badrev ", "]"
315 }
316 } else {
317 set err [join [lrange $errlines $l end] "\n"]
318 }
319 break
320 }
321 lappend badrev $line
322 }
Pat Thoytsd93f1712009-04-17 01:24:35 +0100323 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200324 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000325 return {}
326 }
327 set ret {}
328 set pos {}
329 set neg {}
330 set sdm 0
331 foreach id [split $ids "\n"] {
332 if {$id eq "--gitk-symmetric-diff-marker"} {
333 set sdm 4
334 } elseif {[string match "^*" $id]} {
335 if {$sdm != 1} {
336 lappend ret $id
337 if {$sdm == 3} {
338 set sdm 0
339 }
340 }
341 lappend neg [string range $id 1 end]
342 } else {
343 if {$sdm != 2} {
344 lappend ret $id
345 } else {
Thomas Rast2b1fbf92009-08-05 23:15:36 +0200346 lset ret end $id...[lindex $ret end]
Paul Mackerrasee66e082008-05-09 10:14:07 +1000347 }
348 lappend pos $id
349 }
350 incr sdm -1
351 }
352 set vposids($view) $pos
353 set vnegids($view) $neg
354 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000355}
356
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100357# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000358proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000359 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400360 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000361 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100362 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400363 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100364 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000365 global vcanopt vflags vrevs vorigargs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400366 global show_notes
Paul Mackerras38ad0912005-12-01 22:42:46 +1100367
368 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000369 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000370 # these are set this way for the error exits
371 set viewcomplete($view) 1
372 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100373 varcinit $view
374
Yann Dirson2d480852008-02-21 21:23:31 +0100375 set args $viewargs($view)
376 if {$viewargscmd($view) ne {}} {
377 if {[catch {
378 set str [exec sh -c $viewargscmd($view)]
379 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200380 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000381 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100382 }
383 set args [concat $args [split $str "\n"]]
384 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000385 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000386
387 set files $viewfiles($view)
388 if {$vmergeonly($view)} {
389 set files [unmerged_files $files]
390 if {$files eq {}} {
391 global nr_unmerged
392 if {$nr_unmerged == 0} {
393 error_popup [mc "No files selected: --merge specified but\
394 no files are unmerged."]
395 } else {
396 error_popup [mc "No files selected: --merge specified but\
397 no unmerged files are within file limit."]
398 }
399 return 0
400 }
401 }
402 set vfilelimit($view) $files
403
Paul Mackerrasee66e082008-05-09 10:14:07 +1000404 if {$vcanopt($view)} {
405 set revs [parseviewrevs $view $vrevs($view)]
406 if {$revs eq {}} {
407 return 0
408 }
409 set args [concat $vflags($view) $revs]
410 } else {
411 set args $vorigargs($view)
412 }
413
Paul Mackerras418c4c72006-02-07 09:10:18 +1100414 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400415 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
416 --parents --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100417 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100418 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000419 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100420 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400421 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100422 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100423 set viewmainheadid($view) $mainheadid
424 set viewmainheadid_orig($view) $mainheadid
425 if {$files ne {} && $mainheadid ne {}} {
426 get_viewmainhead $view
427 }
428 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
429 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000430 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400431 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100432 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000433 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100434 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100435 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100436 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000437 set viewcomplete($view) 0
438 set viewactive($view) 1
439 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100440}
441
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400442proc stop_instance {inst} {
443 global commfd leftover
444
445 set fd $commfd($inst)
446 catch {
447 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400448
449 if {$::tcl_platform(platform) eq {windows}} {
Sebastian Schuberth7b68b0ee2014-10-23 21:30:54 +0200450 exec taskkill /pid $pid
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400451 } else {
452 exec kill $pid
453 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400454 }
455 catch {close $fd}
456 nukefile $fd
457 unset commfd($inst)
458 unset leftover($inst)
459}
460
461proc stop_backends {} {
462 global commfd
463
464 foreach inst [array names commfd] {
465 stop_instance $inst
466 }
467}
468
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100469proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400470 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000471
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100472 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400473 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000474 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100475 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000476}
477
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400478proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400479 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400480
481 if {$selid ne {}} {
482 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400483 } elseif {$selectheadid ne {}} {
484 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400485 } else {
486 set pending_select $mainheadid
487 }
488}
489
490proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000491 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100492
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000493 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000494 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400495 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000496 show_status [mc "Reading commits..."]
497 set need_redisplay 1
498 } else {
499 show_status [mc "No commits selected"]
500 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000501}
502
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100503proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000504 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400505 global viewactive viewcomplete tclencoding
506 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100507 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400508 global hasworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000509 global varcid vposids vnegids vflags vrevs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400510 global show_notes
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100511
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400512 set hasworktree [hasworktree]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100513 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100514 set view $curview
515 if {$mainheadid ne $viewmainheadid_orig($view)} {
516 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100517 dohidelocalchanges
518 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100519 set viewmainheadid($view) $mainheadid
520 set viewmainheadid_orig($view) $mainheadid
521 if {$vfilelimit($view) ne {}} {
522 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100523 }
524 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100525 if {$showlocalchanges} {
526 doshowlocalchanges
527 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000528 if {$vcanopt($view)} {
529 set oldpos $vposids($view)
530 set oldneg $vnegids($view)
531 set revs [parseviewrevs $view $vrevs($view)]
532 if {$revs eq {}} {
533 return
534 }
535 # note: getting the delta when negative refs change is hard,
536 # and could require multiple git log invocations, so in that
537 # case we ask git log for all the commits (not just the delta)
538 if {$oldneg eq $vnegids($view)} {
539 set newrevs {}
540 set npos 0
541 # take out positive refs that we asked for before or
542 # that we have already seen
543 foreach rev $revs {
544 if {[string length $rev] == 40} {
545 if {[lsearch -exact $oldpos $rev] < 0
546 && ![info exists varcid($view,$rev)]} {
547 lappend newrevs $rev
548 incr npos
549 }
550 } else {
551 lappend $newrevs $rev
552 }
553 }
554 if {$npos == 0} return
555 set revs $newrevs
556 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
557 }
558 set args [concat $vflags($view) $revs --not $oldpos]
559 } else {
560 set args $vorigargs($view)
561 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100562 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400563 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
564 --parents --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100565 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200566 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000567 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100568 }
569 if {$viewactive($view) == 0} {
570 set startmsecs [clock clicks -milliseconds]
571 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400572 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100573 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100574 fconfigure $fd -blocking 0 -translation lf -eofchar {}
575 if {$tclencoding != {}} {
576 fconfigure $fd -encoding $tclencoding
577 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100578 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100579 incr viewactive($view)
580 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400581 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200582 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100583 if {$showneartags} {
584 getallcommits
585 }
586}
587
588proc reloadcommits {} {
589 global curview viewcomplete selectedline currentid thickerline
590 global showneartags treediffs commitinterest cached_commitrow
Markus Hitter18ae9122016-11-07 19:02:51 +0100591 global targetid commitinfo
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100592
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400593 set selid {}
594 if {$selectedline ne {}} {
595 set selid $currentid
596 }
597
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100598 if {!$viewcomplete($curview)} {
599 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100600 }
601 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000602 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +1000603 unset -nocomplain currentid
604 unset -nocomplain thickerline
605 unset -nocomplain treediffs
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100606 readrefs
607 changedrefs
608 if {$showneartags} {
609 getallcommits
610 }
611 clear_display
Markus Hitter18ae9122016-11-07 19:02:51 +0100612 unset -nocomplain commitinfo
Paul Mackerras009409f2015-05-02 20:53:36 +1000613 unset -nocomplain commitinterest
614 unset -nocomplain cached_commitrow
615 unset -nocomplain targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100616 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400617 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100618 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100619}
620
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000621# This makes a string representation of a positive integer which
622# sorts as a string in numerical order
623proc strrep {n} {
624 if {$n < 16} {
625 return [format "%x" $n]
626 } elseif {$n < 256} {
627 return [format "x%.2x" $n]
628 } elseif {$n < 65536} {
629 return [format "y%.4x" $n]
630 }
631 return [format "z%.8x" $n]
632}
633
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100634# Procedures used in reordering commits from git log (without
635# --topo-order) into the order for display.
636
637proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100638 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
639 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100640
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100641 set varcstart($view) {{}}
642 set vupptr($view) {0}
643 set vdownptr($view) {0}
644 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100645 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100646 set varctok($view) {{}}
647 set varcrow($view) {{}}
648 set vtokmod($view) {}
649 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100650 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100651 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100652 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100653}
654
655proc resetvarcs {view} {
656 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100657 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100658
659 foreach vid [array names varcid $view,*] {
660 unset varcid($vid)
661 unset children($vid)
662 unset parents($vid)
663 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100664 foreach vid [array names vshortids $view,*] {
665 unset vshortids($vid)
666 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100667 # some commits might have children but haven't been seen yet
668 foreach vid [array names children $view,*] {
669 unset children($vid)
670 }
671 foreach va [array names varccommits $view,*] {
672 unset varccommits($va)
673 }
674 foreach vd [array names vseedcount $view,*] {
675 unset vseedcount($vd)
676 }
Paul Mackerras009409f2015-05-02 20:53:36 +1000677 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100678}
679
Paul Mackerras468bcae2008-03-03 10:19:35 +1100680# returns a list of the commits with no children
681proc seeds {v} {
682 global vdownptr vleftptr varcstart
683
684 set ret {}
685 set a [lindex $vdownptr($v) 0]
686 while {$a != 0} {
687 lappend ret [lindex $varcstart($v) $a]
688 set a [lindex $vleftptr($v) $a]
689 }
690 return $ret
691}
692
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100693proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000694 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100695 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
696 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100697
698 set a [llength $varctok($view)]
699 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000700 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100701 if {![info exists commitinfo($id)]} {
702 parsecommit $id $commitdata($id) 1
703 }
Anders Kaseorgf5974d92011-01-19 14:47:25 -0500704 set cdate [lindex [lindex $commitinfo($id) 4] 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100705 if {![string is integer -strict $cdate]} {
706 set cdate 0
707 }
708 if {![info exists vseedcount($view,$cdate)]} {
709 set vseedcount($view,$cdate) -1
710 }
711 set c [incr vseedcount($view,$cdate)]
712 set cdate [expr {$cdate ^ 0xffffffff}]
713 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100714 } else {
715 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100716 }
717 set ka 0
718 if {[llength $children($vid)] > 0} {
719 set kid [lindex $children($vid) end]
720 set k $varcid($view,$kid)
721 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
722 set ki $kid
723 set ka $k
724 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100725 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100726 }
727 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100728 set i [lsearch -exact $parents($view,$ki) $id]
729 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100730 append tok [strrep $j]
731 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100732 set c [lindex $vlastins($view) $ka]
733 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
734 set c $ka
735 set b [lindex $vdownptr($view) $ka]
736 } else {
737 set b [lindex $vleftptr($view) $c]
738 }
739 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
740 set c $b
741 set b [lindex $vleftptr($view) $c]
742 }
743 if {$c == $ka} {
744 lset vdownptr($view) $ka $a
745 lappend vbackptr($view) 0
746 } else {
747 lset vleftptr($view) $c $a
748 lappend vbackptr($view) $c
749 }
750 lset vlastins($view) $ka $a
751 lappend vupptr($view) $ka
752 lappend vleftptr($view) $b
753 if {$b != 0} {
754 lset vbackptr($view) $b $a
755 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100756 lappend varctok($view) $tok
757 lappend varcstart($view) $id
758 lappend vdownptr($view) 0
759 lappend varcrow($view) {}
760 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100761 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100762 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100763 return $a
764}
765
766proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100767 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100768 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100769
770 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100771 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100772 set ac $varccommits($v,$oa)
773 set i [lsearch -exact $varccommits($v,$oa) $p]
774 if {$i <= 0} return
775 set na [llength $varctok($v)]
776 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100777 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100778 lappend varctok($v) $tok
779 lappend varcrow($v) {}
780 lappend varcix($v) {}
781 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
782 set varccommits($v,$na) [lrange $ac $i end]
783 lappend varcstart($v) $p
784 foreach id $varccommits($v,$na) {
785 set varcid($v,$id) $na
786 }
787 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100788 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100789 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100790 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100791 lappend vupptr($v) $oa
792 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100793 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100794 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
795 lset vupptr($v) $b $na
796 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100797 if {[string compare $otok $vtokmod($v)] <= 0} {
798 modify_arc $v $oa
799 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100800}
801
802proc renumbervarc {a v} {
803 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000804 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100805
806 set t1 [clock clicks -milliseconds]
807 set todo {}
808 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100809 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100810 set ntot 0
811 while {$a != 0} {
812 if {[info exists isrelated($a)]} {
813 lappend todo $a
814 set id [lindex $varccommits($v,$a) end]
815 foreach p $parents($v,$id) {
816 if {[info exists varcid($v,$p)]} {
817 set isrelated($varcid($v,$p)) 1
818 }
819 }
820 }
821 incr ntot
822 set b [lindex $vdownptr($v) $a]
823 if {$b == 0} {
824 while {$a != 0} {
825 set b [lindex $vleftptr($v) $a]
826 if {$b != 0} break
827 set a [lindex $vupptr($v) $a]
828 }
829 }
830 set a $b
831 }
832 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100833 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100834 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100835 if {[llength $children($v,$id)] > 1} {
836 set children($v,$id) [lsort -command [list vtokcmp $v] \
837 $children($v,$id)]
838 }
839 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000840 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100841 set tok {}
842 } else {
843 set tok $oldtok
844 }
845 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100846 set kid [last_real_child $v,$id]
847 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100848 set k $varcid($v,$kid)
849 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
850 set ki $kid
851 set ka $k
852 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100853 }
854 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100855 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100856 set i [lsearch -exact $parents($v,$ki) $id]
857 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
858 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100859 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100860 if {$tok eq $oldtok} {
861 continue
862 }
863 set id [lindex $varccommits($v,$a) end]
864 foreach p $parents($v,$id) {
865 if {[info exists varcid($v,$p)]} {
866 set kidchanged($varcid($v,$p)) 1
867 } else {
868 set sortkids($p) 1
869 }
870 }
871 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100872 set b [lindex $vupptr($v) $a]
873 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100874 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
875 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100876 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100877 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
878 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100879 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100880 set c [lindex $vbackptr($v) $a]
881 set d [lindex $vleftptr($v) $a]
882 if {$c == 0} {
883 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100884 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100885 lset vleftptr($v) $c $d
886 }
887 if {$d != 0} {
888 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100889 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100890 if {[lindex $vlastins($v) $b] == $a} {
891 lset vlastins($v) $b $c
892 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100893 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100894 set c [lindex $vlastins($v) $ka]
895 if {$c == 0 || \
896 [string compare $tok [lindex $varctok($v) $c]] < 0} {
897 set c $ka
898 set b [lindex $vdownptr($v) $ka]
899 } else {
900 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100901 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100902 while {$b != 0 && \
903 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
904 set c $b
905 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100906 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100907 if {$c == $ka} {
908 lset vdownptr($v) $ka $a
909 lset vbackptr($v) $a 0
910 } else {
911 lset vleftptr($v) $c $a
912 lset vbackptr($v) $a $c
913 }
914 lset vleftptr($v) $a $b
915 if {$b != 0} {
916 lset vbackptr($v) $b $a
917 }
918 lset vlastins($v) $ka $a
919 }
920 }
921 foreach id [array names sortkids] {
922 if {[llength $children($v,$id)] > 1} {
923 set children($v,$id) [lsort -command [list vtokcmp $v] \
924 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100925 }
926 }
927 set t2 [clock clicks -milliseconds]
928 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
929}
930
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100931# Fix up the graph after we have found out that in view $v,
932# $p (a commit that we have already seen) is actually the parent
933# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100934proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100935 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100936
937 set pa $varcid($v,$p)
938 if {$p ne [lindex $varcstart($v) $pa]} {
939 splitvarc $p $v
940 set pa $varcid($v,$p)
941 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100942 # seeds always need to be renumbered
943 if {[lindex $vupptr($v) $pa] == 0 ||
944 [string compare [lindex $varctok($v) $a] \
945 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100946 renumbervarc $pa $v
947 }
948}
949
950proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100951 global cmitlisted children parents varcid varctok vtokmod
952 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100953 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100954
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100955 readcommit $id
956 set vid $v,$id
957 set cmitlisted($vid) 1
958 set children($vid) {}
959 set parents($vid) [list $p]
960 set a [newvarc $v $id]
961 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100962 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100963 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
964 modify_arc $v $a
965 }
966 lappend varccommits($v,$a) $id
967 set vp $v,$p
968 if {[llength [lappend children($vp) $id]] > 1} {
969 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
Paul Mackerras009409f2015-05-02 20:53:36 +1000970 unset -nocomplain ordertok
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100971 }
972 fix_reversal $p $a $v
973 incr commitidx($v)
974 if {$v == $curview} {
975 set numcommits $commitidx($v)
976 setcanvscroll
977 if {[info exists targetid]} {
978 if {![comes_before $targetid $p]} {
979 incr targetrow
980 }
981 }
982 }
983}
984
985proc insertfakerow {id p} {
986 global varcid varccommits parents children cmitlisted
987 global commitidx varctok vtokmod targetid targetrow curview numcommits
988
989 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100990 set a $varcid($v,$p)
991 set i [lsearch -exact $varccommits($v,$a) $p]
992 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100993 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100994 return
995 }
996 set children($v,$id) {}
997 set parents($v,$id) [list $p]
998 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100999 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001000 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001001 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001002 # note we deliberately don't update varcstart($v) even if $i == 0
1003 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001004 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +11001005 if {[info exists targetid]} {
1006 if {![comes_before $targetid $p]} {
1007 incr targetrow
1008 }
1009 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001010 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001011 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001012}
1013
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001014proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001015 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001016 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001017 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001018
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001019 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001020 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001021 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001022 return
1023 }
1024 set p [lindex $parents($v,$id) 0]
1025 set a $varcid($v,$id)
1026 set i [lsearch -exact $varccommits($v,$a) $id]
1027 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001028 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001029 return
1030 }
1031 unset varcid($v,$id)
1032 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1033 unset parents($v,$id)
1034 unset children($v,$id)
1035 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001036 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001037 set j [lsearch -exact $children($v,$p) $id]
1038 if {$j >= 0} {
1039 set children($v,$p) [lreplace $children($v,$p) $j $j]
1040 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001041 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001042 if {[info exist currentid] && $id eq $currentid} {
1043 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +10001044 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001045 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001046 if {[info exists targetid] && $targetid eq $id} {
1047 set targetid $p
1048 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001049 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001050 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001051}
1052
Paul Mackerrasaa435612009-09-10 21:58:40 +10001053proc real_children {vp} {
1054 global children nullid nullid2
1055
1056 set kids {}
1057 foreach id $children($vp) {
1058 if {$id ne $nullid && $id ne $nullid2} {
1059 lappend kids $id
1060 }
1061 }
1062 return $kids
1063}
1064
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001065proc first_real_child {vp} {
1066 global children nullid nullid2
1067
1068 foreach id $children($vp) {
1069 if {$id ne $nullid && $id ne $nullid2} {
1070 return $id
1071 }
1072 }
1073 return {}
1074}
1075
1076proc last_real_child {vp} {
1077 global children nullid nullid2
1078
1079 set kids $children($vp)
1080 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1081 set id [lindex $kids $i]
1082 if {$id ne $nullid && $id ne $nullid2} {
1083 return $id
1084 }
1085 }
1086 return {}
1087}
1088
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001089proc vtokcmp {v a b} {
1090 global varctok varcid
1091
1092 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1093 [lindex $varctok($v) $varcid($v,$b)]]
1094}
1095
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001096# This assumes that if lim is not given, the caller has checked that
1097# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001098proc modify_arc {v a {lim {}}} {
1099 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001100
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001101 if {$lim ne {}} {
1102 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1103 if {$c > 0} return
1104 if {$c == 0} {
1105 set r [lindex $varcrow($v) $a]
1106 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1107 }
1108 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001109 set vtokmod($v) [lindex $varctok($v) $a]
1110 set varcmod($v) $a
1111 if {$v == $curview} {
1112 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1113 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001114 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001115 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001116 set r 0
1117 if {$a != 0} {
1118 if {$lim eq {}} {
1119 set lim [llength $varccommits($v,$a)]
1120 }
1121 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1122 }
1123 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001124 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001125 }
1126}
1127
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001128proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001129 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001130 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001131 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001132 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001133
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001134 if {$vrowmod($v) == $commitidx($v)} return
1135 if {$v == $curview} {
1136 if {[llength $displayorder] > $vrowmod($v)} {
1137 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1138 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1139 }
Paul Mackerras009409f2015-05-02 20:53:36 +10001140 unset -nocomplain cached_commitrow
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001141 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001142 set narctot [expr {[llength $varctok($v)] - 1}]
1143 set a $varcmod($v)
1144 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1145 # go up the tree until we find something that has a row number,
1146 # or we get to a seed
1147 set a [lindex $vupptr($v) $a]
1148 }
1149 if {$a == 0} {
1150 set a [lindex $vdownptr($v) 0]
1151 if {$a == 0} return
1152 set vrownum($v) {0}
1153 set varcorder($v) [list $a]
1154 lset varcix($v) $a 0
1155 lset varcrow($v) $a 0
1156 set arcn 0
1157 set row 0
1158 } else {
1159 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001160 if {[llength $vrownum($v)] > $arcn + 1} {
1161 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1162 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1163 }
1164 set row [lindex $varcrow($v) $a]
1165 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001166 while {1} {
1167 set p $a
1168 incr row [llength $varccommits($v,$a)]
1169 # go down if possible
1170 set b [lindex $vdownptr($v) $a]
1171 if {$b == 0} {
1172 # if not, go left, or go up until we can go left
1173 while {$a != 0} {
1174 set b [lindex $vleftptr($v) $a]
1175 if {$b != 0} break
1176 set a [lindex $vupptr($v) $a]
1177 }
1178 if {$a == 0} break
1179 }
1180 set a $b
1181 incr arcn
1182 lappend vrownum($v) $row
1183 lappend varcorder($v) $a
1184 lset varcix($v) $a $arcn
1185 lset varcrow($v) $a $row
1186 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001187 set vtokmod($v) [lindex $varctok($v) $p]
1188 set varcmod($v) $p
1189 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001190 if {[info exists currentid]} {
1191 set selectedline [rowofcommit $currentid]
1192 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001193}
1194
1195# Test whether view $v contains commit $id
1196proc commitinview {id v} {
1197 global varcid
1198
1199 return [info exists varcid($v,$id)]
1200}
1201
1202# Return the row number for commit $id in the current view
1203proc rowofcommit {id} {
1204 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001205 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001206
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001207 set v $curview
1208 if {![info exists varcid($v,$id)]} {
1209 puts "oops rowofcommit no arc for [shortids $id]"
1210 return {}
1211 }
1212 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001213 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001214 update_arcrows $v
1215 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001216 if {[info exists cached_commitrow($id)]} {
1217 return $cached_commitrow($id)
1218 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001219 set i [lsearch -exact $varccommits($v,$a) $id]
1220 if {$i < 0} {
1221 puts "oops didn't find commit [shortids $id] in arc $a"
1222 return {}
1223 }
1224 incr i [lindex $varcrow($v) $a]
1225 set cached_commitrow($id) $i
1226 return $i
1227}
1228
Paul Mackerras42a671f2008-01-02 09:59:39 +11001229# Returns 1 if a is on an earlier row than b, otherwise 0
1230proc comes_before {a b} {
1231 global varcid varctok curview
1232
1233 set v $curview
1234 if {$a eq $b || ![info exists varcid($v,$a)] || \
1235 ![info exists varcid($v,$b)]} {
1236 return 0
1237 }
1238 if {$varcid($v,$a) != $varcid($v,$b)} {
1239 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1240 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1241 }
1242 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1243}
1244
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001245proc bsearch {l elt} {
1246 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1247 return 0
1248 }
1249 set lo 0
1250 set hi [llength $l]
1251 while {$hi - $lo > 1} {
1252 set mid [expr {int(($lo + $hi) / 2)}]
1253 set t [lindex $l $mid]
1254 if {$elt < $t} {
1255 set hi $mid
1256 } elseif {$elt > $t} {
1257 set lo $mid
1258 } else {
1259 return $mid
1260 }
1261 }
1262 return $lo
1263}
1264
1265# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1266proc make_disporder {start end} {
1267 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001268 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001269 global d_valid_start d_valid_end
1270
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001271 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001272 update_arcrows $curview
1273 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001274 set ai [bsearch $vrownum($curview) $start]
1275 set start [lindex $vrownum($curview) $ai]
1276 set narc [llength $vrownum($curview)]
1277 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1278 set a [lindex $varcorder($curview) $ai]
1279 set l [llength $displayorder]
1280 set al [llength $varccommits($curview,$a)]
1281 if {$l < $r + $al} {
1282 if {$l < $r} {
1283 set pad [ntimes [expr {$r - $l}] {}]
1284 set displayorder [concat $displayorder $pad]
1285 set parentlist [concat $parentlist $pad]
1286 } elseif {$l > $r} {
1287 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1288 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1289 }
1290 foreach id $varccommits($curview,$a) {
1291 lappend displayorder $id
1292 lappend parentlist $parents($curview,$id)
1293 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001294 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001295 set i $r
1296 foreach id $varccommits($curview,$a) {
1297 lset displayorder $i $id
1298 lset parentlist $i $parents($curview,$id)
1299 incr i
1300 }
1301 }
1302 incr r $al
1303 }
1304}
1305
1306proc commitonrow {row} {
1307 global displayorder
1308
1309 set id [lindex $displayorder $row]
1310 if {$id eq {}} {
1311 make_disporder $row [expr {$row + 1}]
1312 set id [lindex $displayorder $row]
1313 }
1314 return $id
1315}
1316
1317proc closevarcs {v} {
1318 global varctok varccommits varcid parents children
Stefan Dotterweichd92aa572016-06-04 10:47:16 +02001319 global cmitlisted commitidx vtokmod curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001320
1321 set missing_parents 0
1322 set scripts {}
1323 set narcs [llength $varctok($v)]
1324 for {set a 1} {$a < $narcs} {incr a} {
1325 set id [lindex $varccommits($v,$a) end]
1326 foreach p $parents($v,$id) {
1327 if {[info exists varcid($v,$p)]} continue
1328 # add p as a new commit
1329 incr missing_parents
1330 set cmitlisted($v,$p) 0
1331 set parents($v,$p) {}
1332 if {[llength $children($v,$p)] == 1 &&
1333 [llength $parents($v,$id)] == 1} {
1334 set b $a
1335 } else {
1336 set b [newvarc $v $p]
1337 }
1338 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001339 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1340 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001341 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001342 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001343 incr commitidx($v)
Stefan Dotterweichd92aa572016-06-04 10:47:16 +02001344 if {$v == $curview} {
1345 set numcommits $commitidx($v)
1346 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001347 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001348 }
1349 }
1350 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001351 foreach s $scripts {
1352 eval $s
1353 }
1354 }
1355}
1356
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001357# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1358# Assumes we already have an arc for $rwid.
1359proc rewrite_commit {v id rwid} {
1360 global children parents varcid varctok vtokmod varccommits
1361
1362 foreach ch $children($v,$id) {
1363 # make $rwid be $ch's parent in place of $id
1364 set i [lsearch -exact $parents($v,$ch) $id]
1365 if {$i < 0} {
1366 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1367 }
1368 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1369 # add $ch to $rwid's children and sort the list if necessary
1370 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1371 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1372 $children($v,$rwid)]
1373 }
1374 # fix the graph after joining $id to $rwid
1375 set a $varcid($v,$ch)
1376 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001377 # parentlist is wrong for the last element of arc $a
1378 # even if displayorder is right, hence the 3rd arg here
1379 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001380 }
1381}
1382
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001383# Mechanism for registering a command to be executed when we come
1384# across a particular commit. To handle the case when only the
1385# prefix of the commit is known, the commitinterest array is now
1386# indexed by the first 4 characters of the ID. Each element is a
1387# list of id, cmd pairs.
1388proc interestedin {id cmd} {
1389 global commitinterest
1390
1391 lappend commitinterest([string range $id 0 3]) $id $cmd
1392}
1393
1394proc check_interest {id scripts} {
1395 global commitinterest
1396
1397 set prefix [string range $id 0 3]
1398 if {[info exists commitinterest($prefix)]} {
1399 set newlist {}
1400 foreach {i script} $commitinterest($prefix) {
1401 if {[string match "$i*" $id]} {
1402 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1403 } else {
1404 lappend newlist $i $script
1405 }
1406 }
1407 if {$newlist ne {}} {
1408 set commitinterest($prefix) $newlist
1409 } else {
1410 unset commitinterest($prefix)
1411 }
1412 }
1413 return $scripts
1414}
1415
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001416proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001417 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001418 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001419 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001420 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001421 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001422
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001423 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001424 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001425 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001426 set stuff "\0"
1427 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001428 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001429 if {![eof $fd]} {
1430 return 1
1431 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001432 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001433 global viewinstances
1434 unset commfd($inst)
1435 set i [lsearch -exact $viewinstances($view) $inst]
1436 if {$i >= 0} {
1437 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001438 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001439 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001440 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001441 if {[catch {close $fd} err]} {
1442 set fv {}
1443 if {$view != $curview} {
1444 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001445 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001446 if {[string range $err 0 4] == "usage"} {
1447 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001448 bad arguments to git log."
Marc Branchaud5ee1c992015-04-07 11:53:37 -04001449 if {$viewname($view) eq [mc "Command line"]} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001450 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001451 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001452 to allow selection of commits to be displayed.)"
1453 }
1454 } else {
1455 set err "Error reading commits$fv: $err"
1456 }
1457 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001458 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001459 if {[incr viewactive($view) -1] <= 0} {
1460 set viewcomplete($view) 1
1461 # Check if we have seen any ids listed as parents that haven't
1462 # appeared in the list
1463 closevarcs $view
1464 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001465 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001466 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001467 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001468 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001469 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001470 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001471 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001472 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001473 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001474 while 1 {
1475 set i [string first "\0" $stuff $start]
1476 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001477 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001478 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001479 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001480 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001481 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001482 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001483 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001484 } else {
1485 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001486 }
1487 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001488 set j [string first "\n" $cmit]
1489 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001490 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001491 if {$j >= 0 && [string match "commit *" $cmit]} {
1492 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001493 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001494 switch -- [string index $ids 0] {
1495 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001496 "^" {set listed 2}
1497 "<" {set listed 3}
1498 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001499 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001500 set ids [string range $ids 1 end]
1501 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001502 set ok 1
1503 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001504 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001505 set ok 0
1506 break
1507 }
1508 }
1509 }
1510 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001511 set shortcmit $cmit
1512 if {[string length $shortcmit] > 80} {
1513 set shortcmit "[string range $shortcmit 0 80]..."
1514 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001515 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001516 exit 1
1517 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001518 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001519 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001520
Paul Mackerras22387f22012-03-19 11:21:08 +11001521 lappend vshortids($view,[string range $id 0 3]) $id
1522
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001523 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001524 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001525 # git log doesn't rewrite parents for unlisted commits
1526 # when doing path limiting, so work around that here
1527 # by working out the rewritten parent with git rev-list
1528 # and if we already know about it, using the rewritten
1529 # parent as a substitute parent for $id's children.
1530 if {![catch {
1531 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001532 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001533 }]} {
1534 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1535 # use $rwid in place of $id
1536 rewrite_commit $view $id $rwid
1537 continue
1538 }
1539 }
1540 }
1541
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001542 set a 0
1543 if {[info exists varcid($vid)]} {
1544 if {$cmitlisted($vid) || !$listed} continue
1545 set a $varcid($vid)
1546 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001547 if {$listed} {
1548 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001549 } else {
1550 set olds {}
1551 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001552 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001553 set cmitlisted($vid) $listed
1554 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001555 if {![info exists children($vid)]} {
1556 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001557 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001558 set k [lindex $children($vid) 0]
1559 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001560 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001561 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1562 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001563 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001564 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001565 if {$a == 0} {
1566 # new arc
1567 set a [newvarc $view $id]
1568 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001569 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1570 modify_arc $view $a
1571 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001572 if {![info exists varcid($vid)]} {
1573 set varcid($vid) $a
1574 lappend varccommits($view,$a) $id
1575 incr commitidx($view)
1576 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001577
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001578 set i 0
1579 foreach p $olds {
1580 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1581 set vp $view,$p
1582 if {[llength [lappend children($vp) $id]] > 1 &&
1583 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1584 set children($vp) [lsort -command [list vtokcmp $view] \
1585 $children($vp)]
Paul Mackerras009409f2015-05-02 20:53:36 +10001586 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001587 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001588 if {[info exists varcid($view,$p)]} {
1589 fix_reversal $p $a $view
1590 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001591 }
1592 incr i
1593 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001594
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001595 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001596 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001597 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001598 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001599 global numcommits hlview
1600
1601 if {$view == $curview} {
1602 set numcommits $commitidx($view)
1603 run chewcommits
1604 }
1605 if {[info exists hlview] && $view == $hlview} {
1606 # we never actually get here...
1607 run vhighlightmore
1608 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001609 foreach s $scripts {
1610 eval $s
1611 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001612 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001613 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001614}
1615
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001616proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001617 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001618 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001619
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001620 layoutmore
1621 if {$viewcomplete($curview)} {
1622 global commitidx varctok
1623 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001624
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001625 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001626 update
1627 reset_pending_select {}
1628
1629 if {[commitinview $pending_select $curview]} {
1630 selectline [rowofcommit $pending_select] 1
1631 } else {
1632 set row [first_real_row]
1633 selectline $row 1
1634 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001635 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001636 if {$commitidx($curview) > 0} {
1637 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1638 #puts "overall $ms ms for $numcommits commits"
1639 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1640 } else {
1641 show_status [mc "No commits selected"]
1642 }
1643 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001644 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001645 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001646}
1647
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001648proc do_readcommit {id} {
1649 global tclencoding
1650
1651 # Invoke git-log to handle automatic encoding conversion
1652 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1653 # Read the results using i18n.logoutputencoding
1654 fconfigure $fd -translation lf -eofchar {}
1655 if {$tclencoding != {}} {
1656 fconfigure $fd -encoding $tclencoding
1657 }
1658 set contents [read $fd]
1659 close $fd
1660 # Remove the heading line
1661 regsub {^commit [0-9a-f]+\n} $contents {} contents
1662
1663 return $contents
1664}
1665
Paul Mackerras1db95b02005-05-09 04:08:39 +00001666proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001667 if {[catch {set contents [do_readcommit $id]}]} return
1668 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001669}
1670
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001671proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001672 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001673
1674 set inhdr 1
1675 set comment {}
1676 set headline {}
1677 set auname {}
1678 set audate {}
1679 set comname {}
1680 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001681 set hdrend [string first "\n\n" $contents]
1682 if {$hdrend < 0} {
1683 # should never happen...
1684 set hdrend [string length $contents]
1685 }
1686 set header [string range $contents 0 [expr {$hdrend - 1}]]
1687 set comment [string range $contents [expr {$hdrend + 2}] end]
1688 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001689 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001690 set tag [lindex $line 0]
1691 if {$tag == "author"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001692 set audate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001693 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001694 } elseif {$tag == "committer"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001695 set comdate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001696 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001697 }
1698 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001699 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001700 # take the first non-blank line of the comment as the headline
1701 set headline [string trimleft $comment]
1702 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001703 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001704 set headline [string range $headline 0 $i]
1705 }
1706 set headline [string trimright $headline]
1707 set i [string first "\r" $headline]
1708 if {$i >= 0} {
1709 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001710 }
1711 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001712 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001713 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001714 set newcomment {}
1715 foreach line [split $comment "\n"] {
1716 append newcomment " "
1717 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001718 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001719 }
1720 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001721 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001722 set hasnote [string first "\nNotes:\n" $contents]
Thomas Rastb449eb22013-11-16 18:37:42 +01001723 set diff ""
1724 # If there is diff output shown in the git-log stream, split it
1725 # out. But get rid of the empty line that always precedes the
1726 # diff.
1727 set i [string first "\n\ndiff" $comment]
1728 if {$i >= 0} {
1729 set diff [string range $comment $i+1 end]
1730 set comment [string range $comment 0 $i-1]
1731 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001732 set commitinfo($id) [list $headline $auname $audate \
Thomas Rastb449eb22013-11-16 18:37:42 +01001733 $comname $comdate $comment $hasnote $diff]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001734}
1735
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001736proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001737 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001738
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001739 if {[info exists commitdata($id)]} {
1740 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001741 } else {
1742 readcommit $id
1743 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001744 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001745 }
1746 }
1747 return 1
1748}
1749
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001750# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1751# and are present in the current view.
1752# This is fairly slow...
1753proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001754 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001755
1756 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001757 if {[string length $prefix] >= 4} {
1758 set vshortid $curview,[string range $prefix 0 3]
1759 if {[info exists vshortids($vshortid)]} {
1760 foreach id $vshortids($vshortid) {
1761 if {[string match "$prefix*" $id]} {
1762 if {[lsearch -exact $ids $id] < 0} {
1763 lappend ids $id
1764 if {[llength $ids] >= 2} break
1765 }
1766 }
1767 }
1768 }
1769 } else {
1770 foreach match [array names varcid "$curview,$prefix*"] {
1771 lappend ids [lindex [split $match ","] 1]
1772 if {[llength $ids] >= 2} break
1773 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001774 }
1775 return $ids
1776}
1777
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001778proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001779 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001780 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001781 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001782 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001783
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001784 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
Paul Mackerras009409f2015-05-02 20:53:36 +10001785 unset -nocomplain $v
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001786 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001787 set refd [open [list | git show-ref -d] r]
1788 while {[gets $refd line] >= 0} {
1789 if {[string index $line 40] ne " "} continue
1790 set id [string range $line 0 39]
1791 set ref [string range $line 41 end]
1792 if {![string match "refs/*" $ref]} continue
1793 set name [string range $ref 5 end]
1794 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001795 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001796 set headids($name) $id
1797 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001798 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001799 } elseif {[string match "heads/*" $name]} {
1800 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001801 set headids($name) $id
1802 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001803 } elseif {[string match "tags/*" $name]} {
1804 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1805 # which is what we want since the former is the commit ID
1806 set name [string range $name 5 end]
1807 if {[string match "*^{}" $name]} {
1808 set name [string range $name 0 end-3]
1809 } else {
1810 set tagobjid($name) $id
1811 }
1812 set tagids($name) $id
1813 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001814 } else {
1815 set otherrefids($name) $id
1816 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001817 }
1818 }
Alex Riesen062d6712007-07-29 22:28:40 +02001819 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001820 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001821 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001822 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001823 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001824 set thehead [exec git symbolic-ref HEAD]
1825 if {[string match "refs/heads/*" $thehead]} {
1826 set mainhead [string range $thehead 11 end]
1827 }
1828 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001829 set selectheadid {}
1830 if {$selecthead ne {}} {
1831 catch {
1832 set selectheadid [exec git rev-parse --verify $selecthead]
1833 }
1834 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001835}
1836
Paul Mackerras8f489362007-07-13 19:49:37 +10001837# skip over fake commits
1838proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001839 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001840
1841 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001842 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001843 if {$id ne $nullid && $id ne $nullid2} {
1844 break
1845 }
1846 }
1847 return $row
1848}
1849
Paul Mackerrase11f1232007-06-16 20:29:25 +10001850# update things for a head moved to a child of its previous location
1851proc movehead {id name} {
1852 global headids idheads
1853
1854 removehead $headids($name) $name
1855 set headids($name) $id
1856 lappend idheads($id) $name
1857}
1858
1859# update things when a head has been removed
1860proc removehead {id name} {
1861 global headids idheads
1862
1863 if {$idheads($id) eq $name} {
1864 unset idheads($id)
1865 } else {
1866 set i [lsearch -exact $idheads($id) $name]
1867 if {$i >= 0} {
1868 set idheads($id) [lreplace $idheads($id) $i $i]
1869 }
1870 }
1871 unset headids($name)
1872}
1873
Pat Thoytsd93f1712009-04-17 01:24:35 +01001874proc ttk_toplevel {w args} {
1875 global use_ttk
1876 eval [linsert $args 0 ::toplevel $w]
1877 if {$use_ttk} {
1878 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1879 }
1880 return $w
1881}
1882
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001883proc make_transient {window origin} {
1884 global have_tk85
1885
1886 # In MacOS Tk 8.4 transient appears to work by setting
1887 # overrideredirect, which is utterly useless, since the
1888 # windows get no border, and are not even kept above
1889 # the parent.
1890 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1891
1892 wm transient $window $origin
1893
1894 # Windows fails to place transient windows normally, so
1895 # schedule a callback to center them on the parent.
1896 if {[tk windowingsystem] eq {win32}} {
1897 after idle [list tk::PlaceWindow $window widget $origin]
1898 }
1899}
1900
Alex Henrieef87a482015-05-11 13:26:41 -06001901proc show_error {w top msg} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001902 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001903 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001904 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001905 message $w.m -text $msg -justify center -aspect 400
1906 pack $w.m -side top -fill x -padx 20 -pady 20
Alex Henrieef87a482015-05-11 13:26:41 -06001907 ${NS}::button $w.ok -default active -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001908 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001909 bind $top <Visibility> "grab $top; focus $top"
1910 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001911 bind $top <Key-space> "destroy $top"
1912 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001913 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001914}
1915
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001916proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001917 if {[tk windowingsystem] eq "win32"} {
1918 tk_messageBox -icon error -type ok -title [wm title .] \
1919 -parent $owner -message $msg
1920 } else {
1921 set w .error
1922 ttk_toplevel $w
1923 make_transient $w $owner
1924 show_error $w $w $msg
1925 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001926}
1927
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001928proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001929 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001930 set confirm_ok 0
1931 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001932 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001933 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001934 message $w.m -text $msg -justify center -aspect 400
1935 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001936 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001937 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001938 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001939 pack $w.cancel -side right -fill x
1940 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001941 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1942 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1943 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001944 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001945 tkwait window $w
1946 return $confirm_ok
1947}
1948
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001949proc setoptions {} {
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001950 global use_ttk
1951
Pat Thoytsd93f1712009-04-17 01:24:35 +01001952 if {[tk windowingsystem] ne "win32"} {
1953 option add *Panedwindow.showHandle 1 startupFile
1954 option add *Panedwindow.sashRelief raised startupFile
1955 if {[tk windowingsystem] ne "aqua"} {
1956 option add *Menu.font uifont startupFile
1957 }
1958 } else {
1959 option add *Menu.TearOff 0 startupFile
1960 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001961 option add *Button.font uifont startupFile
1962 option add *Checkbutton.font uifont startupFile
1963 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001964 option add *Menubutton.font uifont startupFile
1965 option add *Label.font uifont startupFile
1966 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001967 option add *Entry.font textfont startupFile
1968 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001969 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001970 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001971 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001972}
1973
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001974proc setttkstyle {} {
1975 eval font configure TkDefaultFont [fontflags mainfont]
1976 eval font configure TkTextFont [fontflags textfont]
1977 eval font configure TkHeadingFont [fontflags mainfont]
1978 eval font configure TkCaptionFont [fontflags mainfont] -weight bold
1979 eval font configure TkTooltipFont [fontflags uifont]
1980 eval font configure TkFixedFont [fontflags textfont]
1981 eval font configure TkIconFont [fontflags uifont]
1982 eval font configure TkMenuFont [fontflags uifont]
1983 eval font configure TkSmallCaptionFont [fontflags uifont]
1984}
1985
Paul Mackerras79056032008-10-18 16:24:46 +11001986# Make a menu and submenus.
1987# m is the window name for the menu, items is the list of menu items to add.
1988# Each item is a list {mc label type description options...}
1989# mc is ignored; it's so we can put mc there to alert xgettext
1990# label is the string that appears in the menu
1991# type is cascade, command or radiobutton (should add checkbutton)
1992# description depends on type; it's the sublist for cascade, the
1993# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001994proc makemenu {m items} {
1995 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001996 if {[tk windowingsystem] eq {aqua}} {
1997 set Meta1 Cmd
1998 } else {
1999 set Meta1 Ctrl
2000 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002001 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11002002 set name [mc [lindex $i 1]]
2003 set type [lindex $i 2]
2004 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002005 set params [list $type]
2006 if {$name ne {}} {
2007 set u [string first "&" [string map {&& x} $name]]
2008 lappend params -label [string map {&& & & {}} $name]
2009 if {$u >= 0} {
2010 lappend params -underline $u
2011 }
2012 }
2013 switch -- $type {
2014 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11002015 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002016 lappend params -menu $m.$submenu
2017 }
2018 "command" {
2019 lappend params -command $thing
2020 }
2021 "radiobutton" {
2022 lappend params -variable [lindex $thing 0] \
2023 -value [lindex $thing 1]
2024 }
2025 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002026 set tail [lrange $i 4 end]
2027 regsub -all {\yMeta1\y} $tail $Meta1 tail
2028 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002029 if {$type eq "cascade"} {
2030 makemenu $m.$submenu $thing
2031 }
2032 }
2033}
2034
2035# translate string and remove ampersands
2036proc mca {str} {
2037 return [string map {&& & & {}} [mc $str]]
2038}
2039
Paul Mackerras39c12692013-05-11 17:08:41 +10002040proc cleardropsel {w} {
2041 $w selection clear
2042}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002043proc makedroplist {w varname args} {
2044 global use_ttk
2045 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002046 set width 0
2047 foreach label $args {
2048 set cx [string length $label]
2049 if {$cx > $width} {set width $cx}
2050 }
2051 set gm [ttk::combobox $w -width $width -state readonly\
Paul Mackerras39c12692013-05-11 17:08:41 +10002052 -textvariable $varname -values $args \
2053 -exportselection false]
2054 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002055 } else {
2056 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
2057 }
2058 return $gm
2059}
2060
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002061proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002062 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002063 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002064 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002065 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002066 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002067 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002068 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002069 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002070 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002071 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04002072 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002073 global uifgcolor uifgdisabledcolor
2074 global filesepbgcolor filesepfgcolor
2075 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002076 global headctxmenu progresscanv progressitem progresscoords statusw
2077 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002078 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002079 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002080 global git_version
2081 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002082
Paul Mackerras79056032008-10-18 16:24:46 +11002083 # The "mc" arguments here are purely so that xgettext
2084 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002085 set file {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002086 mc "&File" cascade {
2087 {mc "&Update" command updatecommits -accelerator F5}
2088 {mc "&Reload" command reloadcommits -accelerator Shift-F5}
2089 {mc "Reread re&ferences" command rereadrefs}
2090 {mc "&List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002091 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002092 {mc "Start git &gui" command {exec git gui &}}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002093 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002094 {mc "&Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002095 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002096 set edit {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002097 mc "&Edit" cascade {
2098 {mc "&Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002099 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002100 set view {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002101 mc "&View" cascade {
2102 {mc "&New view..." command {newview 0} -accelerator Shift-F4}
2103 {mc "&Edit view..." command editview -state disabled -accelerator F4}
2104 {mc "&Delete view" command delview -state disabled}
Paul Mackerras79056032008-10-18 16:24:46 +11002105 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002106 {mc "&All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002107 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002108 if {[tk windowingsystem] ne "aqua"} {
2109 set help {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002110 mc "&Help" cascade {
2111 {mc "&About gitk" command about}
2112 {mc "&Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002113 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002114 set bar [list $file $edit $view $help]
2115 } else {
2116 proc ::tk::mac::ShowPreferences {} {doprefs}
2117 proc ::tk::mac::Quit {} {doquit}
2118 lset file end [lreplace [lindex $file end] end-1 end]
2119 set apple {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002120 xx "&Apple" cascade {
2121 {mc "&About gitk" command about}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002122 {xx "" separator}
2123 }}
2124 set help {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002125 mc "&Help" cascade {
2126 {mc "&Key bindings" command keys}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002127 }}
2128 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002129 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002130 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002131 . configure -menu .bar
2132
Pat Thoytsd93f1712009-04-17 01:24:35 +01002133 if {$use_ttk} {
2134 # cover the non-themed toplevel with a themed frame.
2135 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2136 }
2137
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002138 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002139 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002140
2141 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002142 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002143 set geometry(topheight) [expr {15 * $linespc}]
2144 set geometry(topwidth) [expr {80 * $charspc}]
2145 set geometry(botheight) [expr {15 * $linespc}]
2146 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002147 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2148 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002149 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002150
2151 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
Pat Thoytsd93f1712009-04-17 01:24:35 +01002152 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2153 ${NS}::frame .tf.histframe
2154 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2155 if {!$use_ttk} {
2156 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
2157 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002158
2159 # create three canvases
2160 set cscroll .tf.histframe.csb
2161 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002162 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04002163 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002164 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002165 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002166 .tf.histframe.pwclist add $canv
2167 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002168 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002169 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002170 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002171 .tf.histframe.pwclist add $canv2
2172 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002173 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002174 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002175 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002176 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002177 if {$use_ttk} {
2178 bind .tf.histframe.pwclist <Map> {
2179 bind %W <Map> {}
2180 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2181 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2182 }
2183 } else {
2184 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2185 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
2186 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002187
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002188 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002189 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2190 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002191 pack $cscroll -side right -fill y
2192 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2193 lappend bglist $canv $canv2 $canv3
2194 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2195
2196 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002197 ${NS}::frame .tf.bar
2198 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002199
2200 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002201 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002202 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002203 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002204 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002205 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002206 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002207 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002208 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002209 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002210
Stefan Hallerf062e502012-09-22 09:46:48 +02002211 set bm_left_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002212 #define left_width 16
2213 #define left_height 16
2214 static unsigned char left_bits[] = {
2215 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2216 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2217 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2218 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002219 set bm_right_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002220 #define right_width 16
2221 #define right_height 16
2222 static unsigned char right_bits[] = {
2223 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2224 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2225 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2226 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002227 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2228 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2229 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2230 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002231
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002232 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2233 if {$use_ttk} {
2234 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
2235 } else {
2236 .tf.bar.leftbut configure -image bm-left
2237 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002238 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002239 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2240 if {$use_ttk} {
2241 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
2242 } else {
2243 .tf.bar.rightbut configure -image bm-right
2244 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002245 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002246
Pat Thoytsd93f1712009-04-17 01:24:35 +01002247 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002248 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002249 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Paul Mackerras6df74032008-05-11 22:13:02 +10002250 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002251 ${NS}::label .tf.bar.rowlabel2 -text "/"
2252 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Paul Mackerras6df74032008-05-11 22:13:02 +10002253 -relief sunken -anchor e
2254 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2255 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002256 if {!$use_ttk} {
2257 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2258 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002259 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002260 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002261
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002262 # Status label and progress bar
2263 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002264 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002265 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002266 if {$use_ttk} {
2267 set progresscanv [ttk::progressbar .tf.bar.progress]
2268 } else {
2269 set h [expr {[font metrics uifont -linespace] + 2}]
2270 set progresscanv .tf.bar.progress
2271 canvas $progresscanv -relief sunken -height $h -borderwidth 2
Paul Mackerras6e8fda52016-12-12 11:29:21 +11002272 set progressitem [$progresscanv create rect -1 0 0 $h -fill "#00ff00"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002273 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2274 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
2275 }
2276 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002277 set progresscoords {0 0}
2278 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002279 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002280 bind $progresscanv <Configure> adjustprogress
2281 set lastprogupdate [clock clicks -milliseconds]
2282 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002283
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002284 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002285 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002286
2287 set bm_down_data {
2288 #define down_width 16
2289 #define down_height 16
2290 static unsigned char down_bits[] = {
2291 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2292 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2293 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
2294 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
2295 }
2296 image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
2297 ${NS}::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
2298 .tf.lbar.fnext configure -image bm-down
2299
2300 set bm_up_data {
2301 #define up_width 16
2302 #define up_height 16
2303 static unsigned char up_bits[] = {
2304 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
2305 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
2306 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2307 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
2308 }
2309 image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
2310 ${NS}::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
2311 .tf.lbar.fprev configure -image bm-up
2312
Pat Thoytsd93f1712009-04-17 01:24:35 +01002313 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002314
Paul Mackerras687c8762007-09-22 12:49:33 +10002315 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2316 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002317 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002318 set gm [makedroplist .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002319 [mc "containing:"] \
2320 [mc "touching paths:"] \
Martin Langhoffc33cb902012-06-14 20:34:11 +02002321 [mc "adding/removing string:"] \
2322 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002323 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002324 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002325
2326 set findstring {}
2327 set fstring .tf.lbar.findstring
2328 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002329 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002330 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002331 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002332 set findtypemenu [makedroplist .tf.lbar.findtype \
2333 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002334 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002335 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002336 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002337 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002338 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002339 pack .tf.lbar.findloc -side right
2340 pack .tf.lbar.findtype -side right
2341 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002342
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002343 # Finish putting the upper half of the viewer together
2344 pack .tf.lbar -in .tf -side bottom -fill x
2345 pack .tf.bar -in .tf -side bottom -fill x
2346 pack .tf.histframe -fill both -side top -expand 1
2347 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002348 if {!$use_ttk} {
2349 .ctop paneconfigure .tf -height $geometry(topheight)
2350 .ctop paneconfigure .tf -width $geometry(topwidth)
2351 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002352
2353 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002354 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002355
2356 # lower left, a text box over search bar, scroll bar to the right
2357 # if we know window height, then that will set the lower text height, otherwise
2358 # we set lower text height which will drive window height
2359 if {[info exists geometry(main)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002360 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002361 } else {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002362 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002363 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002364 ${NS}::frame .bleft.top
2365 ${NS}::frame .bleft.mid
2366 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002367
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002368 # gap between sub-widgets
2369 set wgap [font measure uifont "i"]
2370
Pat Thoytsd93f1712009-04-17 01:24:35 +01002371 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002372 pack .bleft.top.search -side left -padx 5
2373 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002374 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002375 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002376 lappend entries $sstring
2377 trace add variable searchstring write incrsearch
2378 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002379 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002380 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002381 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002382 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002383 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002384 -command changediffdisp -variable diffelide -value {1 0}
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002385
Pat Thoytsd93f1712009-04-17 01:24:35 +01002386 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002387 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left -ipadx $wgap
Mark Hills0933b042010-01-13 20:40:19 +00002388 spinbox .bleft.mid.diffcontext -width 5 \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002389 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002390 -validate all -validatecommand "diffcontextvalidate %P" \
2391 -textvariable diffcontextstring
2392 .bleft.mid.diffcontext set $diffcontext
2393 trace add variable diffcontextstring write diffcontextchange
2394 lappend entries .bleft.mid.diffcontext
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002395 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left -ipadx $wgap
Pat Thoytsd93f1712009-04-17 01:24:35 +01002396 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002397 -command changeignorespace -variable ignorespace
2398 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002399
2400 set worddiff [mc "Line diff"]
2401 if {[package vcompare $git_version "1.7.2"] >= 0} {
2402 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2403 [mc "Markup words"] [mc "Color words"]
2404 trace add variable worddiff write changeworddiff
2405 pack .bleft.mid.worddiff -side left -padx 5
2406 }
2407
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002408 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002409 text $ctext -background $bgcolor -foreground $fgcolor \
Markus Hitter106a6d92016-11-06 20:38:03 +01002410 -state disabled -undo 0 -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002411 -yscrollcommand scrolltext -wrap none \
2412 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002413 if {$have_tk85} {
2414 $ctext conf -tabstyle wordprocessor
2415 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002416 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2417 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002418 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002419 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002420 grid $ctext .bleft.bottom.sb -sticky nsew
2421 grid .bleft.bottom.sbhorizontal -sticky ew
2422 grid columnconfigure .bleft.bottom 0 -weight 1
2423 grid rowconfigure .bleft.bottom 0 -weight 1
2424 grid rowconfigure .bleft.bottom 1 -weight 0
2425 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002426 lappend bglist $ctext
2427 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002428
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002429 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002430 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002431 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2432 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002433 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002434 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2435 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2436 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2437 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2438 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2439 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2440 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2441 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2442 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2443 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2444 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2445 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2446 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2447 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2448 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2449 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002450 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002451 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002452 $ctext tag conf mresult -font textfontbold
2453 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002454 $ctext tag conf found -back $foundbgcolor
2455 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerras76d64ca2014-01-23 22:06:22 +11002456 $ctext tag conf wwrap -wrap word -lmargin2 1c
Paul Mackerras4399fe32013-01-03 10:10:31 +11002457 $ctext tag conf bold -font textfontbold
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002458
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002459 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002460 if {!$use_ttk} {
2461 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
2462 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002463
2464 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002465 ${NS}::frame .bright
2466 ${NS}::frame .bright.mode
2467 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002468 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002469 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002470 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002471 grid .bright.mode.patch .bright.mode.tree -sticky ew
2472 pack .bright.mode -side top -fill x
2473 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002474 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002475 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002476 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002477 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002478 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002479 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002480 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002481 -cursor [. cget -cursor] \
2482 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002483 lappend bglist $cflist
2484 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002485 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002486 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002487 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002488 $cflist tag configure highlight \
2489 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002490 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002491
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002492 .pwbottom add .bright
2493 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002494
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002495 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002496 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002497 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2498 if {$w > [winfo screenwidth .]} {
2499 set w [winfo screenwidth .]
2500 }
2501 if {$h > [winfo screenheight .]} {
2502 set h [winfo screenheight .]
2503 }
2504 wm geometry . "${w}x$h"
2505 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002506 }
2507
Pat Thoytsc876dba2009-04-14 22:09:53 +01002508 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2509 wm state . $geometry(state)
2510 }
2511
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002512 if {[tk windowingsystem] eq {aqua}} {
2513 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002514 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002515 } else {
2516 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002517 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002518 }
2519
Pat Thoytsd93f1712009-04-17 01:24:35 +01002520 if {$use_ttk} {
2521 bind .ctop <Map> {
2522 bind %W <Map> {}
2523 %W sashpos 0 $::geometry(topheight)
2524 }
2525 bind .pwbottom <Map> {
2526 bind %W <Map> {}
2527 %W sashpos 0 $::geometry(botwidth)
2528 }
2529 }
2530
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002531 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2532 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002533 bindall <1> {selcanvline %W %x %y}
2534 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002535 if {[tk windowingsystem] == "win32"} {
2536 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2537 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2538 } else {
2539 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2540 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Gabriele Mazzotta122b8072014-11-15 15:05:06 +01002541 bind $ctext <Button> {
2542 if {"%b" eq 6} {
2543 $ctext xview scroll -5 units
2544 } elseif {"%b" eq 7} {
2545 $ctext xview scroll 5 units
2546 }
2547 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002548 if {[tk windowingsystem] eq "aqua"} {
2549 bindall <MouseWheel> {
2550 set delta [expr {- (%D)}]
2551 allcanvs yview scroll $delta units
2552 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002553 bindall <Shift-MouseWheel> {
2554 set delta [expr {- (%D)}]
2555 $canv xview scroll $delta units
2556 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002557 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002558 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002559 bindall <$::BM> "canvscan mark %W %x %y"
2560 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002561 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2562 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002563 bindkey <Home> selfirstline
2564 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002565 bind . <Key-Up> "selnextline -1"
2566 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002567 bind . <Shift-Key-Up> "dofind -1 0"
2568 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002569 bindkey <Key-Right> "goforw"
2570 bindkey <Key-Left> "goback"
2571 bind . <Key-Prior> "selnextpage -1"
2572 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002573 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2574 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2575 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2576 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2577 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2578 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002579 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2580 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2581 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002582 bindkey p "selnextline -1"
2583 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002584 bindkey z "goback"
2585 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002586 bindkey k "selnextline -1"
2587 bindkey j "selnextline 1"
2588 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002589 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002590 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002591 bindkey d "$ctext yview scroll 18 units"
2592 bindkey u "$ctext yview scroll -18 units"
Ismael Luceno0deb5c92015-04-15 13:18:17 -03002593 bindkey g {$sha1entry delete 0 end; focus $sha1entry}
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002594 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002595 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002596 bindkey <Key-Return> {dofind 1 1}
2597 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002598 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002599 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002600 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002601 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002602 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002603 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002604 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002605 bind . <$M1B-f> {dofind 1 1}
2606 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002607 bind . <$M1B-r> dosearchback
2608 bind . <$M1B-s> dosearch
2609 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002610 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002611 bind . <$M1B-KP_Add> {incrfont 1}
2612 bind . <$M1B-minus> {incrfont -1}
2613 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002614 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002615 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002616 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002617 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002618 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002619 bind $sha1entry <<PasteSelection>> clearsha1
Ilya Bobyrada2ea12014-03-20 01:58:51 -07002620 bind $sha1entry <<Paste>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002621 bind $cflist <1> {sel_flist %W %x %y; break}
2622 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002623 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002624 global ctxbut
2625 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002626 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002627 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002628 bind $ctext <<Selection>> rehighlight_search_results
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002629 for {set i 1} {$i < 10} {incr i} {
2630 bind . <$M1B-Key-$i> [list go_to_parent $i]
2631 }
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002632
2633 set maincursor [. cget -cursor]
2634 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002635 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002636
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002637 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002638 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002639 {mc "Diff this -> selected" command {diffvssel 0}}
2640 {mc "Diff selected -> this" command {diffvssel 1}}
2641 {mc "Make patch" command mkpatch}
2642 {mc "Create tag" command mktag}
Beat Bollid835dbb2015-07-18 13:15:39 +02002643 {mc "Copy commit summary" command copysummary}
Paul Mackerras79056032008-10-18 16:24:46 +11002644 {mc "Write commit to file" command writecommit}
2645 {mc "Create new branch" command mkbranch}
2646 {mc "Cherry-pick this commit" command cherrypick}
2647 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002648 {mc "Mark this commit" command markhere}
2649 {mc "Return to mark" command gotomark}
2650 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002651 {mc "Compare with marked commit" command compare_commits}
Paul Mackerras6febded2012-03-23 22:07:27 +11002652 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2653 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Knut Franke8f3ff932013-04-27 16:36:13 +02002654 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002655 }
2656 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002657
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002658 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002659 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002660 {mc "Diff this -> selected" command {diffvssel 0}}
2661 {mc "Diff selected -> this" command {diffvssel 1}}
2662 {mc "Make patch" command mkpatch}
Paul Mackerras6febded2012-03-23 22:07:27 +11002663 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2664 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002665 }
2666 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002667
Paul Mackerras10299152006-08-02 09:52:01 +10002668 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002669 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002670 {mc "Check out this branch" command cobranch}
Rogier Goossens5a046c52016-03-19 19:32:16 +01002671 {mc "Rename this branch" command mvbranch}
Paul Mackerras79056032008-10-18 16:24:46 +11002672 {mc "Remove this branch" command rmbranch}
Michael Rappazzo427cf162015-05-07 22:29:20 -04002673 {mc "Copy branch name" command {clipboard clear; clipboard append $headmenuhead}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002674 }
2675 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002676
2677 global flist_menu
2678 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002679 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002680 {mc "Highlight this too" command {flist_hl 0}}
2681 {mc "Highlight this only" command {flist_hl 1}}
2682 {mc "External diff" command {external_diff}}
2683 {mc "Blame parent commit" command {external_blame 1}}
Michael Rappazzo427cf162015-05-07 22:29:20 -04002684 {mc "Copy path" command {clipboard clear; clipboard append $flist_menu_file}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002685 }
2686 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002687
2688 global diff_menu
2689 set diff_menu .diffctxmenu
2690 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002691 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002692 {mc "Run git gui blame on this line" command {external_blame_diff}}
2693 }
2694 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002695}
2696
Mark Levedahl314c3092007-08-07 21:40:35 -04002697# Windows sends all mouse wheel events to the current focused window, not
2698# the one where the mouse hovers, so bind those events here and redirect
2699# to the correct window
2700proc windows_mousewheel_redirector {W X Y D} {
2701 global canv canv2 canv3
2702 set w [winfo containing -displayof $W $X $Y]
2703 if {$w ne ""} {
2704 set u [expr {$D < 0 ? 5 : -5}]
2705 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2706 allcanvs yview scroll $u units
2707 } else {
2708 catch {
2709 $w yview scroll $u units
2710 }
2711 }
2712 }
2713}
2714
Paul Mackerras6df74032008-05-11 22:13:02 +10002715# Update row number label when selectedline changes
2716proc selectedline_change {n1 n2 op} {
2717 global selectedline rownumsel
2718
Paul Mackerras94b4a692008-05-20 20:51:06 +10002719 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002720 set rownumsel {}
2721 } else {
2722 set rownumsel [expr {$selectedline + 1}]
2723 }
2724}
2725
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002726# mouse-2 makes all windows scan vertically, but only the one
2727# the cursor is in scans horizontally
2728proc canvscan {op w x y} {
2729 global canv canv2 canv3
2730 foreach c [list $canv $canv2 $canv3] {
2731 if {$c == $w} {
2732 $c scan $op $x $y
2733 } else {
2734 $c scan $op 0 $y
2735 }
2736 }
2737}
2738
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002739proc scrollcanv {cscroll f0 f1} {
2740 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002741 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002742 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002743}
2744
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002745# when we make a key binding for the toplevel, make sure
2746# it doesn't get triggered when that key is pressed in the
2747# find string entry widget.
2748proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002749 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002750 bind . $ev $script
2751 set escript [bind Entry $ev]
2752 if {$escript == {}} {
2753 set escript [bind Entry <Key>]
2754 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002755 foreach e $entries {
2756 bind $e $ev "$escript; break"
2757 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002758}
2759
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002760proc bindmodfunctionkey {mod n script} {
2761 bind . <$mod-F$n> $script
2762 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2763}
2764
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002765# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002766# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002767proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002768 global ctext entries
2769 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002770 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002771 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002772 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002773}
2774
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002775# Adjust the progress bar for a change in requested extent or canvas size
2776proc adjustprogress {} {
2777 global progresscanv progressitem progresscoords
2778 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002779 global rprogitem rprogcoord use_ttk
2780
2781 if {$use_ttk} {
2782 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2783 return
2784 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002785
2786 set w [expr {[winfo width $progresscanv] - 4}]
2787 set x0 [expr {$w * [lindex $progresscoords 0]}]
2788 set x1 [expr {$w * [lindex $progresscoords 1]}]
2789 set h [winfo height $progresscanv]
2790 $progresscanv coords $progressitem $x0 0 $x1 $h
2791 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002792 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002793 set now [clock clicks -milliseconds]
2794 if {$now >= $lastprogupdate + 100} {
2795 set progupdatepending 0
2796 update
2797 } elseif {!$progupdatepending} {
2798 set progupdatepending 1
2799 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2800 }
2801}
2802
2803proc doprogupdate {} {
2804 global lastprogupdate progupdatepending
2805
2806 if {$progupdatepending} {
2807 set progupdatepending 0
2808 set lastprogupdate [clock clicks -milliseconds]
2809 update
2810 }
2811}
2812
Max Kirilloveaf7e832015-03-04 05:58:18 +02002813proc config_check_tmp_exists {tries_left} {
2814 global config_file_tmp
2815
2816 if {[file exists $config_file_tmp]} {
2817 incr tries_left -1
2818 if {$tries_left > 0} {
2819 after 100 [list config_check_tmp_exists $tries_left]
2820 } else {
2821 error_popup "There appears to be a stale $config_file_tmp\
2822 file, which will prevent gitk from saving its configuration on exit.\
2823 Please remove it if it is not being used by any existing gitk process."
2824 }
2825 }
2826}
2827
Max Kirillov995f7922015-03-04 05:58:16 +02002828proc config_init_trace {name} {
2829 global config_variable_changed config_variable_original
2830
2831 upvar #0 $name var
2832 set config_variable_changed($name) 0
2833 set config_variable_original($name) $var
2834}
2835
2836proc config_variable_change_cb {name name2 op} {
2837 global config_variable_changed config_variable_original
2838
2839 upvar #0 $name var
2840 if {$op eq "write" &&
2841 (![info exists config_variable_original($name)] ||
2842 $config_variable_original($name) ne $var)} {
2843 set config_variable_changed($name) 1
2844 }
2845}
2846
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002847proc savestuff {w} {
Max Kirillov9fabefb2014-09-14 23:35:57 +03002848 global stuffsaved
Astril Hayato8f863392014-01-21 19:10:16 +00002849 global config_file config_file_tmp
Max Kirillov995f7922015-03-04 05:58:16 +02002850 global config_variables config_variable_changed
2851 global viewchanged
2852
2853 upvar #0 viewname current_viewname
2854 upvar #0 viewfiles current_viewfiles
2855 upvar #0 viewargs current_viewargs
2856 upvar #0 viewargscmd current_viewargscmd
2857 upvar #0 viewperm current_viewperm
2858 upvar #0 nextviewnum current_nextviewnum
2859 upvar #0 use_ttk current_use_ttk
Paul Mackerras4ef17532005-07-27 22:16:51 -05002860
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002861 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002862 if {![winfo viewable .]} return
Max Kirilloveaf7e832015-03-04 05:58:18 +02002863 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002864 if {[catch {
Max Kirilloveaf7e832015-03-04 05:58:18 +02002865 set try_count 0
2866 while {[catch {set f [open $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2867 if {[incr try_count] > 50} {
2868 error "Unable to write config file: $config_file_tmp exists"
2869 }
2870 after 100
Astril Hayato8f863392014-01-21 19:10:16 +00002871 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002872 set remove_tmp 1
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002873 if {$::tcl_platform(platform) eq {windows}} {
Astril Hayato8f863392014-01-21 19:10:16 +00002874 file attributes $config_file_tmp -hidden true
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002875 }
Max Kirillov995f7922015-03-04 05:58:16 +02002876 if {[file exists $config_file]} {
2877 source $config_file
2878 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002879 foreach var_name $config_variables {
2880 upvar #0 $var_name var
Max Kirillov995f7922015-03-04 05:58:16 +02002881 upvar 0 $var_name old_var
2882 if {!$config_variable_changed($var_name) && [info exists old_var]} {
2883 puts $f [list set $var_name $old_var]
2884 } else {
2885 puts $f [list set $var_name $var]
2886 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002887 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002888
Mark Levedahlb6047c52007-02-08 22:22:24 -05002889 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002890 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002891 puts $f "set geometry(topwidth) [winfo width .tf]"
2892 puts $f "set geometry(topheight) [winfo height .tf]"
Max Kirillov995f7922015-03-04 05:58:16 +02002893 if {$current_use_ttk} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002894 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2895 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2896 } else {
2897 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2898 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2899 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002900 puts $f "set geometry(botwidth) [winfo width .bleft]"
2901 puts $f "set geometry(botheight) [winfo height .bleft]"
2902
Max Kirillov995f7922015-03-04 05:58:16 +02002903 array set view_save {}
2904 array set views {}
2905 if {![info exists permviews]} { set permviews {} }
2906 foreach view $permviews {
2907 set view_save([lindex $view 0]) 1
2908 set views([lindex $view 0]) $view
2909 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002910 puts -nonewline $f "set permviews {"
Max Kirillov995f7922015-03-04 05:58:16 +02002911 for {set v 1} {$v < $current_nextviewnum} {incr v} {
2912 if {$viewchanged($v)} {
2913 if {$current_viewperm($v)} {
2914 set views($current_viewname($v)) [list $current_viewname($v) $current_viewfiles($v) $current_viewargs($v) $current_viewargscmd($v)]
2915 } else {
2916 set view_save($current_viewname($v)) 0
2917 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002918 }
2919 }
Max Kirillov995f7922015-03-04 05:58:16 +02002920 # write old and updated view to their places and append remaining to the end
2921 foreach view $permviews {
2922 set view_name [lindex $view 0]
2923 if {$view_save($view_name)} {
2924 puts $f "{$views($view_name)}"
2925 }
2926 unset views($view_name)
2927 }
2928 foreach view_name [array names views] {
2929 puts $f "{$views($view_name)}"
2930 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002931 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002932 close $f
Astril Hayato8f863392014-01-21 19:10:16 +00002933 file rename -force $config_file_tmp $config_file
Max Kirilloveaf7e832015-03-04 05:58:18 +02002934 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002935 } err]} {
2936 puts "Error saving config: $err"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002937 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002938 if {$remove_tmp} {
2939 file delete -force $config_file_tmp
2940 }
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002941 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002942}
2943
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002944proc resizeclistpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002945 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002946 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002947 if {$use_ttk} {
2948 set s0 [$win sashpos 0]
2949 set s1 [$win sashpos 1]
2950 } else {
2951 set s0 [$win sash coord 0]
2952 set s1 [$win sash coord 1]
2953 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002954 if {$w < 60} {
2955 set sash0 [expr {int($w/2 - 2)}]
2956 set sash1 [expr {int($w*5/6 - 2)}]
2957 } else {
2958 set factor [expr {1.0 * $w / $oldwidth($win)}]
2959 set sash0 [expr {int($factor * [lindex $s0 0])}]
2960 set sash1 [expr {int($factor * [lindex $s1 0])}]
2961 if {$sash0 < 30} {
2962 set sash0 30
2963 }
2964 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002965 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002966 }
2967 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002968 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002969 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002970 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002971 }
2972 }
2973 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002974 if {$use_ttk} {
2975 $win sashpos 0 $sash0
2976 $win sashpos 1 $sash1
2977 } else {
2978 $win sash place 0 $sash0 [lindex $s0 1]
2979 $win sash place 1 $sash1 [lindex $s1 1]
2980 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002981 }
2982 set oldwidth($win) $w
2983}
2984
2985proc resizecdetpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002986 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002987 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002988 if {$use_ttk} {
2989 set s0 [$win sashpos 0]
2990 } else {
2991 set s0 [$win sash coord 0]
2992 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002993 if {$w < 60} {
2994 set sash0 [expr {int($w*3/4 - 2)}]
2995 } else {
2996 set factor [expr {1.0 * $w / $oldwidth($win)}]
2997 set sash0 [expr {int($factor * [lindex $s0 0])}]
2998 if {$sash0 < 45} {
2999 set sash0 45
3000 }
3001 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003002 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003003 }
3004 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003005 if {$use_ttk} {
3006 $win sashpos 0 $sash0
3007 } else {
3008 $win sash place 0 $sash0 [lindex $s0 1]
3009 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003010 }
3011 set oldwidth($win) $w
3012}
3013
Paul Mackerrasb5721c72005-05-10 12:08:22 +00003014proc allcanvs args {
3015 global canv canv2 canv3
3016 eval $canv $args
3017 eval $canv2 $args
3018 eval $canv3 $args
3019}
3020
3021proc bindall {event action} {
3022 global canv canv2 canv3
3023 bind $canv $event $action
3024 bind $canv2 $event $action
3025 bind $canv3 $event $action
3026}
3027
Paul Mackerras9a40c502005-05-12 23:46:16 +00003028proc about {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003029 global bgcolor NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00003030 set w .about
3031 if {[winfo exists $w]} {
3032 raise $w
3033 return
3034 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003035 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003036 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003037 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01003038 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003039Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00003040
Paul Mackerrasfbf42642016-12-12 20:46:42 +11003041Copyright \u00a9 2005-2016 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00003042
Christian Stimmingd990ced2007-11-07 18:42:55 +01003043Use and redistribute under the terms of the GNU General Public License"] \
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003044 -justify center -aspect 400 -border 2 -bg $bgcolor -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003045 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003046 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00003047 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003048 bind $w <Visibility> "focus $w.ok"
3049 bind $w <Key-Escape> "destroy $w"
3050 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01003051 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00003052}
3053
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003054proc keys {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003055 global bgcolor NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003056 set w .keys
3057 if {[winfo exists $w]} {
3058 raise $w
3059 return
3060 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003061 if {[tk windowingsystem] eq {aqua}} {
3062 set M1T Cmd
3063 } else {
3064 set M1T Ctrl
3065 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003066 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003067 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003068 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003069 message $w.m -text "
3070[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003071
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003072[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01003073[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003074[mc "<Home> Move to first commit"]
3075[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05003076[mc "<Up>, p, k Move up one commit"]
3077[mc "<Down>, n, j Move down one commit"]
3078[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003079[mc "<Right>, x, l Go forward in history list"]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03003080[mc "<%s-n> Go to n-th parent of current commit in history list" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003081[mc "<PageUp> Move up one page in commit list"]
3082[mc "<PageDown> Move down one page in commit list"]
3083[mc "<%s-Home> Scroll to top of commit list" $M1T]
3084[mc "<%s-End> Scroll to bottom of commit list" $M1T]
3085[mc "<%s-Up> Scroll commit list up one line" $M1T]
3086[mc "<%s-Down> Scroll commit list down one line" $M1T]
3087[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
3088[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
3089[mc "<Shift-Up> Find backwards (upwards, later commits)"]
3090[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
3091[mc "<Delete>, b Scroll diff view up one page"]
3092[mc "<Backspace> Scroll diff view up one page"]
3093[mc "<Space> Scroll diff view down one page"]
3094[mc "u Scroll diff view up 18 lines"]
3095[mc "d Scroll diff view down 18 lines"]
3096[mc "<%s-F> Find" $M1T]
3097[mc "<%s-G> Move to next find hit" $M1T]
3098[mc "<Return> Move to next find hit"]
Ismael Luceno0deb5c92015-04-15 13:18:17 -03003099[mc "g Go to commit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01003100[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003101[mc "? Move to previous find hit"]
3102[mc "f Scroll diff view to next file"]
3103[mc "<%s-S> Search for next hit in diff view" $M1T]
3104[mc "<%s-R> Search for previous hit in diff view" $M1T]
3105[mc "<%s-KP+> Increase font size" $M1T]
3106[mc "<%s-plus> Increase font size" $M1T]
3107[mc "<%s-KP-> Decrease font size" $M1T]
3108[mc "<%s-minus> Decrease font size" $M1T]
3109[mc "<F5> Update"]
3110" \
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003111 -justify left -bg $bgcolor -border 2 -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003112 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003113 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003114 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003115 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003116 bind $w <Visibility> "focus $w.ok"
3117 bind $w <Key-Escape> "destroy $w"
3118 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003119}
3120
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003121# Procedures for manipulating the file list window at the
3122# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003123
3124proc treeview {w l openlevs} {
3125 global treecontents treediropen treeheight treeparent treeindex
3126
3127 set ix 0
3128 set treeindex() 0
3129 set lev 0
3130 set prefix {}
3131 set prefixend -1
3132 set prefendstack {}
3133 set htstack {}
3134 set ht 0
3135 set treecontents() {}
3136 $w conf -state normal
3137 foreach f $l {
3138 while {[string range $f 0 $prefixend] ne $prefix} {
3139 if {$lev <= $openlevs} {
3140 $w mark set e:$treeindex($prefix) "end -1c"
3141 $w mark gravity e:$treeindex($prefix) left
3142 }
3143 set treeheight($prefix) $ht
3144 incr ht [lindex $htstack end]
3145 set htstack [lreplace $htstack end end]
3146 set prefixend [lindex $prefendstack end]
3147 set prefendstack [lreplace $prefendstack end end]
3148 set prefix [string range $prefix 0 $prefixend]
3149 incr lev -1
3150 }
3151 set tail [string range $f [expr {$prefixend+1}] end]
3152 while {[set slash [string first "/" $tail]] >= 0} {
3153 lappend htstack $ht
3154 set ht 0
3155 lappend prefendstack $prefixend
3156 incr prefixend [expr {$slash + 1}]
3157 set d [string range $tail 0 $slash]
3158 lappend treecontents($prefix) $d
3159 set oldprefix $prefix
3160 append prefix $d
3161 set treecontents($prefix) {}
3162 set treeindex($prefix) [incr ix]
3163 set treeparent($prefix) $oldprefix
3164 set tail [string range $tail [expr {$slash+1}] end]
3165 if {$lev <= $openlevs} {
3166 set ht 1
3167 set treediropen($prefix) [expr {$lev < $openlevs}]
3168 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3169 $w mark set d:$ix "end -1c"
3170 $w mark gravity d:$ix left
3171 set str "\n"
3172 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3173 $w insert end $str
3174 $w image create end -align center -image $bm -padx 1 \
3175 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10003176 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003177 $w mark set s:$ix "end -1c"
3178 $w mark gravity s:$ix left
3179 }
3180 incr lev
3181 }
3182 if {$tail ne {}} {
3183 if {$lev <= $openlevs} {
3184 incr ht
3185 set str "\n"
3186 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3187 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003188 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003189 }
3190 lappend treecontents($prefix) $tail
3191 }
3192 }
3193 while {$htstack ne {}} {
3194 set treeheight($prefix) $ht
3195 incr ht [lindex $htstack end]
3196 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05003197 set prefixend [lindex $prefendstack end]
3198 set prefendstack [lreplace $prefendstack end end]
3199 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003200 }
3201 $w conf -state disabled
3202}
3203
3204proc linetoelt {l} {
3205 global treeheight treecontents
3206
3207 set y 2
3208 set prefix {}
3209 while {1} {
3210 foreach e $treecontents($prefix) {
3211 if {$y == $l} {
3212 return "$prefix$e"
3213 }
3214 set n 1
3215 if {[string index $e end] eq "/"} {
3216 set n $treeheight($prefix$e)
3217 if {$y + $n > $l} {
3218 append prefix $e
3219 incr y
3220 break
3221 }
3222 }
3223 incr y $n
3224 }
3225 }
3226}
3227
Paul Mackerras45a9d502006-05-20 22:56:27 +10003228proc highlight_tree {y prefix} {
3229 global treeheight treecontents cflist
3230
3231 foreach e $treecontents($prefix) {
3232 set path $prefix$e
3233 if {[highlight_tag $path] ne {}} {
3234 $cflist tag add bold $y.0 "$y.0 lineend"
3235 }
3236 incr y
3237 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3238 set y [highlight_tree $y $path]
3239 }
3240 }
3241 return $y
3242}
3243
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003244proc treeclosedir {w dir} {
3245 global treediropen treeheight treeparent treeindex
3246
3247 set ix $treeindex($dir)
3248 $w conf -state normal
3249 $w delete s:$ix e:$ix
3250 set treediropen($dir) 0
3251 $w image configure a:$ix -image tri-rt
3252 $w conf -state disabled
3253 set n [expr {1 - $treeheight($dir)}]
3254 while {$dir ne {}} {
3255 incr treeheight($dir) $n
3256 set dir $treeparent($dir)
3257 }
3258}
3259
3260proc treeopendir {w dir} {
3261 global treediropen treeheight treeparent treecontents treeindex
3262
3263 set ix $treeindex($dir)
3264 $w conf -state normal
3265 $w image configure a:$ix -image tri-dn
3266 $w mark set e:$ix s:$ix
3267 $w mark gravity e:$ix right
3268 set lev 0
3269 set str "\n"
3270 set n [llength $treecontents($dir)]
3271 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
3272 incr lev
3273 append str "\t"
3274 incr treeheight($x) $n
3275 }
3276 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003277 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003278 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003279 set iy $treeindex($de)
3280 $w mark set d:$iy e:$ix
3281 $w mark gravity d:$iy left
3282 $w insert e:$ix $str
3283 set treediropen($de) 0
3284 $w image create e:$ix -align center -image tri-rt -padx 1 \
3285 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10003286 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003287 $w mark set s:$iy e:$ix
3288 $w mark gravity s:$iy left
3289 set treeheight($de) 1
3290 } else {
3291 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003292 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003293 }
3294 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003295 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003296 $w conf -state disabled
3297 set treediropen($dir) 1
3298 set top [lindex [split [$w index @0,0] .] 0]
3299 set ht [$w cget -height]
3300 set l [lindex [split [$w index s:$ix] .] 0]
3301 if {$l < $top} {
3302 $w yview $l.0
3303 } elseif {$l + $n + 1 > $top + $ht} {
3304 set top [expr {$l + $n + 2 - $ht}]
3305 if {$l < $top} {
3306 set top $l
3307 }
3308 $w yview $top.0
3309 }
3310}
3311
3312proc treeclick {w x y} {
3313 global treediropen cmitmode ctext cflist cflist_top
3314
3315 if {$cmitmode ne "tree"} return
3316 if {![info exists cflist_top]} return
3317 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3318 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3319 $cflist tag add highlight $l.0 "$l.0 lineend"
3320 set cflist_top $l
3321 if {$l == 1} {
3322 $ctext yview 1.0
3323 return
3324 }
3325 set e [linetoelt $l]
3326 if {[string index $e end] ne "/"} {
3327 showfile $e
3328 } elseif {$treediropen($e)} {
3329 treeclosedir $w $e
3330 } else {
3331 treeopendir $w $e
3332 }
3333}
3334
3335proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003336 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003337
3338 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003339 if {$jump_to_here ne {}} {
3340 set f [lindex $jump_to_here 0]
3341 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3342 showfile $f
3343 }
3344 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003345}
3346
3347image create bitmap tri-rt -background black -foreground blue -data {
3348 #define tri-rt_width 13
3349 #define tri-rt_height 13
3350 static unsigned char tri-rt_bits[] = {
3351 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3352 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3353 0x00, 0x00};
3354} -maskdata {
3355 #define tri-rt-mask_width 13
3356 #define tri-rt-mask_height 13
3357 static unsigned char tri-rt-mask_bits[] = {
3358 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3359 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3360 0x08, 0x00};
3361}
3362image create bitmap tri-dn -background black -foreground blue -data {
3363 #define tri-dn_width 13
3364 #define tri-dn_height 13
3365 static unsigned char tri-dn_bits[] = {
3366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3367 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3368 0x00, 0x00};
3369} -maskdata {
3370 #define tri-dn-mask_width 13
3371 #define tri-dn-mask_height 13
3372 static unsigned char tri-dn-mask_bits[] = {
3373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3374 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3375 0x00, 0x00};
3376}
3377
Paul Mackerras887c9962007-08-20 19:36:20 +10003378image create bitmap reficon-T -background black -foreground yellow -data {
3379 #define tagicon_width 13
3380 #define tagicon_height 9
3381 static unsigned char tagicon_bits[] = {
3382 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3383 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3384} -maskdata {
3385 #define tagicon-mask_width 13
3386 #define tagicon-mask_height 9
3387 static unsigned char tagicon-mask_bits[] = {
3388 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3389 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3390}
3391set rectdata {
3392 #define headicon_width 13
3393 #define headicon_height 9
3394 static unsigned char headicon_bits[] = {
3395 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3396 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3397}
3398set rectmask {
3399 #define headicon-mask_width 13
3400 #define headicon-mask_height 9
3401 static unsigned char headicon-mask_bits[] = {
3402 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3403 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3404}
Paul Mackerras6e8fda52016-12-12 11:29:21 +11003405image create bitmap reficon-H -background black -foreground "#00ff00" \
Paul Mackerras887c9962007-08-20 19:36:20 +10003406 -data $rectdata -maskdata $rectmask
3407image create bitmap reficon-o -background black -foreground "#ddddff" \
3408 -data $rectdata -maskdata $rectmask
3409
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003410proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003411 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003412
3413 $cflist conf -state normal
3414 $cflist delete 0.0 end
3415 if {$first ne {}} {
3416 $cflist insert end $first
3417 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003418 $cflist tag add highlight 1.0 "1.0 lineend"
3419 } else {
Paul Mackerras009409f2015-05-02 20:53:36 +10003420 unset -nocomplain cflist_top
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003421 }
3422 $cflist conf -state disabled
3423 set difffilestart {}
3424}
3425
Paul Mackerras63b79192006-05-20 21:31:52 +10003426proc highlight_tag {f} {
3427 global highlight_paths
3428
3429 foreach p $highlight_paths {
3430 if {[string match $p $f]} {
3431 return "bold"
3432 }
3433 }
3434 return {}
3435}
3436
3437proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003438 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003439
Paul Mackerras45a9d502006-05-20 22:56:27 +10003440 $cflist conf -state normal
3441 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003442 set end [lindex [split [$cflist index end] .] 0]
3443 for {set l 2} {$l < $end} {incr l} {
3444 set line [$cflist get $l.0 "$l.0 lineend"]
3445 if {[highlight_tag $line] ne {}} {
3446 $cflist tag add bold $l.0 "$l.0 lineend"
3447 }
3448 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003449 } else {
3450 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003451 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003452 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003453}
3454
3455proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003456 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003457
Paul Mackerras45a9d502006-05-20 22:56:27 +10003458 $cflist conf -state normal
3459 $cflist tag remove bold 1.0 end
3460 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003461}
3462
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003463proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003464 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003465
Paul Mackerras45a9d502006-05-20 22:56:27 +10003466 $cflist conf -state normal
3467 foreach f $fl {
3468 $cflist insert end "\n"
3469 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003470 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003471 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003472}
3473
3474proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003475 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003476
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003477 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003478 if {![info exists cflist_top]} return
3479 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003480 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3481 $cflist tag add highlight $l.0 "$l.0 lineend"
3482 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003483 if {$l == 1} {
3484 $ctext yview 1.0
3485 } else {
3486 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003487 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003488 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003489}
3490
Paul Mackerras32447292007-07-27 22:30:15 +10003491proc pop_flist_menu {w X Y x y} {
3492 global ctext cflist cmitmode flist_menu flist_menu_file
3493 global treediffs diffids
3494
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003495 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003496 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3497 if {$l <= 1} return
3498 if {$cmitmode eq "tree"} {
3499 set e [linetoelt $l]
3500 if {[string index $e end] eq "/"} return
3501 } else {
3502 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3503 }
3504 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003505 set xdiffstate "normal"
3506 if {$cmitmode eq "tree"} {
3507 set xdiffstate "disabled"
3508 }
3509 # Disable "External diff" item in tree mode
3510 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003511 tk_popup $flist_menu $X $Y
3512}
3513
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003514proc find_ctext_fileinfo {line} {
3515 global ctext_file_names ctext_file_lines
3516
3517 set ok [bsearch $ctext_file_lines $line]
3518 set tline [lindex $ctext_file_lines $ok]
3519
3520 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3521 return {}
3522 } else {
3523 return [list [lindex $ctext_file_names $ok] $tline]
3524 }
3525}
3526
3527proc pop_diff_menu {w X Y x y} {
3528 global ctext diff_menu flist_menu_file
3529 global diff_menu_txtpos diff_menu_line
3530 global diff_menu_filebase
3531
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003532 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3533 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003534 # don't pop up the menu on hunk-separator or file-separator lines
3535 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3536 return
3537 }
3538 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003539 set f [find_ctext_fileinfo $diff_menu_line]
3540 if {$f eq {}} return
3541 set flist_menu_file [lindex $f 0]
3542 set diff_menu_filebase [lindex $f 1]
3543 tk_popup $diff_menu $X $Y
3544}
3545
Paul Mackerras32447292007-07-27 22:30:15 +10003546proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003547 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003548
3549 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003550 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003551 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003552 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003553 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003554 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003555 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003556}
3557
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003558proc gitknewtmpdir {} {
David Aguilarc7664f12014-06-13 14:13:37 -07003559 global diffnum gitktmpdir gitdir env
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003560
3561 if {![info exists gitktmpdir]} {
David Aguilarc7664f12014-06-13 14:13:37 -07003562 if {[info exists env(GITK_TMPDIR)]} {
3563 set tmpdir $env(GITK_TMPDIR)
3564 } elseif {[info exists env(TMPDIR)]} {
3565 set tmpdir $env(TMPDIR)
3566 } else {
3567 set tmpdir $gitdir
3568 }
David Aguilar105b5d32014-06-13 14:43:48 -07003569 set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
David Aguilarac54a4b2014-06-18 19:53:14 -07003570 if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
3571 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
3572 }
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003573 if {[catch {file mkdir $gitktmpdir} err]} {
3574 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3575 unset gitktmpdir
3576 return {}
3577 }
3578 set diffnum 0
3579 }
3580 incr diffnum
3581 set diffdir [file join $gitktmpdir $diffnum]
3582 if {[catch {file mkdir $diffdir} err]} {
3583 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3584 return {}
3585 }
3586 return $diffdir
3587}
3588
Thomas Arcila314f5de2008-03-24 12:55:36 +01003589proc save_file_from_commit {filename output what} {
3590 global nullfile
3591
3592 if {[catch {exec git show $filename -- > $output} err]} {
3593 if {[string match "fatal: bad revision *" $err]} {
3594 return $nullfile
3595 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003596 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003597 return {}
3598 }
3599 return $output
3600}
3601
3602proc external_diff_get_one_file {diffid filename diffdir} {
3603 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003604 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003605
3606 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003607 set difffile [file join $worktree $filename]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003608 if {[file exists $difffile]} {
3609 return $difffile
3610 }
3611 return $nullfile
3612 }
3613 if {$diffid == $nullid2} {
3614 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3615 return [save_file_from_commit :$filename $difffile index]
3616 }
3617 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3618 return [save_file_from_commit $diffid:$filename $difffile \
3619 "revision $diffid"]
3620}
3621
3622proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003623 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003624 global flist_menu_file
3625 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003626 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003627
3628 if {[llength $diffids] == 1} {
3629 # no reference commit given
3630 set diffidto [lindex $diffids 0]
3631 if {$diffidto eq $nullid} {
3632 # diffing working copy with index
3633 set diffidfrom $nullid2
3634 } elseif {$diffidto eq $nullid2} {
3635 # diffing index with HEAD
3636 set diffidfrom "HEAD"
3637 } else {
3638 # use first parent commit
3639 global parentlist selectedline
3640 set diffidfrom [lindex $parentlist $selectedline 0]
3641 }
3642 } else {
3643 set diffidfrom [lindex $diffids 0]
3644 set diffidto [lindex $diffids 1]
3645 }
3646
3647 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003648 set diffdir [gitknewtmpdir]
3649 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003650
3651 # gather files to diff
3652 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3653 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3654
3655 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003656 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3657 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003658 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003659 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003660 } else {
3661 fconfigure $fl -blocking 0
3662 filerun $fl [list delete_at_eof $fl $diffdir]
3663 }
3664 }
3665}
3666
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003667proc find_hunk_blamespec {base line} {
3668 global ctext
3669
3670 # Find and parse the hunk header
3671 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3672 if {$s_lix eq {}} return
3673
3674 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3675 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3676 s_line old_specs osz osz1 new_line nsz]} {
3677 return
3678 }
3679
3680 # base lines for the parents
3681 set base_lines [list $new_line]
3682 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3683 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3684 old_spec old_line osz]} {
3685 return
3686 }
3687 lappend base_lines $old_line
3688 }
3689
3690 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003691 set max_parent [expr {[llength $base_lines]-2}]
3692 set dline 0
3693 set s_lno [lindex [split $s_lix "."] 0]
3694
Paul Mackerras190ec522008-10-27 21:13:37 +11003695 # Determine if the line is removed
3696 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3697 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003698 set removed_idx [string first "-" $chunk]
3699 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003700 if {$removed_idx >= 0} {
3701 set parent $removed_idx
3702 } else {
3703 set unchanged_idx [string first " " $chunk]
3704 if {$unchanged_idx >= 0} {
3705 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003706 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003707 # blame the current commit
3708 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003709 }
3710 }
3711 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003712 for {set i $line} {[incr i -1] > $s_lno} {} {
3713 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3714 # Determine if the line is removed
3715 set removed_idx [string first "-" $chunk]
3716 if {$parent >= 0} {
3717 set code [string index $chunk $parent]
3718 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3719 incr dline
3720 }
3721 } else {
3722 if {$removed_idx < 0} {
3723 incr dline
3724 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003725 }
3726 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003727 incr parent
3728 } else {
3729 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003730 }
3731
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003732 incr dline [lindex $base_lines $parent]
3733 return [list $parent $dline]
3734}
3735
3736proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003737 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003738 global diff_menu_txtpos diff_menu_line
3739 global diff_menu_filebase flist_menu_file
3740
3741 if {$cmitmode eq "tree"} {
3742 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003743 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003744 } else {
3745 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3746 if {$hinfo ne {}} {
3747 set parent_idx [lindex $hinfo 0]
3748 set line [lindex $hinfo 1]
3749 } else {
3750 set parent_idx 0
3751 set line 0
3752 }
3753 }
3754
3755 external_blame $parent_idx $line
3756}
3757
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003758# Find the SHA1 ID of the blob for file $fname in the index
3759# at stage 0 or 2
3760proc index_sha1 {fname} {
3761 set f [open [list | git ls-files -s $fname] r]
3762 while {[gets $f line] >= 0} {
3763 set info [lindex [split $line "\t"] 0]
3764 set stage [lindex $info 2]
3765 if {$stage eq "0" || $stage eq "2"} {
3766 close $f
3767 return [lindex $info 1]
3768 }
3769 }
3770 close $f
3771 return {}
3772}
3773
Paul Mackerras9712b812008-12-06 21:44:05 +11003774# Turn an absolute path into one relative to the current directory
3775proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003776 if {[file pathtype $f] eq "relative"} {
3777 return $f
3778 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003779 set elts [file split $f]
3780 set here [file split [pwd]]
3781 set ei 0
3782 set hi 0
3783 set res {}
3784 foreach d $here {
3785 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3786 lappend res ".."
3787 } else {
3788 incr ei
3789 }
3790 incr hi
3791 }
3792 set elts [concat $res [lrange $elts $ei end]]
3793 return [eval file join $elts]
3794}
3795
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003796proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003797 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003798 global nullid nullid2
3799 global parentlist selectedline currentid
3800
3801 if {$parent_idx > 0} {
3802 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3803 } else {
3804 set base_commit $currentid
3805 }
3806
3807 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3808 error_popup [mc "No such commit"]
3809 return
3810 }
3811
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003812 set cmdline [list git gui blame]
3813 if {$line ne {} && $line > 1} {
3814 lappend cmdline "--line=$line"
3815 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003816 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003817 # Unfortunately it seems git gui blame doesn't like
3818 # being given an absolute path...
3819 set f [make_relative $f]
3820 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003821 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003822 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003823 }
3824}
3825
Paul Mackerras8a897742008-10-27 21:36:25 +11003826proc show_line_source {} {
3827 global cmitmode currentid parents curview blamestuff blameinst
3828 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003829 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003830
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003831 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003832 if {$cmitmode eq "tree"} {
3833 set id $currentid
3834 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3835 } else {
3836 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3837 if {$h eq {}} return
3838 set pi [lindex $h 0]
3839 if {$pi == 0} {
3840 mark_ctext_line $diff_menu_line
3841 return
3842 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003843 incr pi -1
3844 if {$currentid eq $nullid} {
3845 if {$pi > 0} {
3846 # must be a merge in progress...
3847 if {[catch {
3848 # get the last line from .git/MERGE_HEAD
3849 set f [open [file join $gitdir MERGE_HEAD] r]
3850 set id [lindex [split [read $f] "\n"] end-1]
3851 close $f
3852 } err]} {
3853 error_popup [mc "Couldn't read merge head: %s" $err]
3854 return
3855 }
3856 } elseif {$parents($curview,$currentid) eq $nullid2} {
3857 # need to do the blame from the index
3858 if {[catch {
3859 set from_index [index_sha1 $flist_menu_file]
3860 } err]} {
3861 error_popup [mc "Error reading index: %s" $err]
3862 return
3863 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003864 } else {
3865 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003866 }
3867 } else {
3868 set id [lindex $parents($curview,$currentid) $pi]
3869 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003870 set line [lindex $h 1]
3871 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003872 set blameargs {}
3873 if {$from_index ne {}} {
3874 lappend blameargs | git cat-file blob $from_index
3875 }
3876 lappend blameargs | git blame -p -L$line,+1
3877 if {$from_index ne {}} {
3878 lappend blameargs --contents -
3879 } else {
3880 lappend blameargs $id
3881 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003882 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003883 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003884 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003885 } err]} {
3886 error_popup [mc "Couldn't start git blame: %s" $err]
3887 return
3888 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003889 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003890 fconfigure $f -blocking 0
3891 set i [reg_instance $f]
3892 set blamestuff($i) {}
3893 set blameinst $i
3894 filerun $f [list read_line_source $f $i]
3895}
3896
3897proc stopblaming {} {
3898 global blameinst
3899
3900 if {[info exists blameinst]} {
3901 stop_instance $blameinst
3902 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003903 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003904 }
3905}
3906
3907proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003908 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003909
3910 while {[gets $fd line] >= 0} {
3911 lappend blamestuff($inst) $line
3912 }
3913 if {![eof $fd]} {
3914 return 1
3915 }
3916 unset commfd($inst)
3917 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003918 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003919 fconfigure $fd -blocking 1
3920 if {[catch {close $fd} err]} {
3921 error_popup [mc "Error running git blame: %s" $err]
3922 return 0
3923 }
3924
3925 set fname {}
3926 set line [split [lindex $blamestuff($inst) 0] " "]
3927 set id [lindex $line 0]
3928 set lnum [lindex $line 1]
3929 if {[string length $id] == 40 && [string is xdigit $id] &&
3930 [string is digit -strict $lnum]} {
3931 # look for "filename" line
3932 foreach l $blamestuff($inst) {
3933 if {[string match "filename *" $l]} {
3934 set fname [string range $l 9 end]
3935 break
3936 }
3937 }
3938 }
3939 if {$fname ne {}} {
3940 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003941 if {$id eq $nullid} {
3942 # blame uses all-zeroes to mean not committed,
3943 # which would mean a change in the index
3944 set id $nullid2
3945 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003946 if {[commitinview $id $curview]} {
Max Kirillov4135d362014-04-05 23:38:50 +03003947 selectline [rowofcommit $id] 1 [list $fname $lnum] 1
Paul Mackerras8a897742008-10-27 21:36:25 +11003948 } else {
3949 error_popup [mc "That line comes from commit %s, \
3950 which is not in this view" [shortids $id]]
3951 }
3952 } else {
3953 puts "oops couldn't parse git blame output"
3954 }
3955 return 0
3956}
3957
Thomas Arcila314f5de2008-03-24 12:55:36 +01003958# delete $dir when we see eof on $f (presumably because the child has exited)
3959proc delete_at_eof {f dir} {
3960 while {[gets $f line] >= 0} {}
3961 if {[eof $f]} {
3962 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003963 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003964 }
3965 file delete -force $dir
3966 return 0
3967 }
3968 return 1
3969}
3970
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003971# Functions for adding and removing shell-type quoting
3972
3973proc shellquote {str} {
3974 if {![string match "*\['\"\\ \t]*" $str]} {
3975 return $str
3976 }
3977 if {![string match "*\['\"\\]*" $str]} {
3978 return "\"$str\""
3979 }
3980 if {![string match "*'*" $str]} {
3981 return "'$str'"
3982 }
3983 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3984}
3985
3986proc shellarglist {l} {
3987 set str {}
3988 foreach a $l {
3989 if {$str ne {}} {
3990 append str " "
3991 }
3992 append str [shellquote $a]
3993 }
3994 return $str
3995}
3996
3997proc shelldequote {str} {
3998 set ret {}
3999 set used -1
4000 while {1} {
4001 incr used
4002 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
4003 append ret [string range $str $used end]
4004 set used [string length $str]
4005 break
4006 }
4007 set first [lindex $first 0]
4008 set ch [string index $str $first]
4009 if {$first > $used} {
4010 append ret [string range $str $used [expr {$first - 1}]]
4011 set used $first
4012 }
4013 if {$ch eq " " || $ch eq "\t"} break
4014 incr used
4015 if {$ch eq "'"} {
4016 set first [string first "'" $str $used]
4017 if {$first < 0} {
4018 error "unmatched single-quote"
4019 }
4020 append ret [string range $str $used [expr {$first - 1}]]
4021 set used $first
4022 continue
4023 }
4024 if {$ch eq "\\"} {
4025 if {$used >= [string length $str]} {
4026 error "trailing backslash"
4027 }
4028 append ret [string index $str $used]
4029 continue
4030 }
4031 # here ch == "\""
4032 while {1} {
4033 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
4034 error "unmatched double-quote"
4035 }
4036 set first [lindex $first 0]
4037 set ch [string index $str $first]
4038 if {$first > $used} {
4039 append ret [string range $str $used [expr {$first - 1}]]
4040 set used $first
4041 }
4042 if {$ch eq "\""} break
4043 incr used
4044 append ret [string index $str $used]
4045 incr used
4046 }
4047 }
4048 return [list $used $ret]
4049}
4050
4051proc shellsplit {str} {
4052 set l {}
4053 while {1} {
4054 set str [string trimleft $str]
4055 if {$str eq {}} break
4056 set dq [shelldequote $str]
4057 set n [lindex $dq 0]
4058 set word [lindex $dq 1]
4059 set str [string range $str $n end]
4060 lappend l $word
4061 }
4062 return $l
4063}
4064
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004065proc set_window_title {} {
4066 global appname curview viewname vrevs
4067 set rev [mc "All files"]
4068 if {$curview ne 0} {
4069 if {$viewname($curview) eq [mc "Command line"]} {
4070 set rev [string map {"--gitk-symmetric-diff-marker" "--merge"} $vrevs($curview)]
4071 } else {
4072 set rev $viewname($curview)
4073 }
4074 }
4075 wm title . "[reponame]: $rev - $appname"
4076}
4077
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004078# Code to implement multiple views
4079
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004080proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004081 global nextviewnum newviewname newishighlight
4082 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004083
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004084 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004085 set top .gitkview
4086 if {[winfo exists $top]} {
4087 raise $top
4088 return
4089 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004090 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01004091 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004092 set newviewopts($nextviewnum,perm) 0
4093 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01004094 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004095}
4096
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004097set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004098 {perm b . {} {mc "Remember this view"}}
4099 {reflabel l + {} {mc "References (space separated list):"}}
4100 {refs t15 .. {} {mc "Branches & tags:"}}
4101 {allrefs b *. "--all" {mc "All refs"}}
4102 {branches b . "--branches" {mc "All (local) branches"}}
4103 {tags b . "--tags" {mc "All tags"}}
4104 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
4105 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
4106 {author t15 .. "--author=*" {mc "Author:"}}
4107 {committer t15 . "--committer=*" {mc "Committer:"}}
4108 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
4109 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
Alex Henrie00132512015-04-02 15:05:06 -06004110 {igrep b .. "--invert-grep" {mc "Matches no Commit Info criteria"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004111 {changes_l l + {} {mc "Changes to Files:"}}
4112 {pickaxe_s r0 . {} {mc "Fixed String"}}
4113 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
4114 {pickaxe t15 .. "-S*" {mc "Search string:"}}
4115 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
4116 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
4117 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
4118 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
4119 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
4120 {skip t10 . "--skip=*" {mc "Number to skip:"}}
4121 {misc_lbl l + {} {mc "Miscellaneous options:"}}
4122 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
4123 {lright b . "--left-right" {mc "Mark branch sides"}}
4124 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02004125 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004126 {args t50 *. {} {mc "Additional arguments to git log:"}}
4127 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
4128 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004129 }
4130
Jonathan Niedere7feb692010-03-06 16:48:38 -06004131# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004132proc encode_view_opts {n} {
4133 global known_view_options newviewopts
4134
4135 set rargs [list]
4136 foreach opt $known_view_options {
4137 set patterns [lindex $opt 3]
4138 if {$patterns eq {}} continue
4139 set pattern [lindex $patterns 0]
4140
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004141 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004142 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004143 if {$val} {
4144 lappend rargs $pattern
4145 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004146 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4147 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4148 set val $newviewopts($n,$button_id)
4149 if {$val eq $value} {
4150 lappend rargs $pattern
4151 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004152 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004153 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004154 set val [string trim $val]
4155 if {$val ne {}} {
4156 set pfix [string range $pattern 0 end-1]
4157 lappend rargs $pfix$val
4158 }
4159 }
4160 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004161 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004162 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4163}
4164
Jonathan Niedere7feb692010-03-06 16:48:38 -06004165# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004166proc decode_view_opts {n view_args} {
4167 global known_view_options newviewopts
4168
4169 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004170 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004171 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004172 # Checkboxes
4173 set val 0
4174 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
4175 # Radiobuttons
4176 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004177 set val 0
4178 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004179 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004180 set val {}
4181 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004182 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004183 }
4184 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004185 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004186 foreach arg $view_args {
4187 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4188 && ![info exists found(limit)]} {
4189 set newviewopts($n,limit) $cnt
4190 set found(limit) 1
4191 continue
4192 }
4193 catch { unset val }
4194 foreach opt $known_view_options {
4195 set id [lindex $opt 0]
4196 if {[info exists found($id)]} continue
4197 foreach pattern [lindex $opt 3] {
4198 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004199 if {[lindex $opt 1] eq "b"} {
4200 # Check buttons
4201 set val 1
4202 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4203 # Radio buttons
4204 regexp {^(.*_)} $id uselessvar id
4205 set val $num
4206 } else {
4207 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004208 set size [string length $pattern]
4209 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004210 }
4211 set newviewopts($n,$id) $val
4212 set found($id) 1
4213 break
4214 }
4215 if {[info exists val]} break
4216 }
4217 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004218 if {[regexp {^-} $arg]} {
4219 lappend oargs $arg
4220 } else {
4221 lappend refargs $arg
4222 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004223 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004224 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004225 set newviewopts($n,args) [shellarglist $oargs]
4226}
4227
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004228proc edit_or_newview {} {
4229 global curview
4230
4231 if {$curview > 0} {
4232 editview
4233 } else {
4234 newview 0
4235 }
4236}
4237
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004238proc editview {} {
4239 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004240 global viewname viewperm newviewname newviewopts
4241 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004242
4243 set top .gitkvedit-$curview
4244 if {[winfo exists $top]} {
4245 raise $top
4246 return
4247 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004248 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004249 set newviewname($curview) $viewname($curview)
4250 set newviewopts($curview,perm) $viewperm($curview)
4251 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004252 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004253}
4254
4255proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004256 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004257 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004258
Pat Thoytsd93f1712009-04-17 01:24:35 +01004259 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004260 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004261 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004262
4263 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004264 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004265 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004266 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004267 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004268 pack $top.nl -in $top.nfr -side left -padx {0 5}
4269 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004270
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004271 # View options
4272 set cframe $top.nfr
4273 set cexpand 0
4274 set cnt 0
4275 foreach opt $known_view_options {
4276 set id [lindex $opt 0]
4277 set type [lindex $opt 1]
4278 set flags [lindex $opt 2]
4279 set title [eval [lindex $opt 4]]
4280 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004281
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004282 if {$flags eq "+" || $flags eq "*"} {
4283 set cframe $top.fr$cnt
4284 incr cnt
Pat Thoytsd93f1712009-04-17 01:24:35 +01004285 ${NS}::frame $cframe
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004286 pack $cframe -in $top -fill x -pady 3 -padx 3
4287 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004288 } elseif {$flags eq ".." || $flags eq "*."} {
4289 set cframe $top.fr$cnt
4290 incr cnt
Paul Mackerraseae7d642009-09-05 17:34:03 +10004291 ${NS}::frame $cframe
Elijah Newren13d40b62009-03-23 11:57:46 -06004292 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4293 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004294 } else {
4295 set lxpad 5
4296 }
4297
Elijah Newren13d40b62009-03-23 11:57:46 -06004298 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004299 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004300 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
4301 } elseif {$type eq "b"} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004302 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004303 pack $cframe.c_$id -in $cframe -side left \
4304 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06004305 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4306 regexp {^(.*_)} $id uselessvar button_id
Paul Mackerraseae7d642009-09-05 17:34:03 +10004307 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
Elijah Newren13d40b62009-03-23 11:57:46 -06004308 pack $cframe.c_$id -in $cframe -side left \
4309 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004310 } elseif {[regexp {^t(\d+)$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004311 ${NS}::label $cframe.l_$id -text $title
4312 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004313 -textvariable newviewopts($n,$id)
4314 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4315 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4316 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004317 ${NS}::label $cframe.l_$id -text $title
4318 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004319 -textvariable newviewopts($n,$id)
4320 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4321 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06004322 } elseif {$type eq "path"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004323 ${NS}::label $top.l -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004324 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
Mark Hillsb9b142f2010-01-13 20:40:22 +00004325 text $top.t -width 40 -height 5 -background $bgcolor
Elijah Newren13d40b62009-03-23 11:57:46 -06004326 if {[info exists viewfiles($n)]} {
4327 foreach f $viewfiles($n) {
4328 $top.t insert end $f
4329 $top.t insert end "\n"
4330 }
4331 $top.t delete {end - 1c} end
4332 $top.t mark set insert 0.0
4333 }
4334 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004335 }
4336 }
4337
Pat Thoytsd93f1712009-04-17 01:24:35 +01004338 ${NS}::frame $top.buts
4339 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4340 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4341 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004342 bind $top <Control-Return> [list newviewok $top $n]
4343 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004344 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004345 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004346 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4347 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004348 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4349 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004350 focus $top.t
4351}
4352
Paul Mackerras908c3582006-05-20 09:38:11 +10004353proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004354 set nmenu [$m index end]
4355 for {set i $first} {$i <= $nmenu} {incr i} {
4356 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004357 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004358 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004359 }
4360 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004361}
4362
4363proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004364 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004365
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004366 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004367 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004368}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004369
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004370proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004371 global nextviewnum newviewperm newviewname newishighlight
Max Kirillov995f7922015-03-04 05:58:16 +02004372 global viewname viewfiles viewperm viewchanged selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004373 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004374
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004375 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004376 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004377 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03004378 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004379 return
4380 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004381 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004382 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004383 set ft [string trim $f]
4384 if {$ft ne {}} {
4385 lappend files $ft
4386 }
4387 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004388 if {![info exists viewfiles($n)]} {
4389 # creating a new view
4390 incr nextviewnum
4391 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004392 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004393 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004394 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004395 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004396 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004397 addviewmenu $n
4398 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004399 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004400 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004401 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004402 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004403 } else {
4404 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004405 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004406 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004407 if {$newviewname($n) ne $viewname($n)} {
4408 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004409 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004410 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10004411 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4412 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004413 }
Yann Dirson2d480852008-02-21 21:23:31 +01004414 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004415 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004416 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004417 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004418 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004419 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004420 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004421 }
4422 }
4423 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004424 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004425 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004426}
4427
4428proc delview {} {
Max Kirillov995f7922015-03-04 05:58:16 +02004429 global curview viewperm hlview selectedhlview viewchanged
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004430
4431 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004432 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004433 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004434 unset hlview
4435 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004436 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004437 set viewperm($curview) 0
Max Kirillov995f7922015-03-04 05:58:16 +02004438 set viewchanged($curview) 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004439 showview 0
4440}
4441
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004442proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004443 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004444
4445 .bar.view add radiobutton -label $viewname($n) \
4446 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004447 #$viewhlmenu add radiobutton -label $viewname($n) \
4448 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004449}
4450
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004451proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004452 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004453 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004454 global colormap rowtextx nextcolor canvxmax
4455 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004456 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004457 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004458 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004459 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004460 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004461 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004462
4463 if {$n == $curview} return
4464 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004465 set ymax [lindex [$canv cget -scrollregion] 3]
4466 set span [$canv yview]
4467 set ytop [expr {[lindex $span 0] * $ymax}]
4468 set ybot [expr {[lindex $span 1] * $ymax}]
4469 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004470 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004471 set selid $currentid
4472 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004473 if {$ytop < $y && $y < $ybot} {
4474 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004475 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004476 } elseif {[info exists pending_select]} {
4477 set selid $pending_select
4478 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004479 }
4480 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004481 normalline
Paul Mackerras009409f2015-05-02 20:53:36 +10004482 unset -nocomplain treediffs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004483 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004484 if {[info exists hlview] && $hlview == $n} {
4485 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004486 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004487 }
Paul Mackerras009409f2015-05-02 20:53:36 +10004488 unset -nocomplain commitinterest
4489 unset -nocomplain cached_commitrow
4490 unset -nocomplain ordertok
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004491
4492 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004493 set selectedview $n
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02004494 .bar.view entryconf [mca "&Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4495 .bar.view entryconf [mca "&Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004496
Paul Mackerrasdf904492007-08-29 22:03:07 +10004497 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004498 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004499 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004500 return
4501 }
4502
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004503 set displayorder {}
4504 set parentlist {}
4505 set rowidlist {}
4506 set rowisopt {}
4507 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004508 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004509
Paul Mackerras009409f2015-05-02 20:53:36 +10004510 unset -nocomplain colormap
4511 unset -nocomplain rowtextx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004512 set nextcolor 0
4513 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004514 set curview $n
4515 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004516 setcanvscroll
4517 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004518 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004519 if {$selid ne {} && [commitinview $selid $n]} {
4520 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004521 # try to get the selected row in the same position on the screen
4522 set ymax [lindex [$canv cget -scrollregion] 3]
4523 set ytop [expr {[yc $row] - $yscreen}]
4524 if {$ytop < 0} {
4525 set ytop 0
4526 }
4527 set yf [expr {$ytop * 1.0 / $ymax}]
4528 }
4529 allcanvs yview moveto $yf
4530 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004531 if {$row ne {}} {
4532 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004533 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004534 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004535 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004536 reset_pending_select {}
4537
4538 if {[commitinview $pending_select $curview]} {
4539 selectline [rowofcommit $pending_select] 1
4540 } else {
4541 set row [first_real_row]
4542 if {$row < $numcommits} {
4543 selectline $row 0
4544 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004545 }
4546 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004547 if {!$viewcomplete($n)} {
4548 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004549 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004550 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004551 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004552 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004553 }
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004554 set_window_title
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004555}
4556
Paul Mackerras908c3582006-05-20 09:38:11 +10004557# Stuff relating to the highlighting facility
4558
Paul Mackerras476ca632008-01-07 22:16:31 +11004559proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004560 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004561
Paul Mackerras476ca632008-01-07 22:16:31 +11004562 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4563 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004564 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004565 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4566 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004567 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004568 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4569 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004570 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004571 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4572 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004573 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004574 return 0
4575}
4576
Paul Mackerras28593d32008-11-13 23:01:46 +11004577proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004578 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004579
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004580 # need_redisplay = 1 means the display is stale and about to be redrawn
4581 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004582 lappend boldids $id
4583 $canv itemconf $linehtag($id) -font $font
4584 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004585 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004586 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004587 -outline {{}} -tags secsel \
4588 -fill [$canv cget -selectbackground]]
4589 $canv lower $t
4590 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004591 if {[info exists markedid] && $id eq $markedid} {
4592 make_idmark $id
4593 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004594}
4595
Paul Mackerras28593d32008-11-13 23:01:46 +11004596proc bolden_name {id font} {
4597 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004598
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004599 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004600 lappend boldnameids $id
4601 $canv2 itemconf $linentag($id) -font $font
4602 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004603 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004604 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004605 -outline {{}} -tags secsel \
4606 -fill [$canv2 cget -selectbackground]]
4607 $canv2 lower $t
4608 }
4609}
4610
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004611proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004612 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004613
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004614 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004615 foreach id $boldids {
4616 if {![ishighlighted $id]} {
4617 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004618 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004619 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004620 }
4621 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004622 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004623}
4624
4625proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004626 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004627
4628 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004629 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004630 }
4631 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004632 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004633 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004634 }
4635 set vhl_done $commitidx($hlview)
4636 if {$vhl_done > 0} {
4637 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004638 }
4639}
4640
Paul Mackerras908c3582006-05-20 09:38:11 +10004641proc delvhighlight {} {
4642 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004643
4644 if {![info exists hlview]} return
4645 unset hlview
Paul Mackerras009409f2015-05-02 20:53:36 +10004646 unset -nocomplain vhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004647 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004648}
4649
Paul Mackerras908c3582006-05-20 09:38:11 +10004650proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004651 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004652
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004653 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004654 set vr [visiblerows]
4655 set r0 [lindex $vr 0]
4656 set r1 [lindex $vr 1]
4657 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004658 set id [commitonrow $i $hlview]
4659 if {[commitinview $id $curview]} {
4660 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004661 if {$r0 <= $row && $row <= $r1} {
4662 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004663 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004664 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004665 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004666 }
4667 }
4668 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004669 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004670 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004671}
4672
4673proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004674 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004675
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004676 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004677 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004678 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004679 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004680 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004681 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004682 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004683 }
4684}
4685
Paul Mackerras687c8762007-09-22 12:49:33 +10004686proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004687 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004688 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004689
4690 if {[info exists filehighlight]} {
4691 # delete previous highlights
4692 catch {close $filehighlight}
4693 unset filehighlight
Paul Mackerras009409f2015-05-02 20:53:36 +10004694 unset -nocomplain fhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004695 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004696 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004697 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004698 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004699 after cancel do_file_hl $fh_serial
4700 incr fh_serial
4701 if {$highlight_files ne {}} {
4702 after 300 do_file_hl $fh_serial
4703 }
4704}
4705
Paul Mackerras687c8762007-09-22 12:49:33 +10004706proc gdttype_change {name ix op} {
4707 global gdttype highlight_files findstring findpattern
4708
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004709 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004710 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004711 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004712 if {$highlight_files ne {}} {
4713 set highlight_files {}
4714 hfiles_change
4715 }
4716 findcom_change
4717 } else {
4718 if {$findpattern ne {}} {
4719 set findpattern {}
4720 findcom_change
4721 }
4722 set highlight_files $findstring
4723 hfiles_change
4724 }
4725 drawvisible
4726 }
4727 # enable/disable findtype/findloc menus too
4728}
4729
4730proc find_change {name ix op} {
4731 global gdttype findstring highlight_files
4732
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004733 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004734 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004735 findcom_change
4736 } else {
4737 if {$highlight_files ne $findstring} {
4738 set highlight_files $findstring
4739 hfiles_change
4740 }
4741 }
4742 drawvisible
4743}
4744
Paul Mackerras64b5f142007-10-04 22:19:24 +10004745proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004746 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004747 global findpattern findtype findstring gdttype
4748
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004749 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004750 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004751 foreach id $boldnameids {
4752 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004753 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004754 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10004755 unset -nocomplain nhighlights
Paul Mackerras687c8762007-09-22 12:49:33 +10004756 unbolden
4757 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004758 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004759 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004760 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004761 set findpattern $findstring
4762 } else {
4763 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4764 $findstring]
4765 set findpattern "*$e*"
4766 }
4767}
4768
Paul Mackerras63b79192006-05-20 21:31:52 +10004769proc makepatterns {l} {
4770 set ret {}
4771 foreach e $l {
4772 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4773 if {[string index $ee end] eq "/"} {
4774 lappend ret "$ee*"
4775 } else {
4776 lappend ret $ee
4777 lappend ret "$ee/*"
4778 }
4779 }
4780 return $ret
4781}
4782
Paul Mackerras908c3582006-05-20 09:38:11 +10004783proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004784 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004785 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004786
Christian Stimmingb007ee22007-11-07 18:44:35 +01004787 if {$gdttype eq [mc "touching paths:"]} {
Yggy Kingde665fd2011-07-13 01:30:26 -07004788 # If "exact" match then convert backslashes to forward slashes.
4789 # Most useful to support Windows-flavoured file paths.
4790 if {$findtype eq [mc "Exact"]} {
4791 set highlight_files [string map {"\\" "/"} $highlight_files]
4792 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004793 if {[catch {set paths [shellsplit $highlight_files]}]} return
4794 set highlight_paths [makepatterns $paths]
4795 highlight_filelist
Martin von Zweigbergkc332f442011-04-04 22:14:12 -04004796 set relative_paths {}
4797 foreach path $paths {
4798 lappend relative_paths [file join $cdup $path]
4799 }
4800 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004801 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004802 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004803 } elseif {$gdttype eq [mc "changing lines matching:"]} {
4804 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004805 } else {
4806 # must be "containing:", i.e. we're searching commit info
4807 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004808 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004809 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004810 set filehighlight [open $cmd r+]
4811 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004812 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004813 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004814 drawvisible
4815 flushhighlights
4816}
4817
4818proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004819 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004820
4821 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004822 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004823 puts $filehighlight ""
4824 flush $filehighlight
4825 }
4826}
4827
4828proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004829 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004830
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004831 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004832 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004833 puts $filehighlight $id
4834}
4835
4836proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004837 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004838 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004839
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004840 if {![info exists filehighlight]} {
4841 return 0
4842 }
4843 set nr 0
4844 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004845 set line [string trim $line]
4846 set i [lsearch -exact $fhl_list $line]
4847 if {$i < 0} continue
4848 for {set j 0} {$j < $i} {incr j} {
4849 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004850 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004851 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004852 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4853 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004854 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004855 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004856 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004857 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004858 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004859 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004860 if {[eof $filehighlight]} {
4861 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004862 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004863 catch {close $filehighlight}
4864 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004865 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004866 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004867 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004868 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004869 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004870 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004871}
4872
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004873proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004874 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004875
Christian Stimmingb007ee22007-11-07 18:44:35 +01004876 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004877 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004878 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004879 return [string match -nocase $findpattern $f]
4880 } else {
4881 return [string match $findpattern $f]
4882 }
4883}
4884
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004885proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004886 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004887 global findloc
4888 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004889
4890 if {![info exists commitinfo($id)]} {
4891 getcommit $id
4892 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004893 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004894 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004895 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004896 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04004897 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01004898 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004899 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004900 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004901 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004902 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004903 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004904 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004905 }
4906 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004907 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004908 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004909 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004910 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004911 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004912 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004913 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004914 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004915 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004916 }
4917 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004918 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004919}
4920
Paul Mackerras005a2f42007-07-26 22:36:39 +10004921proc markrowmatches {row id} {
4922 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004923
Paul Mackerras005a2f42007-07-26 22:36:39 +10004924 set headline [lindex $commitinfo($id) 0]
4925 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004926 $canv delete match$row
4927 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004928 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004929 set m [findmatches $headline]
4930 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004931 markmatches $canv $row $headline $linehtag($id) $m \
4932 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004933 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004934 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004935 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004936 set m [findmatches $author]
4937 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004938 markmatches $canv2 $row $author $linentag($id) $m \
4939 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004940 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004941 }
4942}
4943
Paul Mackerras164ff272006-05-29 19:50:02 +10004944proc vrel_change {name ix op} {
4945 global highlight_related
4946
4947 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004948 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004949 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004950 }
4951}
4952
4953# prepare for testing whether commits are descendents or ancestors of a
4954proc rhighlight_sel {a} {
4955 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004956 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004957
Paul Mackerras009409f2015-05-02 20:53:36 +10004958 unset -nocomplain descendent
Paul Mackerras164ff272006-05-29 19:50:02 +10004959 set desc_todo [list $a]
Paul Mackerras009409f2015-05-02 20:53:36 +10004960 unset -nocomplain ancestor
Paul Mackerras164ff272006-05-29 19:50:02 +10004961 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004962 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004963 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004964 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004965 }
4966}
4967
4968proc rhighlight_none {} {
4969 global rhighlights
4970
Paul Mackerras009409f2015-05-02 20:53:36 +10004971 unset -nocomplain rhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004972 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004973}
4974
4975proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004976 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004977
4978 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004979 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004980 set todo $desc_todo
4981 set leftover {}
4982 set done 0
4983 for {set i 0} {$i < [llength $todo]} {incr i} {
4984 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004985 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004986 lappend leftover $do
4987 continue
4988 }
4989 foreach nk $children($v,$do) {
4990 if {![info exists descendent($nk)]} {
4991 set descendent($nk) 1
4992 lappend todo $nk
4993 if {$nk eq $a} {
4994 set done 1
4995 }
4996 }
4997 }
4998 if {$done} {
4999 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5000 return
5001 }
5002 }
5003 set descendent($a) 0
5004 set desc_todo $leftover
5005}
5006
5007proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005008 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10005009
5010 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005011 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10005012 set todo $anc_todo
5013 set leftover {}
5014 set done 0
5015 for {set i 0} {$i < [llength $todo]} {incr i} {
5016 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005017 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005018 lappend leftover $do
5019 continue
5020 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005021 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10005022 if {![info exists ancestor($np)]} {
5023 set ancestor($np) 1
5024 lappend todo $np
5025 if {$np eq $a} {
5026 set done 1
5027 }
5028 }
5029 }
5030 if {$done} {
5031 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5032 return
5033 }
5034 }
5035 set ancestor($a) 0
5036 set anc_todo $leftover
5037}
5038
5039proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005040 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005041 global selectedline ancestor
5042
Paul Mackerras94b4a692008-05-20 20:51:06 +10005043 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10005044 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01005045 if {$highlight_related eq [mc "Descendant"] ||
5046 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005047 if {![info exists descendent($id)]} {
5048 is_descendent $id
5049 }
Christian Stimming55e34432008-01-09 22:23:18 +01005050 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005051 set isbold 1
5052 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005053 } elseif {$highlight_related eq [mc "Ancestor"] ||
5054 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005055 if {![info exists ancestor($id)]} {
5056 is_ancestor $id
5057 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005058 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005059 set isbold 1
5060 }
5061 }
5062 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11005063 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005064 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005065 }
5066 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005067 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005068}
5069
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005070# Graph layout functions
5071
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005072proc shortids {ids} {
5073 set res {}
5074 foreach id $ids {
5075 if {[llength $id] > 1} {
5076 lappend res [shortids $id]
5077 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
5078 lappend res [string range $id 0 7]
5079 } else {
5080 lappend res $id
5081 }
5082 }
5083 return $res
5084}
5085
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005086proc ntimes {n o} {
5087 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10005088 set o [list $o]
5089 for {set mask 1} {$mask <= $n} {incr mask $mask} {
5090 if {($n & $mask) != 0} {
5091 set ret [concat $ret $o]
5092 }
5093 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005094 }
5095 return $ret
5096}
5097
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005098proc ordertoken {id} {
5099 global ordertok curview varcid varcstart varctok curview parents children
5100 global nullid nullid2
5101
5102 if {[info exists ordertok($id)]} {
5103 return $ordertok($id)
5104 }
5105 set origid $id
5106 set todo {}
5107 while {1} {
5108 if {[info exists varcid($curview,$id)]} {
5109 set a $varcid($curview,$id)
5110 set p [lindex $varcstart($curview) $a]
5111 } else {
5112 set p [lindex $children($curview,$id) 0]
5113 }
5114 if {[info exists ordertok($p)]} {
5115 set tok $ordertok($p)
5116 break
5117 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11005118 set id [first_real_child $curview,$p]
5119 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005120 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11005121 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005122 break
5123 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005124 if {[llength $parents($curview,$id)] == 1} {
5125 lappend todo [list $p {}]
5126 } else {
5127 set j [lsearch -exact $parents($curview,$id) $p]
5128 if {$j < 0} {
5129 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
5130 }
5131 lappend todo [list $p [strrep $j]]
5132 }
5133 }
5134 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
5135 set p [lindex $todo $i 0]
5136 append tok [lindex $todo $i 1]
5137 set ordertok($p) $tok
5138 }
5139 set ordertok($origid) $tok
5140 return $tok
5141}
5142
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005143# Work out where id should go in idlist so that order-token
5144# values increase from left to right
5145proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005146 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005147 if {$i < 0} {
5148 set i 0
5149 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005150 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005151 if {$i > [llength $idlist]} {
5152 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005153 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005154 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005155 incr i
5156 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005157 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005158 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005159 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005160 }
5161 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005162 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005163}
5164
5165proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005166 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005167 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005168 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005169 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005170
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005171 set numcommits 0
5172 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005173 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005174 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005175 set rowidlist {}
5176 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005177 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005178 set canvxmax [$canv cget -width]
Paul Mackerras009409f2015-05-02 20:53:36 +10005179 unset -nocomplain colormap
5180 unset -nocomplain rowtextx
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005181 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005182}
5183
5184proc setcanvscroll {} {
5185 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005186 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005187
5188 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5189 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5190 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5191 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005192 set lastscrollset [clock clicks -milliseconds]
5193 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005194}
5195
5196proc visiblerows {} {
5197 global canv numcommits linespc
5198
5199 set ymax [lindex [$canv cget -scrollregion] 3]
5200 if {$ymax eq {} || $ymax == 0} return
5201 set f [$canv yview]
5202 set y0 [expr {int([lindex $f 0] * $ymax)}]
5203 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5204 if {$r0 < 0} {
5205 set r0 0
5206 }
5207 set y1 [expr {int([lindex $f 1] * $ymax)}]
5208 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5209 if {$r1 >= $numcommits} {
5210 set r1 [expr {$numcommits - 1}]
5211 }
5212 return [list $r0 $r1]
5213}
5214
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005215proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005216 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005217 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005218 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005219
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005220 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
5221 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005222 setcanvscroll
5223 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005224 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005225 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04005226 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005227 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005228 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005229 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005230}
5231
Paul Mackerrascdc84292008-11-18 19:54:14 +11005232# With path limiting, we mightn't get the actual HEAD commit,
5233# so ask git rev-list what is the first ancestor of HEAD that
5234# touches a file in the path limit.
5235proc get_viewmainhead {view} {
5236 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005237
Paul Mackerrascdc84292008-11-18 19:54:14 +11005238 catch {
5239 set rfd [open [concat | git rev-list -1 $mainheadid \
5240 -- $vfilelimit($view)] r]
5241 set j [reg_instance $rfd]
5242 lappend viewinstances($view) $j
5243 fconfigure $rfd -blocking 0
5244 filerun $rfd [list getviewhead $rfd $j $view]
5245 set viewmainheadid($curview) {}
5246 }
5247}
5248
5249# git rev-list should give us just 1 line to use as viewmainheadid($view)
5250proc getviewhead {fd inst view} {
5251 global viewmainheadid commfd curview viewinstances showlocalchanges
5252
5253 set id {}
5254 if {[gets $fd line] < 0} {
5255 if {![eof $fd]} {
5256 return 1
5257 }
5258 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
5259 set id $line
5260 }
5261 set viewmainheadid($view) $id
5262 close $fd
5263 unset commfd($inst)
5264 set i [lsearch -exact $viewinstances($view) $inst]
5265 if {$i >= 0} {
5266 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
5267 }
5268 if {$showlocalchanges && $id ne {} && $view == $curview} {
5269 doshowlocalchanges
5270 }
5271 return 0
5272}
5273
5274proc doshowlocalchanges {} {
5275 global curview viewmainheadid
5276
5277 if {$viewmainheadid($curview) eq {}} return
5278 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005279 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005280 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005281 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005282 }
5283}
5284
5285proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005286 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005287
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005288 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005289 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005290 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005291 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005292 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005293 }
5294 incr lserial
5295}
5296
Paul Mackerras8f489362007-07-13 19:49:37 +10005297# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005298proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005299 global lserial showlocalchanges vfilelimit curview
Jens Lehmann17f98362014-04-08 21:36:08 +02005300 global hasworktree git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005301
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005302 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005303 incr lserial
Jens Lehmann17f98362014-04-08 21:36:08 +02005304 if {[package vcompare $git_version "1.7.2"] >= 0} {
5305 set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
5306 } else {
5307 set cmd "|git diff-index --cached HEAD"
5308 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005309 if {$vfilelimit($curview) ne {}} {
5310 set cmd [concat $cmd -- $vfilelimit($curview)]
5311 }
5312 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005313 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005314 set i [reg_instance $fd]
5315 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005316}
5317
Alexander Gavrilove439e092008-07-13 16:40:47 +04005318proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005319 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5320 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005321
Paul Mackerras8f489362007-07-13 19:49:37 +10005322 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005323 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005324 if {![eof $fd]} {
5325 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005326 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005327 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005328 }
5329 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005330 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005331
Paul Mackerras24f7a662007-12-19 09:35:33 +11005332 if {$serial != $lserial} {
5333 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005334 }
5335
Paul Mackerras24f7a662007-12-19 09:35:33 +11005336 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005337 set cmd "|git diff-files"
5338 if {$vfilelimit($curview) ne {}} {
5339 set cmd [concat $cmd -- $vfilelimit($curview)]
5340 }
5341 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005342 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005343 set i [reg_instance $fd]
5344 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005345
5346 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005347 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005348 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10005349 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5350 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005351 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005352 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005353 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005354 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005355 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005356 if {[commitinview $nullid $curview]} {
5357 removefakerow $nullid
5358 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005359 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005360 }
5361 return 0
5362}
5363
Alexander Gavrilove439e092008-07-13 16:40:47 +04005364proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005365 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005366 global commitinfo commitdata lserial
5367
5368 set isdiff 1
5369 if {[gets $fd line] < 0} {
5370 if {![eof $fd]} {
5371 return 1
5372 }
5373 set isdiff 0
5374 }
5375 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005376 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005377
Paul Mackerras24f7a662007-12-19 09:35:33 +11005378 if {$serial != $lserial} {
5379 return 0
5380 }
5381
5382 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005383 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005384 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005385 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5386 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005387 if {[commitinview $nullid2 $curview]} {
5388 set p $nullid2
5389 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005390 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005391 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005392 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005393 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005394 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005395 }
5396 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005397}
5398
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005399proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005400 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005401
5402 if {[info exists children($curview,$id)]} {
5403 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005404 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005405 return -1
5406 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005407 if {[rowofcommit $kid] > $row} {
5408 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005409 }
5410 }
5411 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005412 if {[commitinview $id $curview]} {
5413 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005414 }
5415 return -1
5416}
5417
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005418proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005419 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005420
5421 set ret -1
5422 if {[info exists children($curview,$id)]} {
5423 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005424 if {![commitinview $kid $curview]} break
5425 if {[rowofcommit $kid] < $row} {
5426 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005427 }
5428 }
5429 }
5430 return $ret
5431}
5432
Paul Mackerras03800812007-08-29 21:45:21 +10005433proc make_idlist {row} {
5434 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005435 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005436
5437 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5438 if {$r < 0} {
5439 set r 0
5440 }
5441 set ra [expr {$row - $downarrowlen}]
5442 if {$ra < 0} {
5443 set ra 0
5444 }
5445 set rb [expr {$row + $uparrowlen}]
5446 if {$rb > $commitidx($curview)} {
5447 set rb $commitidx($curview)
5448 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005449 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005450 set ids {}
5451 for {} {$r < $ra} {incr r} {
5452 set nextid [lindex $displayorder [expr {$r + 1}]]
5453 foreach p [lindex $parentlist $r] {
5454 if {$p eq $nextid} continue
5455 set rn [nextuse $p $r]
5456 if {$rn >= $row &&
5457 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005458 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005459 }
5460 }
5461 }
5462 for {} {$r < $row} {incr r} {
5463 set nextid [lindex $displayorder [expr {$r + 1}]]
5464 foreach p [lindex $parentlist $r] {
5465 if {$p eq $nextid} continue
5466 set rn [nextuse $p $r]
5467 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005468 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005469 }
5470 }
5471 }
5472 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005473 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005474 while {$r < $rb} {
5475 foreach p [lindex $parentlist $r] {
5476 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005477 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005478 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005479 }
5480 }
5481 incr r
5482 set id [lindex $displayorder $r]
5483 if {$id ne {}} {
5484 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005485 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005486 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005487 }
5488 }
5489 }
5490 set idlist {}
5491 foreach idx [lsort -unique $ids] {
5492 lappend idlist [lindex $idx 1]
5493 }
5494 return $idlist
5495}
5496
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005497proc rowsequal {a b} {
5498 while {[set i [lsearch -exact $a {}]] >= 0} {
5499 set a [lreplace $a $i $i]
5500 }
5501 while {[set i [lsearch -exact $b {}]] >= 0} {
5502 set b [lreplace $b $i $i]
5503 }
5504 return [expr {$a eq $b}]
5505}
5506
5507proc makeupline {id row rend col} {
5508 global rowidlist uparrowlen downarrowlen mingaplen
5509
5510 for {set r $rend} {1} {set r $rstart} {
5511 set rstart [prevuse $id $r]
5512 if {$rstart < 0} return
5513 if {$rstart < $row} break
5514 }
5515 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5516 set rstart [expr {$rend - $uparrowlen - 1}]
5517 }
5518 for {set r $rstart} {[incr r] <= $row} {} {
5519 set idlist [lindex $rowidlist $r]
5520 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5521 set col [idcol $idlist $id $col]
5522 lset rowidlist $r [linsert $idlist $col $id]
5523 changedrow $r
5524 }
5525 }
5526}
5527
Paul Mackerras03800812007-08-29 21:45:21 +10005528proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005529 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005530 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005531 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005532 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005533
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005534 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005535 set idlist {}
5536 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005537 set rm1 [expr {$row - 1}]
5538 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005539 if {$id ne {}} {
5540 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005541 }
5542 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005543 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005544 }
Paul Mackerras03800812007-08-29 21:45:21 +10005545 for {} {$row < $endrow} {incr row} {
5546 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005547 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005548 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005549 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005550 } else {
5551 set id [lindex $displayorder $rm1]
5552 set col [lsearch -exact $idlist $id]
5553 set idlist [lreplace $idlist $col $col]
5554 foreach p [lindex $parentlist $rm1] {
5555 if {[lsearch -exact $idlist $p] < 0} {
5556 set col [idcol $idlist $p $col]
5557 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005558 # if not the first child, we have to insert a line going up
5559 if {$id ne [lindex $children($curview,$p) 0]} {
5560 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005561 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005562 }
5563 }
Paul Mackerras03800812007-08-29 21:45:21 +10005564 set id [lindex $displayorder $row]
5565 if {$row > $downarrowlen} {
5566 set termrow [expr {$row - $downarrowlen - 1}]
5567 foreach p [lindex $parentlist $termrow] {
5568 set i [lsearch -exact $idlist $p]
5569 if {$i < 0} continue
5570 set nr [nextuse $p $termrow]
5571 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5572 set idlist [lreplace $idlist $i $i]
5573 }
5574 }
5575 }
5576 set col [lsearch -exact $idlist $id]
5577 if {$col < 0} {
5578 set col [idcol $idlist $id]
5579 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005580 if {$children($curview,$id) ne {}} {
5581 makeupline $id $rm1 $row $col
5582 }
Paul Mackerras03800812007-08-29 21:45:21 +10005583 }
5584 set r [expr {$row + $uparrowlen - 1}]
5585 if {$r < $commitidx($curview)} {
5586 set x $col
5587 foreach p [lindex $parentlist $r] {
5588 if {[lsearch -exact $idlist $p] >= 0} continue
5589 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005590 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005591 set x [idcol $idlist $p $x]
5592 set idlist [linsert $idlist $x $p]
5593 }
5594 }
5595 if {[incr r] < $commitidx($curview)} {
5596 set p [lindex $displayorder $r]
5597 if {[lsearch -exact $idlist $p] < 0} {
5598 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005599 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005600 set x [idcol $idlist $p $x]
5601 set idlist [linsert $idlist $x $p]
5602 }
5603 }
5604 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005605 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005606 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005607 if {$final && !$viewcomplete($curview) &&
5608 $row + $uparrowlen + $mingaplen + $downarrowlen
5609 >= $commitidx($curview)} {
5610 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005611 }
Paul Mackerras03800812007-08-29 21:45:21 +10005612 set l [llength $rowidlist]
5613 if {$row == $l} {
5614 lappend rowidlist $idlist
5615 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005616 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005617 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005618 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005619 lset rowidlist $row $idlist
5620 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005621 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005622 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005623 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005624 set pad [ntimes [expr {$row - $l}] {}]
5625 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005626 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005627 set rowfinal [concat $rowfinal $pad]
5628 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005629 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005630 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005631 }
5632 return $row
5633}
5634
Paul Mackerras03800812007-08-29 21:45:21 +10005635proc changedrow {row} {
5636 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005637
Paul Mackerras03800812007-08-29 21:45:21 +10005638 set l [llength $rowisopt]
5639 if {$row < $l} {
5640 lset rowisopt $row 0
5641 if {$row + 1 < $l} {
5642 lset rowisopt [expr {$row + 1}] 0
5643 if {$row + 2 < $l} {
5644 lset rowisopt [expr {$row + 2}] 0
5645 }
5646 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005647 }
Paul Mackerras03800812007-08-29 21:45:21 +10005648 set id [lindex $displayorder $row]
5649 if {[info exists iddrawn($id)]} {
5650 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005651 }
5652}
5653
5654proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005655 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005656
5657 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005658 set idlist [lindex $rowidlist $row]
5659 set bef [lrange $idlist 0 [expr {$col - 1}]]
5660 set aft [lrange $idlist $col end]
5661 set i [lsearch -exact $aft {}]
5662 if {$i > 0} {
5663 set aft [lreplace $aft $i $i]
5664 }
5665 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005666 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005667}
5668
5669proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005670 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005671
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005672 if {$row < 1} {
5673 set row 1
5674 }
Paul Mackerras03800812007-08-29 21:45:21 +10005675 for {} {$row < $endrow} {incr row; set col 0} {
5676 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005677 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005678 set y0 [expr {$row - 1}]
5679 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005680 set idlist [lindex $rowidlist $row]
5681 set previdlist [lindex $rowidlist $y0]
5682 if {$idlist eq {} || $previdlist eq {}} continue
5683 if {$ym >= 0} {
5684 set pprevidlist [lindex $rowidlist $ym]
5685 if {$pprevidlist eq {}} continue
5686 } else {
5687 set pprevidlist {}
5688 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005689 set x0 -1
5690 set xm -1
5691 for {} {$col < [llength $idlist]} {incr col} {
5692 set id [lindex $idlist $col]
5693 if {[lindex $previdlist $col] eq $id} continue
5694 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005695 set haspad 1
5696 continue
5697 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005698 set x0 [lsearch -exact $previdlist $id]
5699 if {$x0 < 0} continue
5700 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005701 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005702 set z0 {}
5703 if {$ym >= 0} {
5704 set xm [lsearch -exact $pprevidlist $id]
5705 if {$xm >= 0} {
5706 set z0 [expr {$xm - $x0}]
5707 }
5708 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005709 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005710 # if row y0 is the first child of $id then it's not an arrow
5711 if {[lindex $children($curview,$id) 0] ne
5712 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005713 set isarrow 1
5714 }
5715 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005716 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5717 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5718 set isarrow 1
5719 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005720 # Looking at lines from this row to the previous row,
5721 # make them go straight up if they end in an arrow on
5722 # the previous row; otherwise make them go straight up
5723 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005724 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005725 # Line currently goes left too much;
5726 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005727 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005728 insert_pad $y0 $x0 $npad
5729 if {$y0 > 0} {
5730 optimize_rows $y0 $x0 $row
5731 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005732 set previdlist [lindex $rowidlist $y0]
5733 set x0 [lsearch -exact $previdlist $id]
5734 set z [expr {$x0 - $col}]
5735 if {$z0 ne {}} {
5736 set pprevidlist [lindex $rowidlist $ym]
5737 set xm [lsearch -exact $pprevidlist $id]
5738 set z0 [expr {$xm - $x0}]
5739 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005740 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005741 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005742 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005743 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005744 insert_pad $row $col $npad
5745 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005746 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005747 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005748 set haspad 1
5749 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005750 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005751 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005752 set id [lindex $displayorder $ym]
5753 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005754 if {$xc >= 0} {
5755 set z0 [expr {$xc - $x0}]
5756 }
5757 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005758 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005759 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5760 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005761 incr x0
5762 optimize_rows $y0 $x0 $row
5763 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005764 }
5765 }
5766 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005767 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005768 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005769 set id [lindex $idlist $col]
5770 if {$id eq {}} break
5771 set x0 [lsearch -exact $previdlist $id]
5772 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005773 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005774 set kid [lindex $displayorder $y0]
5775 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005776 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005777 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005778 }
5779 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005780 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005781 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005782 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005783 # isn't the last column
5784 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005785 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005786 lset rowidlist $row $idlist
5787 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005788 }
5789 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005790 }
5791}
5792
5793proc xc {row col} {
5794 global canvx0 linespc
5795 return [expr {$canvx0 + $col * $linespc}]
5796}
5797
5798proc yc {row} {
5799 global canvy0 linespc
5800 return [expr {$canvy0 + $row * $linespc}]
5801}
5802
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005803proc linewidth {id} {
5804 global thickerline lthickness
5805
5806 set wid $lthickness
5807 if {[info exists thickerline] && $id eq $thickerline} {
5808 set wid [expr {2 * $lthickness}]
5809 }
5810 return $wid
5811}
5812
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005813proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005814 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005815 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005816
Paul Mackerras92ed6662007-08-22 22:35:28 +10005817 set kids $children($curview,$id)
5818 if {$kids eq {}} {
5819 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005820 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005821 set ret {}
5822 lappend kids $id
5823 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005824 if {![commitinview $child $curview]} break
5825 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005826 if {![info exists prev]} {
5827 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005828 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005829 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005830 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005831 }
5832 # see if the line extends the whole way from prevrow to row
5833 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5834 [lsearch -exact [lindex $rowidlist \
5835 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5836 # it doesn't, see where it ends
5837 set r [expr {$prevrow + $downarrowlen}]
5838 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5839 while {[incr r -1] > $prevrow &&
5840 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5841 } else {
5842 while {[incr r] <= $row &&
5843 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5844 incr r -1
5845 }
5846 lappend ret $r
5847 # see where it starts up again
5848 set r [expr {$row - $uparrowlen}]
5849 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5850 while {[incr r] < $row &&
5851 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5852 } else {
5853 while {[incr r -1] >= $prevrow &&
5854 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5855 incr r
5856 }
5857 lappend ret $r
5858 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005859 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005860 if {$child eq $id} {
5861 lappend ret $row
5862 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005863 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005864 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005865 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005866 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005867}
5868
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005869proc drawlineseg {id row endrow arrowlow} {
5870 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005871 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005872
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005873 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5874 set le [expr {$row + 1}]
5875 set arrowhigh 1
5876 while {1} {
5877 set c [lsearch -exact [lindex $rowidlist $le] $id]
5878 if {$c < 0} {
5879 incr le -1
5880 break
5881 }
5882 lappend cols $c
5883 set x [lindex $displayorder $le]
5884 if {$x eq $id} {
5885 set arrowhigh 0
5886 break
5887 }
5888 if {[info exists iddrawn($x)] || $le == $endrow} {
5889 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5890 if {$c >= 0} {
5891 lappend cols $c
5892 set arrowhigh 0
5893 }
5894 break
5895 }
5896 incr le
5897 }
5898 if {$le <= $row} {
5899 return $row
5900 }
5901
5902 set lines {}
5903 set i 0
5904 set joinhigh 0
5905 if {[info exists linesegs($id)]} {
5906 set lines $linesegs($id)
5907 foreach li $lines {
5908 set r0 [lindex $li 0]
5909 if {$r0 > $row} {
5910 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5911 set joinhigh 1
5912 }
5913 break
5914 }
5915 incr i
5916 }
5917 }
5918 set joinlow 0
5919 if {$i > 0} {
5920 set li [lindex $lines [expr {$i-1}]]
5921 set r1 [lindex $li 1]
5922 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5923 set joinlow 1
5924 }
5925 }
5926
5927 set x [lindex $cols [expr {$le - $row}]]
5928 set xp [lindex $cols [expr {$le - 1 - $row}]]
5929 set dir [expr {$xp - $x}]
5930 if {$joinhigh} {
5931 set ith [lindex $lines $i 2]
5932 set coords [$canv coords $ith]
5933 set ah [$canv itemcget $ith -arrow]
5934 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5935 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5936 if {$x2 ne {} && $x - $x2 == $dir} {
5937 set coords [lrange $coords 0 end-2]
5938 }
5939 } else {
5940 set coords [list [xc $le $x] [yc $le]]
5941 }
5942 if {$joinlow} {
5943 set itl [lindex $lines [expr {$i-1}] 2]
5944 set al [$canv itemcget $itl -arrow]
5945 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005946 } elseif {$arrowlow} {
5947 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5948 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5949 set arrowlow 0
5950 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005951 }
5952 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5953 for {set y $le} {[incr y -1] > $row} {} {
5954 set x $xp
5955 set xp [lindex $cols [expr {$y - 1 - $row}]]
5956 set ndir [expr {$xp - $x}]
5957 if {$dir != $ndir || $xp < 0} {
5958 lappend coords [xc $y $x] [yc $y]
5959 }
5960 set dir $ndir
5961 }
5962 if {!$joinlow} {
5963 if {$xp < 0} {
5964 # join parent line to first child
5965 set ch [lindex $displayorder $row]
5966 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5967 if {$xc < 0} {
5968 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005969 } elseif {$xc != $x} {
5970 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5971 set d [expr {int(0.5 * $linespc)}]
5972 set x1 [xc $row $x]
5973 if {$xc < $x} {
5974 set x2 [expr {$x1 - $d}]
5975 } else {
5976 set x2 [expr {$x1 + $d}]
5977 }
5978 set y2 [yc $row]
5979 set y1 [expr {$y2 + $d}]
5980 lappend coords $x1 $y1 $x2 $y2
5981 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005982 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5983 } elseif {$xc > $x + 1} {
5984 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5985 }
5986 set x $xc
5987 }
5988 lappend coords [xc $row $x] [yc $row]
5989 } else {
5990 set xn [xc $row $xp]
5991 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005992 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005993 }
5994 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005995 assigncolor $id
5996 set t [$canv create line $coords -width [linewidth $id] \
5997 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5998 $canv lower $t
5999 bindline $t $id
6000 set lines [linsert $lines $i [list $row $le $t]]
6001 } else {
6002 $canv coords $ith $coords
6003 if {$arrow ne $ah} {
6004 $canv itemconf $ith -arrow $arrow
6005 }
6006 lset lines $i 0 $row
6007 }
6008 } else {
6009 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
6010 set ndir [expr {$xo - $xp}]
6011 set clow [$canv coords $itl]
6012 if {$dir == $ndir} {
6013 set clow [lrange $clow 2 end]
6014 }
6015 set coords [concat $coords $clow]
6016 if {!$joinhigh} {
6017 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006018 } else {
6019 # coalesce two pieces
6020 $canv delete $ith
6021 set b [lindex $lines [expr {$i-1}] 0]
6022 set e [lindex $lines $i 1]
6023 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
6024 }
6025 $canv coords $itl $coords
6026 if {$arrow ne $al} {
6027 $canv itemconf $itl -arrow $arrow
6028 }
6029 }
6030
6031 set linesegs($id) $lines
6032 return $le
6033}
6034
6035proc drawparentlinks {id row} {
6036 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10006037 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006038
6039 set rowids [lindex $rowidlist $row]
6040 set col [lsearch -exact $rowids $id]
6041 if {$col < 0} return
6042 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006043 set row2 [expr {$row + 1}]
6044 set x [xc $row $col]
6045 set y [yc $row]
6046 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10006047 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006048 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006049 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006050 # rmx = right-most X coord used
6051 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006052 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11006053 set i [lsearch -exact $ids $p]
6054 if {$i < 0} {
6055 puts "oops, parent $p of $id not in list"
6056 continue
6057 }
6058 set x2 [xc $row2 $i]
6059 if {$x2 > $rmx} {
6060 set rmx $x2
6061 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10006062 set j [lsearch -exact $rowids $p]
6063 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11006064 # drawlineseg will do this one for us
6065 continue
6066 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006067 assigncolor $p
6068 # should handle duplicated parents here...
6069 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006070 if {$i != $col} {
6071 # if attaching to a vertical segment, draw a smaller
6072 # slant for visual distinctness
6073 if {$i == $j} {
6074 if {$i < $col} {
6075 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
6076 } else {
6077 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
6078 }
6079 } elseif {$i < $col && $i < $j} {
6080 # segment slants towards us already
6081 lappend coords [xc $row $j] $y
6082 } else {
6083 if {$i < $col - 1} {
6084 lappend coords [expr {$x2 + $linespc}] $y
6085 } elseif {$i > $col + 1} {
6086 lappend coords [expr {$x2 - $linespc}] $y
6087 }
6088 lappend coords $x2 $y2
6089 }
6090 } else {
6091 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006092 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006093 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006094 -fill $colormap($p) -tags lines.$p]
6095 $canv lower $t
6096 bindline $t $p
6097 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006098 if {$rmx > [lindex $idpos($id) 1]} {
6099 lset idpos($id) 1 $rmx
6100 redrawtags $id
6101 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006102}
6103
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006104proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006105 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006106
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006107 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006108}
6109
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006110proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006111 global linespc canv canv2 canv3 fgcolor curview
6112 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006113 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10006114 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006115 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05006116 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006117 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
6118 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006119
Linus Torvalds1407ade2008-02-09 14:02:07 -08006120 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006121 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006122 if {$id eq $nullid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006123 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10006124 } elseif {$id eq $nullid2} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006125 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006126 } elseif {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006127 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006128 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006129 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006130 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006131 set x [xc $row $col]
6132 set y [yc $row]
6133 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006134 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006135 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
6136 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006137 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006138 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006139 # triangle pointing left for left-side commits
6140 set t [$canv create polygon \
6141 [expr {$x - $orad}] $y \
6142 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
6143 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006144 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006145 } else {
6146 # triangle pointing right for right-side commits
6147 set t [$canv create polygon \
6148 [expr {$x + $orad - 1}] $y \
6149 [expr {$x - $orad}] [expr {$y - $orad}] \
6150 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006151 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006152 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006153 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006154 $canv raise $t
6155 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006156 set rmx [llength [lindex $rowidlist $row]]
6157 set olds [lindex $parentlist $row]
6158 if {$olds ne {}} {
6159 set nextids [lindex $rowidlist [expr {$row + 1}]]
6160 foreach p $olds {
6161 set i [lsearch -exact $nextids $p]
6162 if {$i > $rmx} {
6163 set rmx $i
6164 }
6165 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006166 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006167 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006168 set rowtextx($row) $xt
6169 set idpos($id) [list $x $xt $y]
6170 if {[info exists idtags($id)] || [info exists idheads($id)]
6171 || [info exists idotherrefs($id)]} {
6172 set xt [drawtags $id $x $xt $y]
6173 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006174 if {[lindex $commitinfo($id) 6] > 0} {
6175 set xt [drawnotesign $xt $y]
6176 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006177 set headline [lindex $commitinfo($id) 0]
6178 set name [lindex $commitinfo($id) 1]
6179 set date [lindex $commitinfo($id) 2]
6180 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006181 set font mainfont
6182 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006183 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006184 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006185 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006186 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006187 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006188 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006189 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006190 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006191 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006192 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
6193 -text $headline -font $font -tags text]
6194 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6195 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
6196 -text $name -font $nfont -tags text]
6197 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
6198 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006199 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006200 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006201 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006202 if {[info exists markedid] && $markedid eq $id} {
6203 make_idmark $id
6204 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006205 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006206 if {$xr > $canvxmax} {
6207 set canvxmax $xr
6208 setcanvscroll
6209 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006210}
6211
6212proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006213 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006214 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006215 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006216 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006217 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006218 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006219
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006220 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006221
6222 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006223 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006224 askvhighlight $row $id
6225 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006226 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006227 askfilehighlight $row $id
6228 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006229 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006230 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006231 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006232 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10006233 askrelhighlight $row $id
6234 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006235 if {![info exists iddrawn($id)]} {
6236 set col [lsearch -exact [lindex $rowidlist $row] $id]
6237 if {$col < 0} {
6238 puts "oops, row $row id $id not in list"
6239 return
6240 }
6241 if {![info exists commitinfo($id)]} {
6242 getcommit $id
6243 }
6244 assigncolor $id
6245 drawcmittext $id $row $col
6246 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10006247 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006248 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006249 if {$markingmatches} {
6250 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006251 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006252}
6253
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006254proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006255 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006256 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006257
6258 if {$row < 0} {
6259 set row 0
6260 }
6261 if {$endrow eq {}} {
6262 set endrow $row
6263 }
6264 if {$endrow >= $numcommits} {
6265 set endrow [expr {$numcommits - 1}]
6266 }
6267
Paul Mackerras03800812007-08-29 21:45:21 +10006268 set rl1 [expr {$row - $downarrowlen - 3}]
6269 if {$rl1 < 0} {
6270 set rl1 0
6271 }
6272 set ro1 [expr {$row - 3}]
6273 if {$ro1 < 0} {
6274 set ro1 0
6275 }
6276 set r2 [expr {$endrow + $uparrowlen + 3}]
6277 if {$r2 > $numcommits} {
6278 set r2 $numcommits
6279 }
6280 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006281 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10006282 if {$rl1 < $r} {
6283 layoutrows $rl1 $r
6284 }
6285 set rl1 [expr {$r + 1}]
6286 }
6287 }
6288 if {$rl1 < $r} {
6289 layoutrows $rl1 $r
6290 }
6291 optimize_rows $ro1 0 $r2
6292 if {$need_redisplay || $nrows_drawn > 2000} {
6293 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006294 }
6295
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006296 # make the lines join to already-drawn rows either side
6297 set r [expr {$row - 1}]
6298 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
6299 set r $row
6300 }
6301 set er [expr {$endrow + 1}]
6302 if {$er >= $numcommits ||
6303 ![info exists iddrawn([lindex $displayorder $er])]} {
6304 set er $endrow
6305 }
6306 for {} {$r <= $er} {incr r} {
6307 set id [lindex $displayorder $r]
6308 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006309 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006310 if {$r == $er} break
6311 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006312 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006313 drawparentlinks $id $r
6314
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006315 set rowids [lindex $rowidlist $r]
6316 foreach lid $rowids {
6317 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006318 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006319 if {$lid eq $id} {
6320 # see if this is the first child of any of its parents
6321 foreach p [lindex $parentlist $r] {
6322 if {[lsearch -exact $rowids $p] < 0} {
6323 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006324 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006325 }
6326 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006327 } else {
6328 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006329 }
6330 }
6331 }
6332}
6333
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006334proc undolayout {row} {
6335 global uparrowlen mingaplen downarrowlen
6336 global rowidlist rowisopt rowfinal need_redisplay
6337
6338 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6339 if {$r < 0} {
6340 set r 0
6341 }
6342 if {[llength $rowidlist] > $r} {
6343 incr r -1
6344 set rowidlist [lrange $rowidlist 0 $r]
6345 set rowfinal [lrange $rowfinal 0 $r]
6346 set rowisopt [lrange $rowisopt 0 $r]
6347 set need_redisplay 1
6348 run drawvisible
6349 }
6350}
6351
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006352proc drawvisible {} {
6353 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006354 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006355
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006356 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006357 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006358 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006359 set f0 [lindex $fs 0]
6360 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006361 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006362 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006363
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006364 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11006365 if {[commitinview $targetid $curview]} {
6366 set r [rowofcommit $targetid]
6367 if {$r != $targetrow} {
6368 # Fix up the scrollregion and change the scrolling position
6369 # now that our target row has moved.
6370 set diff [expr {($r - $targetrow) * $linespc}]
6371 set targetrow $r
6372 setcanvscroll
6373 set ymax [lindex [$canv cget -scrollregion] 3]
6374 incr y0 $diff
6375 incr y1 $diff
6376 set f0 [expr {$y0 / $ymax}]
6377 set f1 [expr {$y1 / $ymax}]
6378 allcanvs yview moveto $f0
6379 $cscroll set $f0 $f1
6380 set need_redisplay 1
6381 }
6382 } else {
6383 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006384 }
6385 }
6386
6387 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6388 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6389 if {$endrow >= $vrowmod($curview)} {
6390 update_arcrows $curview
6391 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006392 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006393 $row <= $selectedline && $selectedline <= $endrow} {
6394 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006395 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006396 set targetrow [expr {int(($row + $endrow) / 2)}]
6397 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006398 if {[info exists targetrow]} {
6399 if {$targetrow >= $numcommits} {
6400 set targetrow [expr {$numcommits - 1}]
6401 }
6402 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006403 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006404 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006405}
6406
6407proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006408 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006409 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006410 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006411
6412 allcanvs delete all
Paul Mackerras009409f2015-05-02 20:53:36 +10006413 unset -nocomplain iddrawn
6414 unset -nocomplain linesegs
6415 unset -nocomplain linehtag
6416 unset -nocomplain linentag
6417 unset -nocomplain linedtag
Paul Mackerras28593d32008-11-13 23:01:46 +11006418 set boldids {}
6419 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10006420 unset -nocomplain vhighlights
6421 unset -nocomplain fhighlights
6422 unset -nocomplain nhighlights
6423 unset -nocomplain rhighlights
Paul Mackerras03800812007-08-29 21:45:21 +10006424 set need_redisplay 0
6425 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006426}
6427
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006428proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006429 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006430
6431 set cross {}
6432 set ccross {}
6433 foreach {s e} [rowranges $id] {
6434 if {$e >= $numcommits} {
6435 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006436 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006437 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006438 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006439 set x [lsearch -exact [lindex $rowidlist $row] $id]
6440 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006441 set olds [lindex $parentlist $row]
6442 set kid [lindex $displayorder $row]
6443 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6444 if {$kidx < 0} continue
6445 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6446 foreach p $olds {
6447 set px [lsearch -exact $nextrow $p]
6448 if {$px < 0} continue
6449 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6450 if {[lsearch -exact $ccross $p] >= 0} continue
6451 if {$x == $px + ($kidx < $px? -1: 1)} {
6452 lappend ccross $p
6453 } elseif {[lsearch -exact $cross $p] < 0} {
6454 lappend cross $p
6455 }
6456 }
6457 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006458 }
6459 }
6460 return [concat $ccross {{}} $cross]
6461}
6462
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006463proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006464 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006465 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006466
Paul Mackerras418c4c72006-02-07 09:10:18 +11006467 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006468 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006469 if {[info exists children($curview,$id)]} {
6470 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006471 } else {
6472 set kids {}
6473 }
6474 if {[llength $kids] == 1} {
6475 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006476 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006477 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006478 set colormap($id) $colormap($child)
6479 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006480 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006481 }
6482 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006483 set origbad {}
6484 foreach x [findcrossings $id] {
6485 if {$x eq {}} {
6486 # delimiter between corner crossings and other crossings
6487 if {[llength $badcolors] >= $ncolors - 1} break
6488 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006489 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006490 if {[info exists colormap($x)]
6491 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6492 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006493 }
6494 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006495 if {[llength $badcolors] >= $ncolors} {
6496 set badcolors $origbad
6497 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006498 set origbad $badcolors
6499 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006500 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006501 if {[info exists colormap($child)]
6502 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6503 lappend badcolors $colormap($child)
6504 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006505 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006506 if {[info exists colormap($p)]
6507 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6508 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006509 }
6510 }
6511 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006512 if {[llength $badcolors] >= $ncolors} {
6513 set badcolors $origbad
6514 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006515 }
6516 for {set i 0} {$i <= $ncolors} {incr i} {
6517 set c [lindex $colors $nextcolor]
6518 if {[incr nextcolor] >= $ncolors} {
6519 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006520 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006521 if {[lsearch -exact $badcolors $c]} break
6522 }
6523 set colormap($id) $c
6524}
6525
Paul Mackerrasa823a912005-06-21 10:01:38 +10006526proc bindline {t id} {
6527 global canv
6528
Paul Mackerrasa823a912005-06-21 10:01:38 +10006529 $canv bind $t <Enter> "lineenter %x %y $id"
6530 $canv bind $t <Motion> "linemotion %x %y $id"
6531 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006532 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006533}
6534
Paul Mackerras4399fe32013-01-03 10:10:31 +11006535proc graph_pane_width {} {
6536 global use_ttk
6537
6538 if {$use_ttk} {
6539 set g [.tf.histframe.pwclist sashpos 0]
6540 } else {
6541 set g [.tf.histframe.pwclist sash coord 0]
6542 }
6543 return [lindex $g 0]
6544}
6545
6546proc totalwidth {l font extra} {
6547 set tot 0
6548 foreach str $l {
6549 set tot [expr {$tot + [font measure $font $str] + $extra}]
6550 }
6551 return $tot
6552}
6553
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006554proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006555 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006556 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006557 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006558 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6559 global tagbgcolor tagfgcolor tagoutlinecolor
6560 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006561
6562 set marks {}
6563 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006564 set nheads 0
Paul Mackerras4399fe32013-01-03 10:10:31 +11006565 set singletag 0
6566 set maxtags 3
6567 set maxtagpct 25
6568 set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
6569 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
6570 set extra [expr {$delta + $lthickness + $linespc}]
6571
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006572 if {[info exists idtags($id)]} {
6573 set marks $idtags($id)
6574 set ntags [llength $marks]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006575 if {$ntags > $maxtags ||
6576 [totalwidth $marks mainfont $extra] > $maxwidth} {
6577 # show just a single "n tags..." tag
6578 set singletag 1
6579 if {$ntags == 1} {
6580 set marks [list "tag..."]
6581 } else {
6582 set marks [list [format "%d tags..." $ntags]]
6583 }
6584 set ntags 1
6585 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006586 }
6587 if {[info exists idheads($id)]} {
6588 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006589 set nheads [llength $idheads($id)]
6590 }
6591 if {[info exists idotherrefs($id)]} {
6592 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006593 }
6594 if {$marks eq {}} {
6595 return $xt
6596 }
6597
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006598 set yt [expr {$y1 - 0.5 * $linespc}]
6599 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006600 set xvals {}
6601 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006602 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006603 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006604 incr i
6605 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006606 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006607 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006608 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006609 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006610 lappend xvals $xt
6611 lappend wvals $wid
Paul Mackerras4399fe32013-01-03 10:10:31 +11006612 set xt [expr {$xt + $wid + $extra}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006613 }
6614 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006615 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006616 $canv lower $t
6617 foreach tag $marks x $xvals wid $wvals {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006618 set tag_quoted [string map {% %%} $tag]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006619 set xl [expr {$x + $delta}]
6620 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006621 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006622 if {[incr ntags -1] >= 0} {
6623 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006624 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6625 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006626 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6627 -tags tag.$id]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006628 if {$singletag} {
6629 set tagclick [list showtags $id 1]
6630 } else {
6631 set tagclick [list showtag $tag_quoted 1]
6632 }
6633 $canv bind $t <1> $tagclick
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006634 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006635 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006636 # draw a head or other ref
6637 if {[incr nheads -1] >= 0} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006638 set col $headbgcolor
Paul Mackerras8a485712006-07-06 10:21:23 +10006639 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006640 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006641 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006642 } else {
6643 set col "#ddddff"
6644 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006645 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006646 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006647 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006648 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006649 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006650 set xi [expr {$x + 1}]
6651 set yti [expr {$yt + 1}]
6652 set xri [expr {$x + $rwid}]
6653 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006654 -width 0 -fill $remotebgcolor -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006655 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006656 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006657 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006658 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006659 if {$ntags >= 0} {
Paul Mackerras4399fe32013-01-03 10:10:31 +11006660 $canv bind $t <1> $tagclick
Paul Mackerras10299152006-08-02 09:52:01 +10006661 } elseif {$nheads >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006662 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
Paul Mackerras106288c2005-08-19 23:11:39 +10006663 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006664 }
6665 return $xt
6666}
6667
Raphael Zimmerer36242492011-04-19 22:37:09 +02006668proc drawnotesign {xt y} {
6669 global linespc canv fgcolor
6670
6671 set orad [expr {$linespc / 3}]
6672 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
6673 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6674 -fill yellow -outline $fgcolor -width 1 -tags circle]
6675 set xt [expr {$xt + $orad * 3}]
6676 return $xt
6677}
6678
Paul Mackerras8d858d12005-08-05 09:52:16 +10006679proc xcoord {i level ln} {
6680 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006681
Paul Mackerras8d858d12005-08-05 09:52:16 +10006682 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6683 if {$i > 0 && $i == $level} {
6684 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6685 } elseif {$i > $level} {
6686 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6687 }
6688 return $x
6689}
6690
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006691proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006692 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006693
6694 clear_display
Marc Branchaud9922c5a2015-04-07 11:51:51 -04006695 set_window_title
Paul Mackerras9c311b32007-10-04 22:27:13 +10006696 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006697 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006698}
6699
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006700# Don't change the text pane cursor if it is currently the hand cursor,
6701# showing that we are over a sha1 ID link.
6702proc settextcursor {c} {
6703 global ctext curtextcursor
6704
6705 if {[$ctext cget -cursor] == $curtextcursor} {
6706 $ctext config -cursor $c
6707 }
6708 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006709}
6710
Paul Mackerrasa137a902007-10-23 21:12:49 +10006711proc nowbusy {what {name {}}} {
6712 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006713
6714 if {[array names isbusy] eq {}} {
6715 . config -cursor watch
6716 settextcursor watch
6717 }
6718 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006719 set busyname($what) $name
6720 if {$name ne {}} {
6721 $statusw conf -text $name
6722 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006723}
6724
6725proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006726 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006727
Paul Mackerrasa137a902007-10-23 21:12:49 +10006728 catch {
6729 unset isbusy($what)
6730 if {$busyname($what) ne {} &&
6731 [$statusw cget -text] eq $busyname($what)} {
6732 $statusw conf -text {}
6733 }
6734 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006735 if {[array names isbusy] eq {}} {
6736 . config -cursor $maincursor
6737 settextcursor $textcursor
6738 }
6739}
6740
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006741proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006742 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006743 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006744 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006745 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006746 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006747 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006748 set f [string tolower $f]
6749 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006750 }
6751 set matches {}
6752 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006753 set l [string length $fs]
6754 while {[set j [string first $fs $f $i]] >= 0} {
6755 lappend matches [list $j [expr {$j+$l-1}]]
6756 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006757 }
6758 }
6759 return $matches
6760}
6761
Paul Mackerrascca5d942007-10-27 21:16:56 +10006762proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006763 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006764 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006765
Paul Mackerrascca5d942007-10-27 21:16:56 +10006766 if {[info exists find_dirn]} {
6767 if {$find_dirn == $dirn} return
6768 stopfinding
6769 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006770 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006771 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006772 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006773 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006774 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006775 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006776 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006777 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006778 nowbusy finding [mc "Searching"]
6779 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006780 after cancel do_file_hl $fh_serial
6781 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006782 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006783 set find_dirn $dirn
6784 set findallowwrap $wrap
6785 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006786}
6787
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006788proc stopfinding {} {
6789 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006790
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006791 if {[info exists find_dirn]} {
6792 unset find_dirn
6793 unset findcurline
6794 notbusy finding
6795 set fprogcoord 0
6796 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006797 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006798 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006799}
6800
6801proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006802 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006803 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006804 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006805 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006806
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006807 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006808 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006809 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006810 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006811 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006812 set moretodo 0
6813 if {$find_dirn > 0} {
6814 incr l
6815 if {$l >= $numcommits} {
6816 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006817 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006818 if {$l <= $findstartline} {
6819 set lim [expr {$findstartline + 1}]
6820 } else {
6821 set lim $numcommits
6822 set moretodo $findallowwrap
6823 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006824 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006825 if {$l == 0} {
6826 set l $numcommits
6827 }
6828 incr l -1
6829 if {$l >= $findstartline} {
6830 set lim [expr {$findstartline - 1}]
6831 } else {
6832 set lim -1
6833 set moretodo $findallowwrap
6834 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006835 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006836 set n [expr {($lim - $l) * $find_dirn}]
6837 if {$n > 500} {
6838 set n 500
6839 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006840 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006841 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6842 update_arcrows $curview
6843 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006844 set found 0
6845 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006846 set ai [bsearch $vrownum($curview) $l]
6847 set a [lindex $varcorder($curview) $ai]
6848 set arow [lindex $vrownum($curview) $ai]
6849 set ids [lindex $varccommits($curview,$a)]
6850 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006851 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006852 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006853 if {$l < $arow || $l >= $arowend} {
6854 incr ai $find_dirn
6855 set a [lindex $varcorder($curview) $ai]
6856 set arow [lindex $vrownum($curview) $ai]
6857 set ids [lindex $varccommits($curview,$a)]
6858 set arowend [expr {$arow + [llength $ids]}]
6859 }
6860 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006861 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006862 if {![info exists commitdata($id)] ||
6863 ![doesmatch $commitdata($id)]} {
6864 continue
6865 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006866 if {![info exists commitinfo($id)]} {
6867 getcommit $id
6868 }
6869 set info $commitinfo($id)
6870 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04006871 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01006872 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006873 [doesmatch $f]} {
6874 set found 1
6875 break
6876 }
6877 }
6878 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006879 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006880 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006881 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006882 if {$l < $arow || $l >= $arowend} {
6883 incr ai $find_dirn
6884 set a [lindex $varcorder($curview) $ai]
6885 set arow [lindex $vrownum($curview) $ai]
6886 set ids [lindex $varccommits($curview,$a)]
6887 set arowend [expr {$arow + [llength $ids]}]
6888 }
6889 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006890 if {![info exists fhighlights($id)]} {
6891 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006892 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006893 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006894 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006895 set found $domore
6896 break
6897 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006898 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006899 if {$domore} {
6900 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006901 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006902 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006903 }
6904 }
6905 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006906 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006907 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006908 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006909 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006910 set fprogcoord 0
6911 adjustprogress
6912 if {$found} {
6913 findselectline $l
6914 } else {
6915 bell
6916 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006917 return 0
6918 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006919 if {!$domore} {
6920 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006921 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006922 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006923 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006924 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006925 if {$n < 0} {
6926 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006927 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006928 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6929 adjustprogress
6930 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006931}
6932
6933proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006934 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006935
Paul Mackerras8b39e042008-12-02 09:02:46 +11006936 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006937 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006938 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006939 if {$markingmatches &&
6940 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006941 # highlight the matches in the comments
6942 set f [$ctext get 1.0 $commentend]
6943 set matches [findmatches $f]
6944 foreach match $matches {
6945 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006946 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006947 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6948 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006949 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006950 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006951}
6952
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006953# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006954proc markmatches {canv l str tag matches font row} {
6955 global selectedline
6956
Paul Mackerras98f350e2005-05-15 05:56:51 +00006957 set bbox [$canv bbox $tag]
6958 set x0 [lindex $bbox 0]
6959 set y0 [lindex $bbox 1]
6960 set y1 [lindex $bbox 3]
6961 foreach match $matches {
6962 set start [lindex $match 0]
6963 set end [lindex $match 1]
6964 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006965 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6966 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6967 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6968 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006969 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006970 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006971 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006972 $canv raise $t secsel
6973 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006974 }
6975}
6976
6977proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006978 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006979
Paul Mackerras98f350e2005-05-15 05:56:51 +00006980 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006981 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006982 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006983}
6984
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006985proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006986 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006987 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006988 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006989 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006990 set yfrac [lindex [$canv yview] 0]
6991 set y [expr {$y + $yfrac * $ymax}]
6992 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6993 if {$l < 0} {
6994 set l 0
6995 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006996 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006997 set xmax [lindex [$canv cget -scrollregion] 2]
6998 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6999 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007000 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00007001 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007002 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007003}
7004
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007005proc commit_descriptor {p} {
7006 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10007007 if {![info exists commitinfo($p)]} {
7008 getcommit $p
7009 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007010 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10007011 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007012 set l [lindex $commitinfo($p) 0]
7013 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007014 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007015}
7016
Paul Mackerras106288c2005-08-19 23:11:39 +10007017# append some text to the ctext widget, and make any SHA1 ID
7018# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007019proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007020 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10007021
7022 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007023 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007024 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10007025 foreach l $links {
7026 set s [lindex $l 0]
7027 set e [lindex $l 1]
7028 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10007029 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10007030 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007031 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10007032 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007033 incr linknum
7034 }
Paul Mackerras97645682007-08-23 22:24:38 +10007035}
7036
7037proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007038 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007039 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10007040
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007041 if {[string range $id 0 1] eq "-g"} {
7042 set id [string range $id 2 end]
7043 }
7044
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007045 set known 0
7046 if {[string length $id] < 40} {
7047 set matches [longid $id]
7048 if {[llength $matches] > 0} {
7049 if {[llength $matches] > 1} return
7050 set known 1
7051 set id [lindex $matches 0]
7052 }
7053 } else {
7054 set known [commitinview $id $curview]
7055 }
7056 if {$known} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007057 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007058 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10007059 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7060 $ctext tag bind $lk <Leave> {linkcursor %W -1}
7061 } else {
7062 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007063 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10007064 }
7065}
7066
Paul Mackerras6f63fc12009-04-21 22:22:31 +10007067proc appendshortlink {id {pre {}} {post {}}} {
7068 global ctext linknum
7069
7070 $ctext insert end $pre
7071 $ctext tag delete link$linknum
7072 $ctext insert end [string range $id 0 7] link$linknum
7073 $ctext insert end $post
7074 setlink $id link$linknum
7075 incr linknum
7076}
7077
Paul Mackerras97645682007-08-23 22:24:38 +10007078proc makelink {id} {
7079 global pendinglinks
7080
7081 if {![info exists pendinglinks($id)]} return
7082 foreach lk $pendinglinks($id) {
7083 setlink $id $lk
7084 }
7085 unset pendinglinks($id)
7086}
7087
7088proc linkcursor {w inc} {
7089 global linkentercount curtextcursor
7090
7091 if {[incr linkentercount $inc] > 0} {
7092 $w configure -cursor hand2
7093 } else {
7094 $w configure -cursor $curtextcursor
7095 if {$linkentercount < 0} {
7096 set linkentercount 0
7097 }
7098 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007099}
7100
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007101proc viewnextline {dir} {
7102 global canv linespc
7103
7104 $canv delete hover
7105 set ymax [lindex [$canv cget -scrollregion] 3]
7106 set wnow [$canv yview]
7107 set wtop [expr {[lindex $wnow 0] * $ymax}]
7108 set newtop [expr {$wtop + $dir * $linespc}]
7109 if {$newtop < 0} {
7110 set newtop 0
7111 } elseif {$newtop > $ymax} {
7112 set newtop $ymax
7113 }
7114 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7115}
7116
Paul Mackerrasef030b82006-06-04 11:50:38 +10007117# add a list of tag or branch names at position pos
7118# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10007119proc appendrefs {pos ids var} {
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007120 global ctext linknum curview $var maxrefs visiblerefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007121
Paul Mackerrasef030b82006-06-04 11:50:38 +10007122 if {[catch {$ctext index $pos}]} {
7123 return 0
7124 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007125 $ctext conf -state normal
7126 $ctext delete $pos "$pos lineend"
7127 set tags {}
7128 foreach id $ids {
7129 foreach tag [set $var\($id\)] {
7130 lappend tags [list $tag $id]
7131 }
7132 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007133
7134 set sep {}
7135 set tags [lsort -index 0 -decreasing $tags]
7136 set nutags 0
7137
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007138 if {[llength $tags] > $maxrefs} {
Paul Mackerras386befb2013-01-02 15:25:29 +11007139 # If we are displaying heads, and there are too many,
7140 # see if there are some important heads to display.
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007141 # Currently that are the current head and heads listed in $visiblerefs option
Paul Mackerras386befb2013-01-02 15:25:29 +11007142 set itags {}
7143 if {$var eq "idheads"} {
7144 set utags {}
7145 foreach ti $tags {
7146 set hname [lindex $ti 0]
7147 set id [lindex $ti 1]
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007148 if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
Paul Mackerras386befb2013-01-02 15:25:29 +11007149 [llength $itags] < $maxrefs} {
7150 lappend itags $ti
7151 } else {
7152 lappend utags $ti
7153 }
7154 }
7155 set tags $utags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007156 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007157 if {$itags ne {}} {
7158 set str [mc "and many more"]
7159 set sep " "
7160 } else {
7161 set str [mc "many"]
7162 }
7163 $ctext insert $pos "$str ([llength $tags])"
7164 set nutags [llength $tags]
7165 set tags $itags
7166 }
7167
7168 foreach ti $tags {
7169 set id [lindex $ti 1]
7170 set lk link$linknum
7171 incr linknum
7172 $ctext tag delete $lk
7173 $ctext insert $pos $sep
7174 $ctext insert $pos [lindex $ti 0] $lk
7175 setlink $id $lk
7176 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007177 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11007178 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007179 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11007180 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007181}
7182
7183# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10007184proc dispneartags {delay} {
7185 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007186
Paul Mackerras94b4a692008-05-20 20:51:06 +10007187 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007188 after cancel dispnexttag
7189 if {$delay} {
7190 after 200 dispnexttag
7191 set tagphase -1
7192 } else {
7193 after idle dispnexttag
7194 set tagphase 0
7195 }
7196}
7197
7198proc dispnexttag {} {
7199 global selectedline currentid showneartags tagphase ctext
7200
Paul Mackerras94b4a692008-05-20 20:51:06 +10007201 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007202 switch -- $tagphase {
7203 0 {
7204 set dtags [desctags $currentid]
7205 if {$dtags ne {}} {
7206 appendrefs precedes $dtags idtags
7207 }
7208 }
7209 1 {
7210 set atags [anctags $currentid]
7211 if {$atags ne {}} {
7212 appendrefs follows $atags idtags
7213 }
7214 }
7215 2 {
7216 set dheads [descheads $currentid]
7217 if {$dheads ne {}} {
7218 if {[appendrefs branch $dheads idheads] > 1
7219 && [$ctext get "branch -3c"] eq "h"} {
7220 # turn "Branch" into "Branches"
7221 $ctext conf -state normal
7222 $ctext insert "branch -2c" "es"
7223 $ctext conf -state disabled
7224 }
7225 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007226 }
7227 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007228 if {[incr tagphase] <= 2} {
7229 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007230 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007231}
7232
Paul Mackerras28593d32008-11-13 23:01:46 +11007233proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007234 global linehtag linentag linedtag canv canv2 canv3
7235
Paul Mackerras28593d32008-11-13 23:01:46 +11007236 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007237 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007238 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007239 -tags secsel -fill [$canv cget -selectbackground]]
7240 $canv lower $t
7241 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007242 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007243 -tags secsel -fill [$canv2 cget -selectbackground]]
7244 $canv2 lower $t
7245 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007246 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007247 -tags secsel -fill [$canv3 cget -selectbackground]]
7248 $canv3 lower $t
7249}
7250
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007251proc make_idmark {id} {
7252 global linehtag canv fgcolor
7253
7254 if {![info exists linehtag($id)]} return
7255 $canv delete markid
7256 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
7257 -tags markid -outline $fgcolor]
7258 $canv raise $t
7259}
7260
Max Kirillov4135d362014-04-05 23:38:50 +03007261proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007262 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007263 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007264 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007265 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007266 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007267 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007268 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007269 global autoselect autosellen jump_to_here
Thomas Rast9403bd02013-11-16 18:37:43 +01007270 global vinlinediff
Paul Mackerrasd6982062005-08-06 22:06:06 +10007271
Paul Mackerras009409f2015-05-02 20:53:36 +10007272 unset -nocomplain pending_select
Paul Mackerras84ba7342005-06-17 00:12:26 +00007273 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007274 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007275 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007276 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007277 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007278 set id [commitonrow $l]
7279 set targetid $id
7280 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007281 set selectedline $l
7282 set currentid $id
7283 if {$lastscrollrows < $numcommits} {
7284 setcanvscroll
7285 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007286
Max Kirillov4135d362014-04-05 23:38:50 +03007287 if {$cmitmode ne "patch" && $switch_to_patch} {
7288 set cmitmode "patch"
7289 }
7290
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007291 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007292 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007293 set ytop [expr {$y - $linespc - 1}]
7294 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007295 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007296 set wtop [expr {[lindex $wnow 0] * $ymax}]
7297 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007298 set wh [expr {$wbot - $wtop}]
7299 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007300 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00007301 if {$ybot < $wtop} {
7302 set newtop [expr {$y - $wh / 2.0}]
7303 } else {
7304 set newtop $ytop
7305 if {$newtop > $wtop - $linespc} {
7306 set newtop [expr {$wtop - $linespc}]
7307 }
Paul Mackerras17386062005-05-18 22:51:00 +00007308 }
Paul Mackerras58422152005-05-19 10:56:42 +00007309 } elseif {$ybot > $wbot} {
7310 if {$ytop > $wbot} {
7311 set newtop [expr {$y - $wh / 2.0}]
7312 } else {
7313 set newtop [expr {$ybot - $wh}]
7314 if {$newtop < $wtop + $linespc} {
7315 set newtop [expr {$wtop + $linespc}]
7316 }
Paul Mackerras17386062005-05-18 22:51:00 +00007317 }
Paul Mackerras58422152005-05-19 10:56:42 +00007318 }
7319 if {$newtop != $wtop} {
7320 if {$newtop < 0} {
7321 set newtop 0
7322 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007323 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007324 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007325 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007326
Paul Mackerras28593d32008-11-13 23:01:46 +11007327 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007328
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007329 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007330 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007331 }
7332
Paul Mackerras98f350e2005-05-15 05:56:51 +00007333 $sha1entry delete 0 end
7334 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007335 if {$autoselect} {
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007336 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007337 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007338 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007339
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007340 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007341 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007342 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007343 if {![info exists commitinfo($id)]} {
7344 getcommit $id
7345 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007346 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007347 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007348 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007349 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007350 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007351 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007352 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007353 foreach tag $idtags($id) {
7354 $ctext insert end " $tag"
7355 }
7356 $ctext insert end "\n"
7357 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007358
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007359 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007360 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007361 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007362 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007363 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007364 if {$np >= $mergemax} {
7365 set tag mmax
7366 } else {
7367 set tag m$np
7368 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007369 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007370 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007371 incr np
7372 }
7373 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007374 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007375 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007376 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007377 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007378
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007379 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007380 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007381 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007382
7383 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007384 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007385 if {$showneartags} {
7386 if {![info exists allcommits]} {
7387 getallcommits
7388 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007389 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10007390 $ctext mark set branch "end -1c"
7391 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007392 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007393 $ctext mark set follows "end -1c"
7394 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007395 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007396 $ctext mark set precedes "end -1c"
7397 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007398 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007399 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007400 }
7401 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007402 set comment [lindex $info 5]
7403 if {[string first "\r" $comment] >= 0} {
7404 set comment [string map {"\r" "\n "} $comment]
7405 }
7406 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007407
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007408 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007409 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007410 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007411
Paul Mackerras8a897742008-10-27 21:36:25 +11007412 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007413 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007414 if {$cmitmode eq "tree"} {
7415 gettree $id
Thomas Rast9403bd02013-11-16 18:37:43 +01007416 } elseif {$vinlinediff($curview) == 1} {
7417 showinlinediff $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007418 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11007419 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007420 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007421 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007422 }
7423}
7424
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007425proc selfirstline {} {
7426 unmarkmatches
7427 selectline 0 1
7428}
7429
7430proc sellastline {} {
7431 global numcommits
7432 unmarkmatches
7433 set l [expr {$numcommits - 1}]
7434 selectline $l 1
7435}
7436
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007437proc selnextline {dir} {
7438 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007439 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007440 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007441 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007442 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007443 selectline $l 1
7444}
7445
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007446proc selnextpage {dir} {
7447 global canv linespc selectedline numcommits
7448
7449 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7450 if {$lpp < 1} {
7451 set lpp 1
7452 }
7453 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007454 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007455 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007456 set l [expr {$selectedline + $dir * $lpp}]
7457 if {$l < 0} {
7458 set l 0
7459 } elseif {$l >= $numcommits} {
7460 set l [expr $numcommits - 1]
7461 }
7462 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007463 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007464}
7465
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007466proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007467 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007468
Paul Mackerras94b4a692008-05-20 20:51:06 +10007469 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +10007470 unset -nocomplain currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007471 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007472 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007473}
7474
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007475proc reselectline {} {
7476 global selectedline
7477
Paul Mackerras94b4a692008-05-20 20:51:06 +10007478 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007479 selectline $selectedline 0
7480 }
7481}
7482
Paul Mackerras354af6b2008-11-23 13:14:23 +11007483proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007484 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007485
Paul Mackerras354af6b2008-11-23 13:14:23 +11007486 unset_posvars
7487 save_position
7488 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007489 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10007490 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007491 return
7492 }
7493
7494 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007495 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007496 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007497 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007498 }
7499 incr historyindex
7500 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007501 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007502 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007503 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007504 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007505 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007506}
7507
Paul Mackerras354af6b2008-11-23 13:14:23 +11007508# save the scrolling position of the diff display pane
7509proc save_position {} {
7510 global historyindex history
7511
7512 if {$historyindex < 1} return
7513 set hi [expr {$historyindex - 1}]
7514 set fn [lindex $history $hi 2]
7515 if {$fn ne {}} {
7516 lset history $hi 3 [eval $fn]
7517 }
7518}
7519
7520proc unset_posvars {} {
7521 global last_posvars
7522
7523 if {[info exists last_posvars]} {
7524 foreach {var val} $last_posvars {
7525 global $var
Paul Mackerras009409f2015-05-02 20:53:36 +10007526 unset -nocomplain $var
Paul Mackerras354af6b2008-11-23 13:14:23 +11007527 }
7528 unset last_posvars
7529 }
7530}
7531
Paul Mackerras2516dae2006-04-21 10:35:31 +10007532proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007533 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007534
7535 set view [lindex $elt 0]
7536 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007537 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007538 if {$curview != $view} {
7539 showview $view
7540 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007541 unset_posvars
7542 foreach {var val} $pv {
7543 global $var
7544 set $var $val
7545 }
7546 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007547 eval $cmd
7548}
7549
Paul Mackerrasd6982062005-08-06 22:06:06 +10007550proc goback {} {
7551 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007552 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007553
7554 if {$historyindex > 1} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007555 save_position
Paul Mackerrasd6982062005-08-06 22:06:06 +10007556 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10007557 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007558 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007559 }
7560 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007561 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007562 }
7563}
7564
7565proc goforw {} {
7566 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007567 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007568
7569 if {$historyindex < [llength $history]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007570 save_position
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007571 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10007572 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10007573 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007574 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007575 }
7576 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007577 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007578 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007579}
7580
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007581proc go_to_parent {i} {
7582 global parents curview targetid
7583 set ps $parents($curview,$targetid)
7584 if {[llength $ps] >= $i} {
7585 selbyid [lindex $ps [expr $i - 1]]
7586 }
7587}
7588
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007589proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007590 global treefilelist treeidlist diffids diffmergeid treepending
7591 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007592
7593 set diffids $id
Paul Mackerras009409f2015-05-02 20:53:36 +10007594 unset -nocomplain diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007595 if {![info exists treefilelist($id)]} {
7596 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007597 if {$id eq $nullid} {
7598 set cmd [list | git ls-files]
7599 } elseif {$id eq $nullid2} {
7600 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007601 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007602 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007603 }
7604 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007605 return
7606 }
7607 set treepending $id
7608 set treefilelist($id) {}
7609 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007610 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007611 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007612 }
7613 } else {
7614 setfilelist $id
7615 }
7616}
7617
7618proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007619 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007620
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007621 set nl 0
7622 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007623 if {$diffids eq $nullid} {
7624 set fname $line
7625 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007626 set i [string first "\t" $line]
7627 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007628 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007629 set line [string range $line 0 [expr {$i-1}]]
7630 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7631 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007632 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007633 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007634 if {[string index $fname 0] eq "\""} {
7635 set fname [lindex $fname 0]
7636 }
7637 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007638 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007639 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007640 if {![eof $gtf]} {
7641 return [expr {$nl >= 1000? 2: 1}]
7642 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007643 close $gtf
7644 unset treepending
7645 if {$cmitmode ne "tree"} {
7646 if {![info exists diffmergeid]} {
7647 gettreediffs $diffids
7648 }
7649 } elseif {$id ne $diffids} {
7650 gettree $diffids
7651 } else {
7652 setfilelist $id
7653 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007654 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007655}
7656
7657proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007658 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007659 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007660 global ctext commentend
7661
7662 set i [lsearch -exact $treefilelist($diffids) $f]
7663 if {$i < 0} {
7664 puts "oops, $f not in list for id $diffids"
7665 return
7666 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007667 if {$diffids eq $nullid} {
7668 if {[catch {set bf [open $f r]} err]} {
7669 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007670 return
7671 }
7672 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007673 set blob [lindex $treeidlist($diffids) $i]
7674 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7675 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007676 return
7677 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007678 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007679 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007680 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007681 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007682 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007683 lappend ctext_file_names $f
7684 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007685 $ctext insert end "\n"
7686 $ctext insert end "$f\n" filesep
7687 $ctext config -state disabled
7688 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007689 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007690}
7691
7692proc getblobline {bf id} {
7693 global diffids cmitmode ctext
7694
7695 if {$id ne $diffids || $cmitmode ne "tree"} {
7696 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007697 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007698 }
7699 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007700 set nl 0
7701 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007702 $ctext insert end "$line\n"
7703 }
7704 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007705 global jump_to_here ctext_file_names commentend
7706
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007707 # delete last newline
7708 $ctext delete "end - 2c" "end - 1c"
7709 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007710 if {$jump_to_here ne {} &&
7711 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7712 set lnum [expr {[lindex $jump_to_here 1] +
7713 [lindex [split $commentend .] 0]}]
7714 mark_ctext_line $lnum
7715 }
Stefan Haller120ea892010-11-14 13:21:50 +01007716 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007717 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007718 }
7719 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007720 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007721}
7722
Paul Mackerras8a897742008-10-27 21:36:25 +11007723proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007724 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007725
7726 $ctext tag delete omark
7727 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007728 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007729 $ctext see $lnum.0
7730}
7731
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007732proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007733 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007734 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007735 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007736
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007737 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007738 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007739 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007740 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007741 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007742 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007743}
7744
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007745proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007746 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007747
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007748 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007749 set diffids $ids
Paul Mackerras009409f2015-05-02 20:53:36 +10007750 unset -nocomplain diffmergeid
Paul Mackerras8f489362007-07-13 19:49:37 +10007751 if {![info exists treediffs($ids)] ||
7752 [lsearch -exact $ids $nullid] >= 0 ||
7753 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007754 if {![info exists treepending]} {
7755 gettreediffs $ids
7756 }
7757 } else {
7758 addtocflist $ids
7759 }
7760}
7761
Thomas Rast9403bd02013-11-16 18:37:43 +01007762proc showinlinediff {ids} {
7763 global commitinfo commitdata ctext
7764 global treediffs
7765
7766 set info $commitinfo($ids)
7767 set diff [lindex $info 7]
7768 set difflines [split $diff "\n"]
7769
7770 initblobdiffvars
7771 set treediff {}
7772
7773 set inhdr 0
7774 foreach line $difflines {
7775 if {![string compare -length 5 "diff " $line]} {
7776 set inhdr 1
7777 } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
7778 # offset also accounts for the b/ prefix
7779 lappend treediff [string range $line 6 end]
7780 set inhdr 0
7781 }
7782 }
7783
7784 set treediffs($ids) $treediff
7785 add_flist $treediff
7786
7787 $ctext conf -state normal
7788 foreach line $difflines {
7789 parseblobdiffline $ids $line
7790 }
7791 maybe_scroll_ctext 1
7792 $ctext conf -state disabled
7793}
7794
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007795# If the filename (name) is under any of the passed filter paths
7796# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007797proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007798 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007799 foreach p $filter {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007800 set fq_p [file normalize $p]
7801 set fq_n [file normalize [file join $worktree $name]]
7802 if {[string match [file normalize $fq_p]* $fq_n]} {
7803 return 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10007804 }
7805 }
7806 return 0
7807}
7808
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007809proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007810 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007811
Paul Mackerras74a40c72007-10-24 10:16:56 +10007812 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007813 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007814}
7815
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007816proc diffcmd {ids flags} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007817 global log_showroot nullid nullid2 git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007818
7819 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007820 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007821 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007822 if {[llength $ids] > 1 && $j < 0} {
7823 # comparing working directory with some specific revision
7824 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007825 if {$i == 0} {
7826 lappend cmd -R [lindex $ids 1]
7827 } else {
7828 lappend cmd [lindex $ids 0]
7829 }
7830 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007831 # comparing working directory with index
7832 set cmd [concat | git diff-files $flags]
7833 if {$j == 1} {
7834 lappend cmd -R
7835 }
7836 }
7837 } elseif {$j >= 0} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007838 if {[package vcompare $git_version "1.7.2"] >= 0} {
7839 set flags "$flags --ignore-submodules=dirty"
7840 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007841 set cmd [concat | git diff-index --cached $flags]
7842 if {[llength $ids] > 1} {
7843 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007844 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007845 lappend cmd -R [lindex $ids 1]
7846 } else {
7847 lappend cmd [lindex $ids 0]
7848 }
7849 } else {
7850 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007851 lappend cmd HEAD
7852 }
7853 } else {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007854 if {$log_showroot} {
7855 lappend flags --root
7856 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007857 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007858 }
7859 return $cmd
7860}
7861
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007862proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007863 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007864
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007865 set cmd [diffcmd $ids {--no-commit-id}]
7866 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7867 set cmd [concat $cmd -- $vfilelimit($curview)]
7868 }
7869 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007870
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007871 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007872 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007873 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007874 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007875}
7876
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007877proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007878 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007879 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007880
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007881 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007882 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007883 set max 1000
7884 if {$perfile_attrs} {
7885 # cache_gitattr is slow, and even slower on win32 where we
7886 # have to invoke it for only about 30 paths at a time
7887 set max 500
7888 if {[tk windowingsystem] == "win32"} {
7889 set max 120
7890 }
7891 }
7892 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007893 set i [string first "\t" $line]
7894 if {$i >= 0} {
7895 set file [string range $line [expr {$i+1}] end]
7896 if {[string index $file 0] eq "\""} {
7897 set file [lindex $file 0]
7898 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007899 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007900 if {$file ne [lindex $treediff end]} {
7901 lappend treediff $file
7902 lappend sublist $file
7903 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007904 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007905 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007906 if {$perfile_attrs} {
7907 cache_gitattr encoding $sublist
7908 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007909 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007910 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007911 }
7912 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007913 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007914 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007915 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007916 gettree $diffids
7917 } elseif {$ids != $diffids} {
7918 if {![info exists diffmergeid]} {
7919 gettreediffs $diffids
7920 }
7921 } else {
7922 addtocflist $ids
7923 }
7924 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007925}
7926
Steffen Prohaska890fae72007-08-12 12:05:46 +02007927# empty string or positive integer
7928proc diffcontextvalidate {v} {
7929 return [regexp {^(|[1-9][0-9]*)$} $v]
7930}
7931
7932proc diffcontextchange {n1 n2 op} {
7933 global diffcontextstring diffcontext
7934
7935 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007936 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007937 set diffcontext $diffcontextstring
7938 reselectline
7939 }
7940 }
7941}
7942
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007943proc changeignorespace {} {
7944 reselectline
7945}
7946
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007947proc changeworddiff {name ix op} {
7948 reselectline
7949}
7950
Thomas Rast5de460a2013-11-16 18:37:41 +01007951proc initblobdiffvars {} {
7952 global diffencoding targetline diffnparents
7953 global diffinhdr currdiffsubmod diffseehere
7954 set targetline {}
7955 set diffnparents 0
7956 set diffinhdr 0
7957 set diffencoding [get_path_encoding {}]
7958 set currdiffsubmod ""
7959 set diffseehere -1
7960}
7961
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007962proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007963 global blobdifffd diffids env
Thomas Rast5de460a2013-11-16 18:37:41 +01007964 global treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007965 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007966 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007967 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007968 global limitdiffs vfilelimit curview
Thomas Rast5de460a2013-11-16 18:37:41 +01007969 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007970
Paul Mackerrasa8138732009-05-16 21:06:01 +10007971 set textconv {}
7972 if {[package vcompare $git_version "1.6.1"] >= 0} {
7973 set textconv "--textconv"
7974 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01007975 set submodule {}
7976 if {[package vcompare $git_version "1.6.6"] >= 0} {
7977 set submodule "--submodule"
7978 }
7979 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007980 if {$ignorespace} {
7981 append cmd " -w"
7982 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007983 if {$worddiff ne [mc "Line diff"]} {
7984 append cmd " --word-diff=porcelain"
7985 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007986 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7987 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007988 }
7989 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007990 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007991 return
7992 }
Pat Thoyts681c3292009-03-16 10:24:40 +00007993 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007994 set blobdifffd($ids) $bdf
Thomas Rast5de460a2013-11-16 18:37:41 +01007995 initblobdiffvars
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007996 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007997}
7998
Paul Mackerras354af6b2008-11-23 13:14:23 +11007999proc savecmitpos {} {
8000 global ctext cmitmode
8001
8002 if {$cmitmode eq "tree"} {
8003 return {}
8004 }
8005 return [list target_scrollpos [$ctext index @0,0]]
8006}
8007
8008proc savectextpos {} {
8009 global ctext
8010
8011 return [list target_scrollpos [$ctext index @0,0]]
8012}
8013
8014proc maybe_scroll_ctext {ateof} {
8015 global ctext target_scrollpos
8016
8017 if {![info exists target_scrollpos]} return
8018 if {!$ateof} {
8019 set nlines [expr {[winfo height $ctext]
8020 / [font metrics textfont -linespace]}]
8021 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
8022 }
8023 $ctext yview $target_scrollpos
8024 unset target_scrollpos
8025}
8026
Paul Mackerras89b11d32006-05-02 19:55:31 +10008027proc setinlist {var i val} {
8028 global $var
8029
8030 while {[llength [set $var]] < $i} {
8031 lappend $var {}
8032 }
8033 if {[llength [set $var]] == $i} {
8034 lappend $var $val
8035 } else {
8036 lset $var $i $val
8037 }
8038}
8039
Paul Mackerras9396cd32007-06-23 20:28:15 +10008040proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008041 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11008042 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10008043
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008044 set fname [encoding convertfrom $fname]
8045 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10008046 set i [lsearch -exact $treediffs($ids) $fname]
8047 if {$i >= 0} {
8048 setinlist difffilestart $i $curdiffstart
8049 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11008050 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10008051 set l [expr {(78 - [string length $fname]) / 2}]
8052 set pad [string range "----------------------------------------" 1 $l]
8053 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11008054 set targetline {}
8055 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
8056 set targetline [lindex $jump_to_here 1]
8057 }
8058 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10008059}
8060
Thomas Rast5de460a2013-11-16 18:37:41 +01008061proc blobdiffmaybeseehere {ateof} {
8062 global diffseehere
8063 if {$diffseehere >= 0} {
8064 mark_ctext_line [lindex [split $diffseehere .] 0]
8065 }
Max Kirillov1f3c8722014-01-18 14:58:51 +02008066 maybe_scroll_ctext $ateof
Thomas Rast5de460a2013-11-16 18:37:41 +01008067}
8068
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008069proc getblobdiffline {bdf ids} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008070 global diffids blobdifffd
8071 global ctext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008072
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008073 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008074 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008075 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
8076 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Markus Hitter0748f412016-11-07 16:01:17 +01008077 # Older diff read. Abort it.
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008078 catch {close $bdf}
Markus Hitter0748f412016-11-07 16:01:17 +01008079 if {$ids != $diffids} {
8080 array unset blobdifffd $ids
8081 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008082 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10008083 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008084 parseblobdiffline $ids $line
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008085 }
8086 $ctext conf -state disabled
Thomas Rast5de460a2013-11-16 18:37:41 +01008087 blobdiffmaybeseehere [eof $bdf]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008088 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008089 catch {close $bdf}
Markus Hitter0748f412016-11-07 16:01:17 +01008090 array unset blobdifffd $ids
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008091 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008092 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008093 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008094}
8095
Thomas Rast5de460a2013-11-16 18:37:41 +01008096proc parseblobdiffline {ids line} {
8097 global ctext curdiffstart
8098 global diffnexthead diffnextnote difffilestart
8099 global ctext_file_names ctext_file_lines
8100 global diffinhdr treediffs mergemax diffnparents
8101 global diffencoding jump_to_here targetline diffline currdiffsubmod
8102 global worddiff diffseehere
8103
8104 if {![string compare -length 5 "diff " $line]} {
8105 if {![regexp {^diff (--cc|--git) } $line m type]} {
8106 set line [encoding convertfrom $line]
8107 $ctext insert end "$line\n" hunksep
8108 continue
8109 }
8110 # start of a new file
8111 set diffinhdr 1
8112 $ctext insert end "\n"
8113 set curdiffstart [$ctext index "end - 1c"]
8114 lappend ctext_file_names ""
8115 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8116 $ctext insert end "\n" filesep
8117
8118 if {$type eq "--cc"} {
8119 # start of a new file in a merge diff
8120 set fname [string range $line 10 end]
8121 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
8122 lappend treediffs($ids) $fname
8123 add_flist [list $fname]
8124 }
8125
8126 } else {
8127 set line [string range $line 11 end]
8128 # If the name hasn't changed the length will be odd,
8129 # the middle char will be a space, and the two bits either
8130 # side will be a/name and b/name, or "a/name" and "b/name".
8131 # If the name has changed we'll get "rename from" and
8132 # "rename to" or "copy from" and "copy to" lines following
8133 # this, and we'll use them to get the filenames.
8134 # This complexity is necessary because spaces in the
8135 # filename(s) don't get escaped.
8136 set l [string length $line]
8137 set i [expr {$l / 2}]
8138 if {!(($l & 1) && [string index $line $i] eq " " &&
8139 [string range $line 2 [expr {$i - 1}]] eq \
8140 [string range $line [expr {$i + 3}] end])} {
8141 return
8142 }
8143 # unescape if quoted and chop off the a/ from the front
8144 if {[string index $line 0] eq "\""} {
8145 set fname [string range [lindex $line 0] 2 end]
8146 } else {
8147 set fname [string range $line 2 [expr {$i - 1}]]
8148 }
8149 }
8150 makediffhdr $fname $ids
8151
8152 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
8153 set fname [encoding convertfrom [string range $line 16 end]]
8154 $ctext insert end "\n"
8155 set curdiffstart [$ctext index "end - 1c"]
8156 lappend ctext_file_names $fname
8157 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8158 $ctext insert end "$line\n" filesep
8159 set i [lsearch -exact $treediffs($ids) $fname]
8160 if {$i >= 0} {
8161 setinlist difffilestart $i $curdiffstart
8162 }
8163
8164 } elseif {![string compare -length 2 "@@" $line]} {
8165 regexp {^@@+} $line ats
8166 set line [encoding convertfrom $diffencoding $line]
8167 $ctext insert end "$line\n" hunksep
8168 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8169 set diffline $nl
8170 }
8171 set diffnparents [expr {[string length $ats] - 1}]
8172 set diffinhdr 0
8173
8174 } elseif {![string compare -length 10 "Submodule " $line]} {
8175 # start of a new submodule
8176 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
8177 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
8178 } else {
8179 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
8180 }
8181 if {$currdiffsubmod != $fname} {
8182 $ctext insert end "\n"; # Add newline after commit message
8183 }
8184 set curdiffstart [$ctext index "end - 1c"]
8185 lappend ctext_file_names ""
8186 if {$currdiffsubmod != $fname} {
8187 lappend ctext_file_lines $fname
8188 makediffhdr $fname $ids
8189 set currdiffsubmod $fname
8190 $ctext insert end "\n$line\n" filesep
8191 } else {
8192 $ctext insert end "$line\n" filesep
8193 }
8194 } elseif {![string compare -length 3 " >" $line]} {
8195 set $currdiffsubmod ""
8196 set line [encoding convertfrom $diffencoding $line]
8197 $ctext insert end "$line\n" dresult
8198 } elseif {![string compare -length 3 " <" $line]} {
8199 set $currdiffsubmod ""
8200 set line [encoding convertfrom $diffencoding $line]
8201 $ctext insert end "$line\n" d0
8202 } elseif {$diffinhdr} {
8203 if {![string compare -length 12 "rename from " $line]} {
8204 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8205 if {[string index $fname 0] eq "\""} {
8206 set fname [lindex $fname 0]
8207 }
8208 set fname [encoding convertfrom $fname]
8209 set i [lsearch -exact $treediffs($ids) $fname]
8210 if {$i >= 0} {
8211 setinlist difffilestart $i $curdiffstart
8212 }
8213 } elseif {![string compare -length 10 $line "rename to "] ||
8214 ![string compare -length 8 $line "copy to "]} {
8215 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8216 if {[string index $fname 0] eq "\""} {
8217 set fname [lindex $fname 0]
8218 }
8219 makediffhdr $fname $ids
8220 } elseif {[string compare -length 3 $line "---"] == 0} {
8221 # do nothing
8222 return
8223 } elseif {[string compare -length 3 $line "+++"] == 0} {
8224 set diffinhdr 0
8225 return
8226 }
8227 $ctext insert end "$line\n" filesep
8228
8229 } else {
8230 set line [string map {\x1A ^Z} \
8231 [encoding convertfrom $diffencoding $line]]
8232 # parse the prefix - one ' ', '-' or '+' for each parent
8233 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8234 set tag [expr {$diffnparents > 1? "m": "d"}]
8235 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8236 set words_pre_markup ""
8237 set words_post_markup ""
8238 if {[string trim $prefix " -+"] eq {}} {
8239 # prefix only has " ", "-" and "+" in it: normal diff line
8240 set num [string first "-" $prefix]
8241 if {$dowords} {
8242 set line [string range $line 1 end]
8243 }
8244 if {$num >= 0} {
8245 # removed line, first parent with line is $num
8246 if {$num >= $mergemax} {
8247 set num "max"
8248 }
8249 if {$dowords && $worddiff eq [mc "Markup words"]} {
8250 $ctext insert end "\[-$line-\]" $tag$num
8251 } else {
8252 $ctext insert end "$line" $tag$num
8253 }
8254 if {!$dowords} {
8255 $ctext insert end "\n" $tag$num
8256 }
8257 } else {
8258 set tags {}
8259 if {[string first "+" $prefix] >= 0} {
8260 # added line
8261 lappend tags ${tag}result
8262 if {$diffnparents > 1} {
8263 set num [string first " " $prefix]
8264 if {$num >= 0} {
8265 if {$num >= $mergemax} {
8266 set num "max"
8267 }
8268 lappend tags m$num
8269 }
8270 }
8271 set words_pre_markup "{+"
8272 set words_post_markup "+}"
8273 }
8274 if {$targetline ne {}} {
8275 if {$diffline == $targetline} {
8276 set diffseehere [$ctext index "end - 1 chars"]
8277 set targetline {}
8278 } else {
8279 incr diffline
8280 }
8281 }
8282 if {$dowords && $worddiff eq [mc "Markup words"]} {
8283 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8284 } else {
8285 $ctext insert end "$line" $tags
8286 }
8287 if {!$dowords} {
8288 $ctext insert end "\n" $tags
8289 }
8290 }
8291 } elseif {$dowords && $prefix eq "~"} {
8292 $ctext insert end "\n" {}
8293 } else {
8294 # "\ No newline at end of file",
8295 # or something else we don't recognize
8296 $ctext insert end "$line\n" hunksep
8297 }
8298 }
8299}
8300
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008301proc changediffdisp {} {
8302 global ctext diffelide
8303
8304 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008305 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008306}
8307
Stefan Hallerb9671352012-09-19 20:17:27 +02008308proc highlightfile {cline} {
8309 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008310
Stefan Hallerce837c92012-10-04 22:50:16 +02008311 if {![info exists cflist_top]} return
8312
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008313 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8314 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8315 $cflist see $cline.0
8316 set cflist_top $cline
8317}
8318
Stefan Hallerb9671352012-09-19 20:17:27 +02008319proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008320 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008321
Stefan Haller978904b2012-10-04 22:50:17 +02008322 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008323 if {![info exists difffilestart]} return
8324
8325 set top [lindex [split $topidx .] 0]
8326 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
8327 highlightfile 0
8328 } else {
8329 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
8330 }
8331}
8332
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008333proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008334 global difffilestart ctext cmitmode
8335
8336 if {$cmitmode eq "tree"} return
8337 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008338 set here [$ctext index @0,0]
8339 foreach loc $difffilestart {
8340 if {[$ctext compare $loc >= $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008341 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008342 return
8343 }
8344 set prev $loc
8345 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008346 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008347}
8348
Paul Mackerras39ad8572005-05-19 12:35:53 +00008349proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008350 global difffilestart ctext cmitmode
8351
8352 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008353 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008354 foreach loc $difffilestart {
8355 if {[$ctext compare $loc > $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008356 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008357 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008358 }
8359 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008360}
8361
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008362proc clear_ctext {{first 1.0}} {
8363 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008364 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008365 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008366
Paul Mackerras1902c272006-05-25 21:25:13 +10008367 set l [lindex [split $first .] 0]
8368 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
8369 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008370 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008371 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
8372 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008373 }
8374 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008375 if {$first eq "1.0"} {
Paul Mackerras009409f2015-05-02 20:53:36 +10008376 unset -nocomplain pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10008377 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008378 set ctext_file_names {}
8379 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008380}
8381
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008382proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008383 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008384
8385 if {$firstab ne {} && $have_tk85} {
8386 set firsttabstop $firstab
8387 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008388 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008389 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10008390 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8391 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008392 } elseif {$have_tk85 || $tabstop != 8} {
8393 $ctext conf -tabs [expr {$tabstop * $w}]
8394 } else {
8395 $ctext conf -tabs {}
8396 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008397}
8398
8399proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008400 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008401
Paul Mackerras1902c272006-05-25 21:25:13 +10008402 if {[catch {$ctext index anchor}]} {
8403 # no anchor set, use start of selection, or of visible area
8404 set sel [$ctext tag ranges sel]
8405 if {$sel ne {}} {
8406 $ctext mark set anchor [lindex $sel 0]
8407 } elseif {$searchdirn eq "-forwards"} {
8408 $ctext mark set anchor @0,0
8409 } else {
8410 $ctext mark set anchor @0,[winfo height $ctext]
8411 }
8412 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008413 if {$searchstring ne {}} {
Stefan Haller30441a62012-09-22 09:40:25 +02008414 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
Paul Mackerras1902c272006-05-25 21:25:13 +10008415 if {$here ne {}} {
8416 $ctext see $here
Stefan Haller30441a62012-09-22 09:40:25 +02008417 set mend "$here + $mlen c"
8418 $ctext tag remove sel 1.0 end
8419 $ctext tag add sel $here $mend
Stefan Hallerb9671352012-09-19 20:17:27 +02008420 suppress_highlighting_file_for_current_scrollpos
8421 highlightfile_for_scrollpos $here
Paul Mackerras1902c272006-05-25 21:25:13 +10008422 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008423 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008424 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008425}
8426
8427proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008428 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008429
8430 focus $sstring
8431 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008432 set searchdirn -forwards
8433 if {$searchstring ne {}} {
8434 set sel [$ctext tag ranges sel]
8435 if {$sel ne {}} {
8436 set start "[lindex $sel 0] + 1c"
8437 } elseif {[catch {set start [$ctext index anchor]}]} {
8438 set start "@0,0"
8439 }
8440 set match [$ctext search -count mlen -- $searchstring $start]
8441 $ctext tag remove sel 1.0 end
8442 if {$match eq {}} {
8443 bell
8444 return
8445 }
8446 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008447 suppress_highlighting_file_for_current_scrollpos
8448 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008449 set mend "$match + $mlen c"
8450 $ctext tag add sel $match $mend
8451 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008452 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008453 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008454}
8455
8456proc dosearchback {} {
8457 global sstring ctext searchstring searchdirn
8458
8459 focus $sstring
8460 $sstring icursor end
8461 set searchdirn -backwards
8462 if {$searchstring ne {}} {
8463 set sel [$ctext tag ranges sel]
8464 if {$sel ne {}} {
8465 set start [lindex $sel 0]
8466 } elseif {[catch {set start [$ctext index anchor]}]} {
8467 set start @0,[winfo height $ctext]
8468 }
8469 set match [$ctext search -backwards -count ml -- $searchstring $start]
8470 $ctext tag remove sel 1.0 end
8471 if {$match eq {}} {
8472 bell
8473 return
8474 }
8475 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008476 suppress_highlighting_file_for_current_scrollpos
8477 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008478 set mend "$match + $ml c"
8479 $ctext tag add sel $match $mend
8480 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008481 rehighlight_search_results
8482 }
8483}
8484
8485proc rehighlight_search_results {} {
8486 global ctext searchstring
8487
8488 $ctext tag remove found 1.0 end
8489 $ctext tag remove currentsearchhit 1.0 end
8490
8491 if {$searchstring ne {}} {
8492 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008493 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008494}
8495
8496proc searchmark {first last} {
8497 global ctext searchstring
8498
Stefan Hallerc4614992012-09-22 09:40:24 +02008499 set sel [$ctext tag ranges sel]
8500
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008501 set mend $first.0
8502 while {1} {
8503 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8504 if {$match eq {}} break
8505 set mend "$match + $mlen c"
Stefan Hallerc4614992012-09-22 09:40:24 +02008506 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8507 $ctext tag add currentsearchhit $match $mend
8508 } else {
8509 $ctext tag add found $match $mend
8510 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008511 }
8512}
8513
8514proc searchmarkvisible {doall} {
8515 global ctext smarktop smarkbot
8516
8517 set topline [lindex [split [$ctext index @0,0] .] 0]
8518 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8519 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
8520 # no overlap with previous
8521 searchmark $topline $botline
8522 set smarktop $topline
8523 set smarkbot $botline
8524 } else {
8525 if {$topline < $smarktop} {
8526 searchmark $topline [expr {$smarktop-1}]
8527 set smarktop $topline
8528 }
8529 if {$botline > $smarkbot} {
8530 searchmark [expr {$smarkbot+1}] $botline
8531 set smarkbot $botline
8532 }
8533 }
8534}
8535
Stefan Hallerb9671352012-09-19 20:17:27 +02008536proc suppress_highlighting_file_for_current_scrollpos {} {
8537 global ctext suppress_highlighting_file_for_this_scrollpos
8538
8539 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8540}
8541
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008542proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008543 global searchstring cmitmode ctext
8544 global suppress_highlighting_file_for_this_scrollpos
8545
Stefan Haller978904b2012-10-04 22:50:17 +02008546 set topidx [$ctext index @0,0]
8547 if {![info exists suppress_highlighting_file_for_this_scrollpos]
8548 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8549 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008550 }
8551
Paul Mackerras009409f2015-05-02 20:53:36 +10008552 unset -nocomplain suppress_highlighting_file_for_this_scrollpos
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008553
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008554 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008555 if {$searchstring ne {}} {
8556 searchmarkvisible 0
8557 }
8558}
8559
Paul Mackerras1d10f362005-05-15 12:55:47 +00008560proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008561 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008562 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008563
Paul Mackerras9c311b32007-10-04 22:27:13 +10008564 set linespc [font metrics mainfont -linespace]
8565 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008566 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8567 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008568 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008569 set xspc1(0) $linespc
8570 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008571}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008572
Paul Mackerras1d10f362005-05-15 12:55:47 +00008573proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008574 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008575 global selectedline
8576
8577 set ymax [lindex [$canv cget -scrollregion] 3]
8578 if {$ymax eq {} || $ymax == 0} return
8579 set span [$canv yview]
8580 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008581 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008582 allcanvs yview moveto [lindex $span 0]
8583 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008584 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008585 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008586 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008587 }
8588}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008589
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008590proc parsefont {f n} {
8591 global fontattr
8592
8593 set fontattr($f,family) [lindex $n 0]
8594 set s [lindex $n 1]
8595 if {$s eq {} || $s == 0} {
8596 set s 10
8597 } elseif {$s < 0} {
8598 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008599 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008600 set fontattr($f,size) $s
8601 set fontattr($f,weight) normal
8602 set fontattr($f,slant) roman
8603 foreach style [lrange $n 2 end] {
8604 switch -- $style {
8605 "normal" -
8606 "bold" {set fontattr($f,weight) $style}
8607 "roman" -
8608 "italic" {set fontattr($f,slant) $style}
8609 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008610 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008611}
8612
8613proc fontflags {f {isbold 0}} {
8614 global fontattr
8615
8616 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
8617 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8618 -slant $fontattr($f,slant)]
8619}
8620
8621proc fontname {f} {
8622 global fontattr
8623
8624 set n [list $fontattr($f,family) $fontattr($f,size)]
8625 if {$fontattr($f,weight) eq "bold"} {
8626 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008627 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008628 if {$fontattr($f,slant) eq "italic"} {
8629 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008630 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008631 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008632}
8633
Paul Mackerras1d10f362005-05-15 12:55:47 +00008634proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008635 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008636 global stopped entries fontattr
8637
Paul Mackerras1d10f362005-05-15 12:55:47 +00008638 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008639 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008640 incr s $inc
8641 if {$s < 1} {
8642 set s 1
8643 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008644 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008645 font config mainfont -size $s
8646 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008647 set mainfont [fontname mainfont]
8648 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008649 incr s $inc
8650 if {$s < 1} {
8651 set s 1
8652 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008653 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008654 font config textfont -size $s
8655 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008656 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008657 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008658 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008659 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008660}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008661
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008662proc clearsha1 {} {
8663 global sha1entry sha1string
8664 if {[string length $sha1string] == 40} {
8665 $sha1entry delete 0 end
8666 }
8667}
8668
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008669proc sha1change {n1 n2 op} {
8670 global sha1string currentid sha1but
8671 if {$sha1string == {}
8672 || ([info exists currentid] && $sha1string == $currentid)} {
8673 set state disabled
8674 } else {
8675 set state normal
8676 }
8677 if {[$sha1but cget -state] == $state} return
8678 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008679 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008680 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008681 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008682 }
8683}
8684
8685proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008686 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008687
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008688 if {$sha1string == {}
8689 || ([info exists currentid] && $sha1string == $currentid)} return
8690 if {[info exists tagids($sha1string)]} {
8691 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008692 } elseif {[info exists headids($sha1string)]} {
8693 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008694 } else {
8695 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008696 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008697 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008698 if {$matches ne {}} {
8699 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008700 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008701 return
8702 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008703 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008704 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008705 } else {
8706 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8707 error_popup [mc "Revision %s is not known" $sha1string]
8708 return
8709 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008710 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008711 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008712 if {[commitinview $id $curview]} {
8713 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008714 return
8715 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008716 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008717 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008718 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008719 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008720 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008721 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008722}
8723
Paul Mackerras84ba7342005-06-17 00:12:26 +00008724proc lineenter {x y id} {
8725 global hoverx hovery hoverid hovertimer
8726 global commitinfo canv
8727
Paul Mackerras8ed16482006-03-02 22:56:44 +11008728 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008729 set hoverx $x
8730 set hovery $y
8731 set hoverid $id
8732 if {[info exists hovertimer]} {
8733 after cancel $hovertimer
8734 }
8735 set hovertimer [after 500 linehover]
8736 $canv delete hover
8737}
8738
8739proc linemotion {x y id} {
8740 global hoverx hovery hoverid hovertimer
8741
8742 if {[info exists hoverid] && $id == $hoverid} {
8743 set hoverx $x
8744 set hovery $y
8745 if {[info exists hovertimer]} {
8746 after cancel $hovertimer
8747 }
8748 set hovertimer [after 500 linehover]
8749 }
8750}
8751
8752proc lineleave {id} {
8753 global hoverid hovertimer canv
8754
8755 if {[info exists hoverid] && $id == $hoverid} {
8756 $canv delete hover
8757 if {[info exists hovertimer]} {
8758 after cancel $hovertimer
8759 unset hovertimer
8760 }
8761 unset hoverid
8762 }
8763}
8764
8765proc linehover {} {
8766 global hoverx hovery hoverid hovertimer
8767 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008768 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8769
Paul Mackerras9c311b32007-10-04 22:27:13 +10008770 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008771
8772 set text [lindex $commitinfo($hoverid) 0]
8773 set ymax [lindex [$canv cget -scrollregion] 3]
8774 if {$ymax == {}} return
8775 set yfrac [lindex [$canv yview] 0]
8776 set x [expr {$hoverx + 2 * $linespc}]
8777 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8778 set x0 [expr {$x - 2 * $lthickness}]
8779 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008780 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008781 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8782 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008783 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8784 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008785 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008786 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008787 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008788 $canv raise $t
8789}
8790
Paul Mackerras9843c302005-08-30 10:57:11 +10008791proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008792 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008793
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008794 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008795 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008796 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008797 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008798 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008799 if {abs([yc $row] - $y) < $thresh} {
8800 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008801 }
8802 }
8803 return {}
8804}
8805
Paul Mackerrasf6342482006-02-28 10:02:03 +11008806proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008807 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008808
Paul Mackerrasf6342482006-02-28 10:02:03 +11008809 # 1 <-> 2, 3 <-> 4, etc...
8810 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008811 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008812 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008813 set ymax [lindex [$canv cget -scrollregion] 3]
8814 if {$ymax eq {} || $ymax <= 0} return
8815 set view [$canv yview]
8816 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8817 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8818 if {$yfrac < 0} {
8819 set yfrac 0
8820 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008821 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008822}
8823
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008824proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008825 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008826
Paul Mackerras8ed16482006-03-02 22:56:44 +11008827 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008828 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008829 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008830 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008831 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008832 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008833 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008834 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008835 if {$isnew} {
8836 set ymax [lindex [$canv cget -scrollregion] 3]
8837 if {$ymax eq {}} return
8838 set yfrac [lindex [$canv yview] 0]
8839 set y [expr {$y + $yfrac * $ymax}]
8840 }
8841 set dirn [clickisonarrow $id $y]
8842 if {$dirn ne {}} {
8843 arrowjump $id $dirn $y
8844 return
8845 }
8846
8847 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008848 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008849 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008850 # fill the details pane with info about this line
8851 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008852 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008853 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008854 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008855 $ctext insert end $id link0
8856 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008857 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008858 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008859 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008860 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008861 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008862 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008863 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008864 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008865 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008866 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008867 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008868 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008869 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008870 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008871 $ctext insert end $child link$i
8872 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008873 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008874 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008875 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008876 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008877 }
8878 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008879 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008880 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008881 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008882}
8883
Paul Mackerras9843c302005-08-30 10:57:11 +10008884proc normalline {} {
8885 global thickerline
8886 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008887 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008888 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008889 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008890 }
8891}
8892
Paul Mackerras354af6b2008-11-23 13:14:23 +11008893proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008894 global curview
8895 if {[commitinview $id $curview]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008896 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008897 }
8898}
8899
8900proc mstime {} {
8901 global startmstime
8902 if {![info exists startmstime]} {
8903 set startmstime [clock clicks -milliseconds]
8904 }
8905 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8906}
8907
8908proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008909 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008910 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008911
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008912 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008913 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008914 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008915 set state disabled
8916 } else {
8917 set state normal
8918 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008919 if {[info exists markedid] && $markedid ne $id} {
8920 set mstate normal
8921 } else {
8922 set mstate disabled
8923 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008924 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008925 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008926 if {$mainhead ne {}} {
Beat Bollib6f92a82015-09-08 01:16:37 +02008927 $menu entryconfigure 8 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008928 } else {
Beat Bollib6f92a82015-09-08 01:16:37 +02008929 $menu entryconfigure 8 -label [mc "Detached head: can't reset" $mainhead] -state disabled
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008930 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008931 $menu entryconfigure 10 -state $mstate
8932 $menu entryconfigure 11 -state $mstate
Beat Bollib6f92a82015-09-08 01:16:37 +02008933 $menu entryconfigure 12 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008934 } else {
8935 set menu $fakerowmenu
8936 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008937 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8938 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8939 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11008940 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
8941 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008942 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008943}
8944
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008945proc markhere {} {
8946 global rowmenuid markedid canv
8947
8948 set markedid $rowmenuid
8949 make_idmark $markedid
8950}
8951
8952proc gotomark {} {
8953 global markedid
8954
8955 if {[info exists markedid]} {
8956 selbyid $markedid
8957 }
8958}
8959
8960proc replace_by_kids {l r} {
8961 global curview children
8962
8963 set id [commitonrow $r]
8964 set l [lreplace $l 0 0]
8965 foreach kid $children($curview,$id) {
8966 lappend l [rowofcommit $kid]
8967 }
8968 return [lsort -integer -decreasing -unique $l]
8969}
8970
8971proc find_common_desc {} {
8972 global markedid rowmenuid curview children
8973
8974 if {![info exists markedid]} return
8975 if {![commitinview $markedid $curview] ||
8976 ![commitinview $rowmenuid $curview]} return
8977 #set t1 [clock clicks -milliseconds]
8978 set l1 [list [rowofcommit $markedid]]
8979 set l2 [list [rowofcommit $rowmenuid]]
8980 while 1 {
8981 set r1 [lindex $l1 0]
8982 set r2 [lindex $l2 0]
8983 if {$r1 eq {} || $r2 eq {}} break
8984 if {$r1 == $r2} {
8985 selectline $r1 1
8986 break
8987 }
8988 if {$r1 > $r2} {
8989 set l1 [replace_by_kids $l1 $r1]
8990 } else {
8991 set l2 [replace_by_kids $l2 $r2]
8992 }
8993 }
8994 #set t2 [clock clicks -milliseconds]
8995 #puts "took [expr {$t2-$t1}]ms"
8996}
8997
Paul Mackerras010509f2009-04-09 22:10:20 +10008998proc compare_commits {} {
8999 global markedid rowmenuid curview children
9000
9001 if {![info exists markedid]} return
9002 if {![commitinview $markedid $curview]} return
9003 addtohistory [list do_cmp_commits $markedid $rowmenuid]
9004 do_cmp_commits $markedid $rowmenuid
9005}
9006
9007proc getpatchid {id} {
9008 global patchids
9009
9010 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009011 set cmd [diffcmd [list $id] {-p --root}]
9012 # trim off the initial "|"
9013 set cmd [lrange $cmd 1 end]
9014 if {[catch {
9015 set x [eval exec $cmd | git patch-id]
9016 set patchids($id) [lindex $x 0]
9017 }]} {
9018 set patchids($id) "error"
9019 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009020 }
9021 return $patchids($id)
9022}
9023
9024proc do_cmp_commits {a b} {
9025 global ctext curview parents children patchids commitinfo
9026
9027 $ctext conf -state normal
9028 clear_ctext
9029 init_flist {}
9030 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009031 set skipa 0
9032 set skipb 0
9033 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009034 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009035 set skipa 1
9036 } else {
9037 set patcha [getpatchid $a]
9038 }
9039 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009040 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009041 set skipb 1
9042 } else {
9043 set patchb [getpatchid $b]
9044 }
9045 if {!$skipa && !$skipb} {
9046 set heada [lindex $commitinfo($a) 0]
9047 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009048 if {$patcha eq "error"} {
9049 appendshortlink $a [mc "Error getting patch ID for "] \
9050 [mc " - stopping\n"]
9051 break
9052 }
9053 if {$patchb eq "error"} {
9054 appendshortlink $b [mc "Error getting patch ID for "] \
9055 [mc " - stopping\n"]
9056 break
9057 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009058 if {$patcha eq $patchb} {
9059 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009060 appendshortlink $a [mc "Commit "]
9061 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009062 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009063 appendshortlink $a [mc "Commit "] " $heada\n"
9064 appendshortlink $b [mc " is the same patch as\n "] \
9065 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009066 }
9067 set skipa 1
9068 set skipb 1
9069 } else {
9070 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009071 appendshortlink $a [mc "Commit "] " $heada\n"
9072 appendshortlink $b [mc " differs from\n "] \
9073 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009074 $ctext insert end [mc "Diff of commits:\n\n"]
9075 $ctext conf -state disabled
9076 update
9077 diffcommits $a $b
9078 return
Paul Mackerras010509f2009-04-09 22:10:20 +10009079 }
9080 }
9081 if {$skipa} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009082 set kids [real_children $curview,$a]
9083 if {[llength $kids] != 1} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009084 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009085 appendshortlink $a [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009086 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009087 break
9088 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009089 set a [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009090 }
9091 if {$skipb} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009092 set kids [real_children $curview,$b]
9093 if {[llength $kids] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009094 appendshortlink $b [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009095 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009096 break
9097 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009098 set b [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009099 }
9100 }
9101 $ctext conf -state disabled
9102}
9103
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009104proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009105 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009106
9107 set tmpdir [gitknewtmpdir]
9108 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
9109 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
9110 if {[catch {
9111 exec git diff-tree -p --pretty $a >$fna
9112 exec git diff-tree -p --pretty $b >$fnb
9113 } err]} {
9114 error_popup [mc "Error writing commit to file: %s" $err]
9115 return
9116 }
9117 if {[catch {
9118 set fd [open "| diff -U$diffcontext $fna $fnb" r]
9119 } err]} {
9120 error_popup [mc "Error diffing commits: %s" $err]
9121 return
9122 }
9123 set diffids [list commits $a $b]
9124 set blobdifffd($diffids) $fd
9125 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009126 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009127 filerun $fd [list getblobdiffline $fd $diffids]
9128}
9129
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009130proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009131 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009132
Paul Mackerras94b4a692008-05-20 20:51:06 +10009133 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009134 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009135 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009136 set newid $rowmenuid
9137 } else {
9138 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009139 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009140 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11009141 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009142 doseldiff $oldid $newid
9143}
9144
Paul Mackerras6febded2012-03-23 22:07:27 +11009145proc diffvsmark {dirn} {
9146 global rowmenuid markedid
9147
9148 if {![info exists markedid]} return
9149 if {$dirn} {
9150 set oldid $markedid
9151 set newid $rowmenuid
9152 } else {
9153 set oldid $rowmenuid
9154 set newid $markedid
9155 }
9156 addtohistory [list doseldiff $oldid $newid] savectextpos
9157 doseldiff $oldid $newid
9158}
9159
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009160proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009161 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009162 global commitinfo
9163
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009164 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009165 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01009166 init_flist [mc "Top"]
9167 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009168 $ctext insert end $oldid link0
9169 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009170 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009171 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009172 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009173 $ctext insert end $newid link1
9174 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009175 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009176 $ctext insert end [lindex $commitinfo($newid) 0]
9177 $ctext insert end "\n"
9178 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009179 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11009180 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009181}
9182
Paul Mackerras74daedb2005-06-27 19:27:32 +10009183proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009184 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10009185
9186 if {![info exists currentid]} return
9187 set oldid $currentid
9188 set oldhead [lindex $commitinfo($oldid) 0]
9189 set newid $rowmenuid
9190 set newhead [lindex $commitinfo($newid) 0]
9191 set top .patch
9192 set patchtop $top
9193 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009194 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009195 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009196 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009197 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009198 ${NS}::label $top.from -text [mc "From:"]
9199 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009200 $top.fromsha1 insert 0 $oldid
9201 $top.fromsha1 conf -state readonly
9202 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009203 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009204 $top.fromhead insert 0 $oldhead
9205 $top.fromhead conf -state readonly
9206 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009207 ${NS}::label $top.to -text [mc "To:"]
9208 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009209 $top.tosha1 insert 0 $newid
9210 $top.tosha1 conf -state readonly
9211 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009212 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009213 $top.tohead insert 0 $newhead
9214 $top.tohead conf -state readonly
9215 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009216 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
9217 grid $top.rev x -pady 10 -padx 5
9218 ${NS}::label $top.flab -text [mc "Output file:"]
9219 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009220 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
9221 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009222 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009223 ${NS}::frame $top.buts
9224 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
9225 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009226 bind $top <Key-Return> mkpatchgo
9227 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10009228 grid $top.buts.gen $top.buts.can
9229 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9230 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9231 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009232 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10009233}
9234
9235proc mkpatchrev {} {
9236 global patchtop
9237
9238 set oldid [$patchtop.fromsha1 get]
9239 set oldhead [$patchtop.fromhead get]
9240 set newid [$patchtop.tosha1 get]
9241 set newhead [$patchtop.tohead get]
9242 foreach e [list fromsha1 fromhead tosha1 tohead] \
9243 v [list $newid $newhead $oldid $oldhead] {
9244 $patchtop.$e conf -state normal
9245 $patchtop.$e delete 0 end
9246 $patchtop.$e insert 0 $v
9247 $patchtop.$e conf -state readonly
9248 }
9249}
9250
9251proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10009252 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10009253
9254 set oldid [$patchtop.fromsha1 get]
9255 set newid [$patchtop.tosha1 get]
9256 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10009257 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10009258 # trim off the initial "|"
9259 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009260 lappend cmd >$fname &
9261 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009262 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009263 }
9264 catch {destroy $patchtop}
9265 unset patchtop
9266}
9267
9268proc mkpatchcan {} {
9269 global patchtop
9270
9271 catch {destroy $patchtop}
9272 unset patchtop
9273}
9274
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009275proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009276 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009277
9278 set top .maketag
9279 set mktagtop $top
9280 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009281 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009282 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009283 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009284 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009285 ${NS}::label $top.id -text [mc "ID:"]
9286 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009287 $top.sha1 insert 0 $rowmenuid
9288 $top.sha1 conf -state readonly
9289 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009290 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009291 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9292 $top.head conf -state readonly
9293 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009294 ${NS}::label $top.tlab -text [mc "Tag name:"]
9295 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009296 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009297 ${NS}::label $top.op -text [mc "Tag message is optional"]
9298 grid $top.op -columnspan 2 -sticky we
9299 ${NS}::label $top.mlab -text [mc "Tag message:"]
9300 ${NS}::entry $top.msg -width 60
9301 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009302 ${NS}::frame $top.buts
9303 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9304 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009305 bind $top <Key-Return> mktaggo
9306 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009307 grid $top.buts.gen $top.buts.can
9308 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9309 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9310 grid $top.buts - -pady 10 -sticky ew
9311 focus $top.tag
9312}
9313
9314proc domktag {} {
9315 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009316
9317 set id [$mktagtop.sha1 get]
9318 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009319 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009320 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009321 error_popup [mc "No tag name specified"] $mktagtop
9322 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009323 }
9324 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009325 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9326 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009327 }
9328 if {[catch {
Dave Dulsondfb891e2010-01-03 14:55:52 +00009329 if {$msg != {}} {
9330 exec git tag -a -m $msg $tag $id
9331 } else {
9332 exec git tag $tag $id
9333 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009334 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009335 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9336 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009337 }
9338
9339 set tagids($tag) $id
9340 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009341 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009342 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009343 dispneartags 0
9344 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009345 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009346}
9347
9348proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009349 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009350 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009351 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009352
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009353 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009354 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009355 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009356 if {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009357 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009358 } else {
9359 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
9360 }
9361 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009362 $canv delete tag.$id
9363 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009364 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9365 set text [$canv itemcget $linehtag($id) -text]
9366 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009367 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009368 if {$xr > $canvxmax} {
9369 set canvxmax $xr
9370 setcanvscroll
9371 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009372 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11009373 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009374 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009375 if {[info exists markedid] && $markedid eq $id} {
9376 make_idmark $id
9377 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009378}
9379
9380proc mktagcan {} {
9381 global mktagtop
9382
9383 catch {destroy $mktagtop}
9384 unset mktagtop
9385}
9386
9387proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009388 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009389 mktagcan
9390}
9391
Beat Bollid835dbb2015-07-18 13:15:39 +02009392proc copysummary {} {
9393 global rowmenuid autosellen
9394
9395 set format "%h (\"%s\", %ad)"
9396 set cmd [list git show -s --pretty=format:$format --date=short]
9397 if {$autosellen < 40} {
9398 lappend cmd --abbrev=$autosellen
9399 }
9400 set summary [eval exec $cmd $rowmenuid]
9401
9402 clipboard clear
9403 clipboard append $summary
9404}
9405
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009406proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009407 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009408
9409 set top .writecommit
9410 set wrcomtop $top
9411 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009412 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009413 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009414 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009415 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009416 ${NS}::label $top.id -text [mc "ID:"]
9417 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009418 $top.sha1 insert 0 $rowmenuid
9419 $top.sha1 conf -state readonly
9420 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009421 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009422 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9423 $top.head conf -state readonly
9424 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009425 ${NS}::label $top.clab -text [mc "Command:"]
9426 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009427 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009428 ${NS}::label $top.flab -text [mc "Output file:"]
9429 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009430 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9431 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009432 ${NS}::frame $top.buts
9433 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9434 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009435 bind $top <Key-Return> wrcomgo
9436 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009437 grid $top.buts.gen $top.buts.can
9438 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9439 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9440 grid $top.buts - -pady 10 -sticky ew
9441 focus $top.fname
9442}
9443
9444proc wrcomgo {} {
9445 global wrcomtop
9446
9447 set id [$wrcomtop.sha1 get]
9448 set cmd "echo $id | [$wrcomtop.cmd get]"
9449 set fname [$wrcomtop.fname get]
9450 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009451 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009452 }
9453 catch {destroy $wrcomtop}
9454 unset wrcomtop
9455}
9456
9457proc wrcomcan {} {
9458 global wrcomtop
9459
9460 catch {destroy $wrcomtop}
9461 unset wrcomtop
9462}
9463
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009464proc mkbranch {} {
Rogier Goossens5a046c52016-03-19 19:32:16 +01009465 global NS rowmenuid
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009466
Rogier Goossens5a046c52016-03-19 19:32:16 +01009467 set top .branchdialog
9468
9469 set val(name) ""
9470 set val(id) $rowmenuid
9471 set val(command) [list mkbrgo $top]
9472
9473 set ui(title) [mc "Create branch"]
9474 set ui(accept) [mc "Create"]
9475
9476 branchdia $top val ui
9477}
9478
9479proc mvbranch {} {
9480 global NS
9481 global headmenuid headmenuhead
9482
9483 set top .branchdialog
9484
9485 set val(name) $headmenuhead
9486 set val(id) $headmenuid
9487 set val(command) [list mvbrgo $top $headmenuhead]
9488
9489 set ui(title) [mc "Rename branch %s" $headmenuhead]
9490 set ui(accept) [mc "Rename"]
9491
9492 branchdia $top val ui
9493}
9494
9495proc branchdia {top valvar uivar} {
Rogier Goossens7f00f4c2016-03-27 09:21:01 +02009496 global NS commitinfo
Rogier Goossens5a046c52016-03-19 19:32:16 +01009497 upvar $valvar val $uivar ui
9498
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009499 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009500 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009501 make_transient $top .
Rogier Goossens5a046c52016-03-19 19:32:16 +01009502 ${NS}::label $top.title -text $ui(title)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009503 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009504 ${NS}::label $top.id -text [mc "ID:"]
9505 ${NS}::entry $top.sha1 -width 40
Rogier Goossens5a046c52016-03-19 19:32:16 +01009506 $top.sha1 insert 0 $val(id)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009507 $top.sha1 conf -state readonly
9508 grid $top.id $top.sha1 -sticky w
Rogier Goossens7f00f4c2016-03-27 09:21:01 +02009509 ${NS}::entry $top.head -width 60
9510 $top.head insert 0 [lindex $commitinfo($val(id)) 0]
9511 $top.head conf -state readonly
9512 grid x $top.head -sticky ew
9513 grid columnconfigure $top 1 -weight 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01009514 ${NS}::label $top.nlab -text [mc "Name:"]
9515 ${NS}::entry $top.name -width 40
Rogier Goossens5a046c52016-03-19 19:32:16 +01009516 $top.name insert 0 $val(name)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009517 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009518 ${NS}::frame $top.buts
Rogier Goossens5a046c52016-03-19 19:32:16 +01009519 ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)
Pat Thoytsd93f1712009-04-17 01:24:35 +01009520 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Rogier Goossens5a046c52016-03-19 19:32:16 +01009521 bind $top <Key-Return> $val(command)
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009522 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009523 grid $top.buts.go $top.buts.can
9524 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9525 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9526 grid $top.buts - -pady 10 -sticky ew
9527 focus $top.name
9528}
9529
9530proc mkbrgo {top} {
9531 global headids idheads
9532
9533 set name [$top.name get]
9534 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009535 set cmdargs {}
9536 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009537 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009538 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009539 return
9540 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009541 if {[info exists headids($name)]} {
9542 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009543 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009544 return
9545 }
9546 set old_id $headids($name)
9547 lappend cmdargs -f
9548 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009549 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009550 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009551 nowbusy newbranch
9552 update
9553 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009554 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009555 } err]} {
9556 notbusy newbranch
9557 error_popup $err
9558 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009559 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009560 if {$old_id ne {}} {
9561 movehead $id $name
9562 movedhead $id $name
9563 redrawtags $old_id
9564 redrawtags $id
9565 } else {
9566 set headids($name) $id
9567 lappend idheads($id) $name
9568 addedhead $id $name
9569 redrawtags $id
9570 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009571 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009572 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009573 }
9574}
9575
Rogier Goossens5a046c52016-03-19 19:32:16 +01009576proc mvbrgo {top prevname} {
9577 global headids idheads mainhead mainheadid
9578
9579 set name [$top.name get]
9580 set id [$top.sha1 get]
9581 set cmdargs {}
9582 if {$name eq $prevname} {
9583 catch {destroy $top}
9584 return
9585 }
9586 if {$name eq {}} {
9587 error_popup [mc "Please specify a new name for the branch"] $top
9588 return
9589 }
9590 catch {destroy $top}
9591 lappend cmdargs -m $prevname $name
9592 nowbusy renamebranch
9593 update
9594 if {[catch {
9595 eval exec git branch $cmdargs
9596 } err]} {
9597 notbusy renamebranch
9598 error_popup $err
9599 } else {
9600 notbusy renamebranch
9601 removehead $id $prevname
9602 removedhead $id $prevname
9603 set headids($name) $id
9604 lappend idheads($id) $name
9605 addedhead $id $name
9606 if {$prevname eq $mainhead} {
9607 set mainhead $name
9608 set mainheadid $id
9609 }
9610 redrawtags $id
9611 dispneartags 0
9612 run refill_reflist
9613 }
9614}
9615
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009616proc exec_citool {tool_args {baseid {}}} {
9617 global commitinfo env
9618
9619 set save_env [array get env GIT_AUTHOR_*]
9620
9621 if {$baseid ne {}} {
9622 if {![info exists commitinfo($baseid)]} {
9623 getcommit $baseid
9624 }
9625 set author [lindex $commitinfo($baseid) 1]
9626 set date [lindex $commitinfo($baseid) 2]
9627 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9628 $author author name email]
9629 && $date ne {}} {
9630 set env(GIT_AUTHOR_NAME) $name
9631 set env(GIT_AUTHOR_EMAIL) $email
9632 set env(GIT_AUTHOR_DATE) $date
9633 }
9634 }
9635
9636 eval exec git citool $tool_args &
9637
9638 array unset env GIT_AUTHOR_*
9639 array set env $save_env
9640}
9641
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009642proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009643 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009644 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009645 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009646
Paul Mackerrase11f1232007-06-16 20:29:25 +10009647 set oldhead [exec git rev-parse HEAD]
9648 set dheads [descheads $rowmenuid]
9649 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009650 set ok [confirm_popup [mc "Commit %s is already\
9651 included in branch %s -- really re-apply it?" \
9652 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009653 if {!$ok} return
9654 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009655 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009656 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009657 # Unfortunately git-cherry-pick writes stuff to stderr even when
9658 # no error occurs, and exec takes that as an indication of error...
9659 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
9660 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009661 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11009662 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9663 $err msg fname]} {
9664 error_popup [mc "Cherry-pick failed because of local changes\
9665 to file '%s'.\nPlease commit, reset or stash\
9666 your changes and try again." $fname]
9667 } elseif {[regexp -line \
Anders Kaseorgb74307f2011-01-19 14:45:00 -05009668 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
Paul Mackerras887a7912008-11-08 21:37:09 +11009669 $err]} {
9670 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9671 conflict.\nDo you wish to run git citool to\
9672 resolve it?"]]} {
9673 # Force citool to read MERGE_MSG
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009674 file delete [file join $gitdir "GITGUI_MSG"]
Paul Mackerras887a7912008-11-08 21:37:09 +11009675 exec_citool {} $rowmenuid
9676 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009677 } else {
9678 error_popup $err
9679 }
Paul Mackerras887a7912008-11-08 21:37:09 +11009680 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009681 return
9682 }
9683 set newhead [exec git rev-parse HEAD]
9684 if {$newhead eq $oldhead} {
9685 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01009686 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009687 return
9688 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009689 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009690 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11009691 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009692 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009693 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009694 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009695 movedhead $newhead $mainhead
9696 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009697 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009698 redrawtags $oldhead
9699 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11009700 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009701 }
9702 notbusy cherrypick
9703}
9704
Knut Franke8f3ff932013-04-27 16:36:13 +02009705proc revert {} {
9706 global rowmenuid curview
9707 global mainhead mainheadid
9708 global gitdir
9709
9710 set oldhead [exec git rev-parse HEAD]
9711 set dheads [descheads $rowmenuid]
9712 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9713 set ok [confirm_popup [mc "Commit %s is not\
9714 included in branch %s -- really revert it?" \
9715 [string range $rowmenuid 0 7] $mainhead]]
9716 if {!$ok} return
9717 }
9718 nowbusy revert [mc "Reverting"]
9719 update
9720
9721 if [catch {exec git revert --no-edit $rowmenuid} err] {
9722 notbusy revert
9723 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9724 $err match files] {
9725 regsub {\n( |\t)+} $files "\n" files
9726 error_popup [mc "Revert failed because of local changes to\
9727 the following files:%s Please commit, reset or stash \
9728 your changes and try again." $files]
9729 } elseif [regexp {error: could not revert} $err] {
9730 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9731 Do you wish to run git citool to resolve it?"]] {
9732 # Force citool to read MERGE_MSG
9733 file delete [file join $gitdir "GITGUI_MSG"]
9734 exec_citool {} $rowmenuid
9735 }
9736 } else { error_popup $err }
9737 run updatecommits
9738 return
9739 }
9740
9741 set newhead [exec git rev-parse HEAD]
9742 if { $newhead eq $oldhead } {
9743 notbusy revert
9744 error_popup [mc "No changes committed"]
9745 return
9746 }
9747
9748 addnewchild $newhead $oldhead
9749
9750 if [commitinview $oldhead $curview] {
9751 # XXX this isn't right if we have a path limit...
9752 insertrow $newhead $oldhead $curview
9753 if {$mainhead ne {}} {
9754 movehead $newhead $mainhead
9755 movedhead $newhead $mainhead
9756 }
9757 set mainheadid $newhead
9758 redrawtags $oldhead
9759 redrawtags $newhead
9760 selbyid $newhead
9761 }
9762
9763 notbusy revert
9764}
9765
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009766proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009767 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009768
9769 set confirm_ok 0
9770 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009771 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009772 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009773 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009774 ${NS}::label $w.m -text \
9775 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009776 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009777 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009778 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009779 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009780 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009781 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009782 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009783 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009784 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009785 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009786 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009787 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009788 pack $w.f -side top -fill x -padx 4
9789 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009790 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009791 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009792 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009793 pack $w.cancel -side right -fill x -padx 20 -pady 20
9794 bind $w <Visibility> "grab $w; focus $w"
9795 tkwait window $w
9796 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009797 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10009798 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009799 error_popup $err
9800 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009801 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10009802 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009803 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11009804 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009805 }
9806}
9807
Paul Mackerrasa137a902007-10-23 21:12:49 +10009808proc readresetstat {fd} {
9809 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009810
9811 if {[gets $fd line] >= 0} {
9812 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10009813 set rprogcoord [expr {1.0 * $m / $n}]
9814 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009815 }
9816 return 1
9817 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009818 set rprogcoord 0
9819 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009820 notbusy reset
9821 if {[catch {close $fd} err]} {
9822 error_popup $err
9823 }
9824 set oldhead $mainheadid
9825 set newhead [exec git rev-parse HEAD]
9826 if {$newhead ne $oldhead} {
9827 movehead $newhead $mainhead
9828 movedhead $newhead $mainhead
9829 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009830 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10009831 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009832 }
9833 if {$showlocalchanges} {
9834 doshowlocalchanges
9835 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009836 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009837}
9838
Paul Mackerras10299152006-08-02 09:52:01 +10009839# context menu for a head
9840proc headmenu {x y id head} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009841 global headmenuid headmenuhead headctxmenu mainhead headids
Paul Mackerras10299152006-08-02 09:52:01 +10009842
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009843 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009844 set headmenuid $id
9845 set headmenuhead $head
Rogier Goossens5a046c52016-03-19 19:32:16 +01009846 array set state {0 normal 1 normal 2 normal}
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309847 if {[string match "remotes/*" $head]} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009848 set localhead [string range $head [expr [string last / $head] + 1] end]
9849 if {[info exists headids($localhead)]} {
9850 set state(0) disabled
9851 }
9852 array set state {1 disabled 2 disabled}
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309853 }
Paul Mackerras00609462007-06-17 17:08:35 +10009854 if {$head eq $mainhead} {
Rogier Goossens5a046c52016-03-19 19:32:16 +01009855 array set state {0 disabled 2 disabled}
Paul Mackerras00609462007-06-17 17:08:35 +10009856 }
Rogier Goossens5a046c52016-03-19 19:32:16 +01009857 foreach i {0 1 2} {
9858 $headctxmenu entryconfigure $i -state $state($i)
9859 }
Paul Mackerras10299152006-08-02 09:52:01 +10009860 tk_popup $headctxmenu $x $y
9861}
9862
9863proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009864 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009865 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009866
9867 # check the tree is clean first??
Rogier Goossens02e6a062016-03-19 19:33:03 +01009868 set newhead $headmenuhead
9869 set command [list | git checkout]
9870 if {[string match "remotes/*" $newhead]} {
9871 set remote $newhead
9872 set newhead [string range $newhead [expr [string last / $newhead] + 1] end]
9873 # The following check is redundant - the menu option should
9874 # be disabled to begin with...
9875 if {[info exists headids($newhead)]} {
9876 error_popup [mc "A local branch named %s exists already" $newhead]
9877 return
9878 }
9879 lappend command -b $newhead --track $remote
9880 } else {
9881 lappend command $newhead
9882 }
9883 lappend command 2>@1
Christian Stimmingd990ced2007-11-07 18:42:55 +01009884 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009885 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009886 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009887 if {[catch {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009888 set fd [open $command r]
Paul Mackerras10299152006-08-02 09:52:01 +10009889 } err]} {
9890 notbusy checkout
9891 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10009892 if {$showlocalchanges} {
9893 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009894 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009895 } else {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009896 filerun $fd [list readcheckoutstat $fd $newhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009897 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009898}
9899
9900proc readcheckoutstat {fd newhead newheadid} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009901 global mainhead mainheadid headids idheads showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009902 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009903
9904 if {[gets $fd line] >= 0} {
9905 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9906 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9907 adjustprogress
9908 }
9909 return 1
9910 }
9911 set progresscoords {0 0}
9912 adjustprogress
9913 notbusy checkout
9914 if {[catch {close $fd} err]} {
9915 error_popup $err
Rogier Goossens02e6a062016-03-19 19:33:03 +01009916 return
Paul Mackerras08ba8202008-05-12 10:18:38 +10009917 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009918 set oldmainid $mainheadid
Rogier Goossens02e6a062016-03-19 19:33:03 +01009919 if {! [info exists headids($newhead)]} {
9920 set headids($newhead) $newheadid
9921 lappend idheads($newheadid) $newhead
9922 addedhead $newheadid $newhead
9923 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009924 set mainhead $newhead
9925 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11009926 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009927 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009928 redrawtags $newheadid
9929 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009930 if {$showlocalchanges} {
9931 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009932 }
9933}
9934
9935proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009936 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10009937 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10009938
9939 set head $headmenuhead
9940 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10009941 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10009942 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009943 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10009944 return
9945 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009946 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10009947 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10009948 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01009949 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
9950 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10009951 }
9952 nowbusy rmbranch
9953 update
9954 if {[catch {exec git branch -D $head} err]} {
9955 notbusy rmbranch
9956 error_popup $err
9957 return
9958 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009959 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009960 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10009961 redrawtags $id
9962 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10009963 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009964 run refill_reflist
9965}
9966
9967# Display a list of tags and heads
9968proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009969 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +10009970 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10009971
9972 set top .showrefs
9973 set showrefstop $top
9974 if {[winfo exists $top]} {
9975 raise $top
9976 refill_reflist
9977 return
9978 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009979 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009980 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009981 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10009982 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10009983 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10009984 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
9985 -width 30 -height 20 -cursor $maincursor \
9986 -spacing1 1 -spacing3 1 -state disabled
9987 $top.list tag configure highlight -background $selectbgcolor
Paul Mackerraseb859df2015-05-03 15:11:29 +10009988 if {![lsearch -exact $bglist $top.list]} {
9989 lappend bglist $top.list
9990 lappend fglist $top.list
9991 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009992 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
9993 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +10009994 grid $top.list $top.ysb -sticky nsew
9995 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +01009996 ${NS}::frame $top.f
9997 ${NS}::label $top.f.l -text "[mc "Filter"]: "
9998 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009999 set reflistfilter "*"
10000 trace add variable reflistfilter write reflistfilter_change
10001 pack $top.f.e -side right -fill x -expand 1
10002 pack $top.f.l -side left
10003 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +010010004 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010005 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +100010006 grid $top.close -
10007 grid columnconfigure $top 0 -weight 1
10008 grid rowconfigure $top 0 -weight 1
10009 bind $top.list <1> {break}
10010 bind $top.list <B1-Motion> {break}
10011 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
10012 set reflist {}
10013 refill_reflist
10014}
10015
10016proc sel_reflist {w x y} {
10017 global showrefstop reflist headids tagids otherrefids
10018
10019 if {![winfo exists $showrefstop]} return
10020 set l [lindex [split [$w index "@$x,$y"] "."] 0]
10021 set ref [lindex $reflist [expr {$l-1}]]
10022 set n [lindex $ref 0]
10023 switch -- [lindex $ref 1] {
10024 "H" {selbyid $headids($n)}
10025 "T" {selbyid $tagids($n)}
10026 "o" {selbyid $otherrefids($n)}
10027 }
10028 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
10029}
10030
10031proc unsel_reflist {} {
10032 global showrefstop
10033
10034 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
10035 $showrefstop.list tag remove highlight 0.0 end
10036}
10037
10038proc reflistfilter_change {n1 n2 op} {
10039 global reflistfilter
10040
10041 after cancel refill_reflist
10042 after 200 refill_reflist
10043}
10044
10045proc refill_reflist {} {
10046 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010047 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +100010048
10049 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
10050 set refs {}
10051 foreach n [array names headids] {
10052 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010053 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +100010054 lappend refs [list $n H]
10055 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010056 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +100010057 }
10058 }
10059 }
10060 foreach n [array names tagids] {
10061 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010062 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +100010063 lappend refs [list $n T]
10064 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010065 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +100010066 }
10067 }
10068 }
10069 foreach n [array names otherrefids] {
10070 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010071 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +100010072 lappend refs [list $n o]
10073 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010074 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +100010075 }
10076 }
10077 }
10078 set refs [lsort -index 0 $refs]
10079 if {$refs eq $reflist} return
10080
10081 # Update the contents of $showrefstop.list according to the
10082 # differences between $reflist (old) and $refs (new)
10083 $showrefstop.list conf -state normal
10084 $showrefstop.list insert end "\n"
10085 set i 0
10086 set j 0
10087 while {$i < [llength $reflist] || $j < [llength $refs]} {
10088 if {$i < [llength $reflist]} {
10089 if {$j < [llength $refs]} {
10090 set cmp [string compare [lindex $reflist $i 0] \
10091 [lindex $refs $j 0]]
10092 if {$cmp == 0} {
10093 set cmp [string compare [lindex $reflist $i 1] \
10094 [lindex $refs $j 1]]
10095 }
10096 } else {
10097 set cmp -1
10098 }
10099 } else {
10100 set cmp 1
10101 }
10102 switch -- $cmp {
10103 -1 {
10104 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
10105 incr i
10106 }
10107 0 {
10108 incr i
10109 incr j
10110 }
10111 1 {
10112 set l [expr {$j + 1}]
10113 $showrefstop.list image create $l.0 -align baseline \
10114 -image reficon-[lindex $refs $j 1] -padx 2
10115 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
10116 incr j
10117 }
10118 }
10119 }
10120 set reflist $refs
10121 # delete last newline
10122 $showrefstop.list delete end-2c end-1c
10123 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +100010124}
10125
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010126# Stuff for finding nearby tags
10127proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010128 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
10129 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010130 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010131
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010132 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010133 set nextarc 0
10134 set allcommits 0
10135 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010136 set allcwait 0
10137 set cachedarcs 0
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010138 set allccache [file join $gitdir "gitk.cache"]
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010139 if {![catch {
10140 set f [open $allccache r]
10141 set allcwait 1
10142 getcache $f
10143 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010144 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010145
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010146 if {$allcwait} {
10147 return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010148 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010149 set cmd [list | git rev-list --parents]
10150 set allcupdate [expr {$seeds ne {}}]
10151 if {!$allcupdate} {
10152 set ids "--all"
10153 } else {
10154 set refs [concat [array names idheads] [array names idtags] \
10155 [array names idotherrefs]]
10156 set ids {}
10157 set tagobjs {}
10158 foreach name [array names tagobjid] {
10159 lappend tagobjs $tagobjid($name)
10160 }
10161 foreach id [lsort -unique $refs] {
10162 if {![info exists allparents($id)] &&
10163 [lsearch -exact $tagobjs $id] < 0} {
10164 lappend ids $id
10165 }
10166 }
10167 if {$ids ne {}} {
10168 foreach id $seeds {
10169 lappend ids "^$id"
10170 }
10171 }
10172 }
10173 if {$ids ne {}} {
10174 set fd [open [concat $cmd $ids] r]
10175 fconfigure $fd -blocking 0
10176 incr allcommits
10177 nowbusy allcommits
10178 filerun $fd [list getallclines $fd]
10179 } else {
10180 dispneartags 0
10181 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010182}
10183
Paul Mackerrase11f1232007-06-16 20:29:25 +100010184# Since most commits have 1 parent and 1 child, we group strings of
10185# such commits into "arcs" joining branch/merge points (BMPs), which
10186# are commits that either don't have 1 parent or don't have 1 child.
10187#
10188# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
10189# arcout(id) - outgoing arcs for BMP
10190# arcids(a) - list of IDs on arc including end but not start
10191# arcstart(a) - BMP ID at start of arc
10192# arcend(a) - BMP ID at end of arc
10193# growing(a) - arc a is still growing
10194# arctags(a) - IDs out of arcids (excluding end) that have tags
10195# archeads(a) - IDs out of arcids (excluding end) that have heads
10196# The start of an arc is at the descendent end, so "incoming" means
10197# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010198
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010199proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010200 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010201 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010202 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +010010203
Paul Mackerrase11f1232007-06-16 20:29:25 +100010204 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010205 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010206 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010207 if {[info exists allparents($id)]} {
10208 # seen it already
10209 continue
10210 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010211 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010212 set olds [lrange $line 1 end]
10213 set allparents($id) $olds
10214 if {![info exists allchildren($id)]} {
10215 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010216 set arcnos($id) {}
10217 lappend seeds $id
10218 } else {
10219 set a $arcnos($id)
10220 if {[llength $olds] == 1 && [llength $a] == 1} {
10221 lappend arcids($a) $id
10222 if {[info exists idtags($id)]} {
10223 lappend arctags($a) $id
10224 }
10225 if {[info exists idheads($id)]} {
10226 lappend archeads($a) $id
10227 }
10228 if {[info exists allparents($olds)]} {
10229 # seen parent already
10230 if {![info exists arcout($olds)]} {
10231 splitarc $olds
10232 }
10233 lappend arcids($a) $olds
10234 set arcend($a) $olds
10235 unset growing($a)
10236 }
10237 lappend allchildren($olds) $id
10238 lappend arcnos($olds) $a
10239 continue
10240 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010241 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010242 foreach a $arcnos($id) {
10243 lappend arcids($a) $id
10244 set arcend($a) $id
10245 unset growing($a)
10246 }
10247
10248 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010249 foreach p $olds {
10250 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010251 set a [incr nextarc]
10252 set arcstart($a) $id
10253 set archeads($a) {}
10254 set arctags($a) {}
10255 set archeads($a) {}
10256 set arcids($a) {}
10257 lappend ao $a
10258 set growing($a) 1
10259 if {[info exists allparents($p)]} {
10260 # seen it already, may need to make a new branch
10261 if {![info exists arcout($p)]} {
10262 splitarc $p
10263 }
10264 lappend arcids($a) $p
10265 set arcend($a) $p
10266 unset growing($a)
10267 }
10268 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010269 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010270 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010271 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010272 if {$nid > 0} {
10273 global cached_dheads cached_dtags cached_atags
Paul Mackerras009409f2015-05-02 20:53:36 +100010274 unset -nocomplain cached_dheads
10275 unset -nocomplain cached_dtags
10276 unset -nocomplain cached_atags
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010277 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010278 if {![eof $fd]} {
10279 return [expr {$nid >= 1000? 2: 1}]
10280 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010281 set cacheok 1
10282 if {[catch {
10283 fconfigure $fd -blocking 1
10284 close $fd
10285 } err]} {
10286 # got an error reading the list of commits
10287 # if we were updating, try rereading the whole thing again
10288 if {$allcupdate} {
10289 incr allcommits -1
10290 dropcache $err
10291 return
10292 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010010293 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010294 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +010010295 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010296 set cacheok 0
10297 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010298 if {[incr allcommits -1] == 0} {
10299 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010300 if {$cacheok} {
10301 run savecache
10302 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010303 }
10304 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010305 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010306}
10307
10308proc recalcarc {a} {
10309 global arctags archeads arcids idtags idheads
10310
10311 set at {}
10312 set ah {}
10313 foreach id [lrange $arcids($a) 0 end-1] {
10314 if {[info exists idtags($id)]} {
10315 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010316 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010317 if {[info exists idheads($id)]} {
10318 lappend ah $id
10319 }
10320 }
10321 set arctags($a) $at
10322 set archeads($a) $ah
10323}
10324
10325proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010326 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +100010327 global arcstart arcend arcout allparents growing
10328
10329 set a $arcnos($p)
10330 if {[llength $a] != 1} {
10331 puts "oops splitarc called but [llength $a] arcs already"
10332 return
10333 }
10334 set a [lindex $a 0]
10335 set i [lsearch -exact $arcids($a) $p]
10336 if {$i < 0} {
10337 puts "oops splitarc $p not in arc $a"
10338 return
10339 }
10340 set na [incr nextarc]
10341 if {[info exists arcend($a)]} {
10342 set arcend($na) $arcend($a)
10343 } else {
10344 set l [lindex $allparents([lindex $arcids($a) end]) 0]
10345 set j [lsearch -exact $arcnos($l) $a]
10346 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
10347 }
10348 set tail [lrange $arcids($a) [expr {$i+1}] end]
10349 set arcids($a) [lrange $arcids($a) 0 $i]
10350 set arcend($a) $p
10351 set arcstart($na) $p
10352 set arcout($p) $na
10353 set arcids($na) $tail
10354 if {[info exists growing($a)]} {
10355 set growing($na) 1
10356 unset growing($a)
10357 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010358
10359 foreach id $tail {
10360 if {[llength $arcnos($id)] == 1} {
10361 set arcnos($id) $na
10362 } else {
10363 set j [lsearch -exact $arcnos($id) $a]
10364 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
10365 }
10366 }
10367
10368 # reconstruct tags and heads lists
10369 if {$arctags($a) ne {} || $archeads($a) ne {}} {
10370 recalcarc $a
10371 recalcarc $na
10372 } else {
10373 set arctags($na) {}
10374 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010375 }
10376}
10377
Paul Mackerrase11f1232007-06-16 20:29:25 +100010378# Update things for a new commit added that is a child of one
10379# existing commit. Used when cherry-picking.
10380proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010381 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010382 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010383 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010384
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010385 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010386 set allparents($id) [list $p]
10387 set allchildren($id) {}
10388 set arcnos($id) {}
10389 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010390 lappend allchildren($p) $id
10391 set a [incr nextarc]
10392 set arcstart($a) $id
10393 set archeads($a) {}
10394 set arctags($a) {}
10395 set arcids($a) [list $p]
10396 set arcend($a) $p
10397 if {![info exists arcout($p)]} {
10398 splitarc $p
10399 }
10400 lappend arcnos($p) $a
10401 set arcout($id) [list $a]
10402}
10403
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010404# This implements a cache for the topology information.
10405# The cache saves, for each arc, the start and end of the arc,
10406# the ids on the arc, and the outgoing arcs from the end.
10407proc readcache {f} {
10408 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10409 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10410 global allcwait
10411
10412 set a $nextarc
10413 set lim $cachedarcs
10414 if {$lim - $a > 500} {
10415 set lim [expr {$a + 500}]
10416 }
10417 if {[catch {
10418 if {$a == $lim} {
10419 # finish reading the cache and setting up arctags, etc.
10420 set line [gets $f]
10421 if {$line ne "1"} {error "bad final version"}
10422 close $f
10423 foreach id [array names idtags] {
10424 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10425 [llength $allparents($id)] == 1} {
10426 set a [lindex $arcnos($id) 0]
10427 if {$arctags($a) eq {}} {
10428 recalcarc $a
10429 }
10430 }
10431 }
10432 foreach id [array names idheads] {
10433 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10434 [llength $allparents($id)] == 1} {
10435 set a [lindex $arcnos($id) 0]
10436 if {$archeads($a) eq {}} {
10437 recalcarc $a
10438 }
10439 }
10440 }
10441 foreach id [lsort -unique $possible_seeds] {
10442 if {$arcnos($id) eq {}} {
10443 lappend seeds $id
10444 }
10445 }
10446 set allcwait 0
10447 } else {
10448 while {[incr a] <= $lim} {
10449 set line [gets $f]
10450 if {[llength $line] != 3} {error "bad line"}
10451 set s [lindex $line 0]
10452 set arcstart($a) $s
10453 lappend arcout($s) $a
10454 if {![info exists arcnos($s)]} {
10455 lappend possible_seeds $s
10456 set arcnos($s) {}
10457 }
10458 set e [lindex $line 1]
10459 if {$e eq {}} {
10460 set growing($a) 1
10461 } else {
10462 set arcend($a) $e
10463 if {![info exists arcout($e)]} {
10464 set arcout($e) {}
10465 }
10466 }
10467 set arcids($a) [lindex $line 2]
10468 foreach id $arcids($a) {
10469 lappend allparents($s) $id
10470 set s $id
10471 lappend arcnos($id) $a
10472 }
10473 if {![info exists allparents($s)]} {
10474 set allparents($s) {}
10475 }
10476 set arctags($a) {}
10477 set archeads($a) {}
10478 }
10479 set nextarc [expr {$a - 1}]
10480 }
10481 } err]} {
10482 dropcache $err
10483 return 0
10484 }
10485 if {!$allcwait} {
10486 getallcommits
10487 }
10488 return $allcwait
10489}
10490
10491proc getcache {f} {
10492 global nextarc cachedarcs possible_seeds
10493
10494 if {[catch {
10495 set line [gets $f]
10496 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10497 # make sure it's an integer
10498 set cachedarcs [expr {int([lindex $line 1])}]
10499 if {$cachedarcs < 0} {error "bad number of arcs"}
10500 set nextarc 0
10501 set possible_seeds {}
10502 run readcache $f
10503 } err]} {
10504 dropcache $err
10505 }
10506 return 0
10507}
10508
10509proc dropcache {err} {
10510 global allcwait nextarc cachedarcs seeds
10511
10512 #puts "dropping cache ($err)"
10513 foreach v {arcnos arcout arcids arcstart arcend growing \
10514 arctags archeads allparents allchildren} {
10515 global $v
Paul Mackerras009409f2015-05-02 20:53:36 +100010516 unset -nocomplain $v
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010517 }
10518 set allcwait 0
10519 set nextarc 0
10520 set cachedarcs 0
10521 set seeds {}
10522 getallcommits
10523}
10524
10525proc writecache {f} {
10526 global cachearc cachedarcs allccache
10527 global arcstart arcend arcnos arcids arcout
10528
10529 set a $cachearc
10530 set lim $cachedarcs
10531 if {$lim - $a > 1000} {
10532 set lim [expr {$a + 1000}]
10533 }
10534 if {[catch {
10535 while {[incr a] <= $lim} {
10536 if {[info exists arcend($a)]} {
10537 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10538 } else {
10539 puts $f [list $arcstart($a) {} $arcids($a)]
10540 }
10541 }
10542 } err]} {
10543 catch {close $f}
10544 catch {file delete $allccache}
10545 #puts "writing cache failed ($err)"
10546 return 0
10547 }
10548 set cachearc [expr {$a - 1}]
10549 if {$a > $cachedarcs} {
10550 puts $f "1"
10551 close $f
10552 return 0
10553 }
10554 return 1
10555}
10556
10557proc savecache {} {
10558 global nextarc cachedarcs cachearc allccache
10559
10560 if {$nextarc == $cachedarcs} return
10561 set cachearc 0
10562 set cachedarcs $nextarc
10563 catch {
10564 set f [open $allccache w]
10565 puts $f [list 1 $cachedarcs]
10566 run writecache $f
10567 }
10568}
10569
Paul Mackerrase11f1232007-06-16 20:29:25 +100010570# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10571# or 0 if neither is true.
10572proc anc_or_desc {a b} {
10573 global arcout arcstart arcend arcnos cached_isanc
10574
10575 if {$arcnos($a) eq $arcnos($b)} {
10576 # Both are on the same arc(s); either both are the same BMP,
10577 # or if one is not a BMP, the other is also not a BMP or is
10578 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +100010579 # Or both can be BMPs with no incoming arcs.
10580 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010581 return 0
10582 }
10583 # assert {[llength $arcnos($a)] == 1}
10584 set arc [lindex $arcnos($a) 0]
10585 set i [lsearch -exact $arcids($arc) $a]
10586 set j [lsearch -exact $arcids($arc) $b]
10587 if {$i < 0 || $i > $j} {
10588 return 1
10589 } else {
10590 return -1
10591 }
10592 }
10593
10594 if {![info exists arcout($a)]} {
10595 set arc [lindex $arcnos($a) 0]
10596 if {[info exists arcend($arc)]} {
10597 set aend $arcend($arc)
10598 } else {
10599 set aend {}
10600 }
10601 set a $arcstart($arc)
10602 } else {
10603 set aend $a
10604 }
10605 if {![info exists arcout($b)]} {
10606 set arc [lindex $arcnos($b) 0]
10607 if {[info exists arcend($arc)]} {
10608 set bend $arcend($arc)
10609 } else {
10610 set bend {}
10611 }
10612 set b $arcstart($arc)
10613 } else {
10614 set bend $b
10615 }
10616 if {$a eq $bend} {
10617 return 1
10618 }
10619 if {$b eq $aend} {
10620 return -1
10621 }
10622 if {[info exists cached_isanc($a,$bend)]} {
10623 if {$cached_isanc($a,$bend)} {
10624 return 1
10625 }
10626 }
10627 if {[info exists cached_isanc($b,$aend)]} {
10628 if {$cached_isanc($b,$aend)} {
10629 return -1
10630 }
10631 if {[info exists cached_isanc($a,$bend)]} {
10632 return 0
10633 }
10634 }
10635
10636 set todo [list $a $b]
10637 set anc($a) a
10638 set anc($b) b
10639 for {set i 0} {$i < [llength $todo]} {incr i} {
10640 set x [lindex $todo $i]
10641 if {$anc($x) eq {}} {
10642 continue
10643 }
10644 foreach arc $arcnos($x) {
10645 set xd $arcstart($arc)
10646 if {$xd eq $bend} {
10647 set cached_isanc($a,$bend) 1
10648 set cached_isanc($b,$aend) 0
10649 return 1
10650 } elseif {$xd eq $aend} {
10651 set cached_isanc($b,$aend) 1
10652 set cached_isanc($a,$bend) 0
10653 return -1
10654 }
10655 if {![info exists anc($xd)]} {
10656 set anc($xd) $anc($x)
10657 lappend todo $xd
10658 } elseif {$anc($xd) ne $anc($x)} {
10659 set anc($xd) {}
10660 }
10661 }
10662 }
10663 set cached_isanc($a,$bend) 0
10664 set cached_isanc($b,$aend) 0
10665 return 0
10666}
10667
10668# This identifies whether $desc has an ancestor that is
10669# a growing tip of the graph and which is not an ancestor of $anc
10670# and returns 0 if so and 1 if not.
10671# If we subsequently discover a tag on such a growing tip, and that
10672# turns out to be a descendent of $anc (which it could, since we
10673# don't necessarily see children before parents), then $desc
10674# isn't a good choice to display as a descendent tag of
10675# $anc (since it is the descendent of another tag which is
10676# a descendent of $anc). Similarly, $anc isn't a good choice to
10677# display as a ancestor tag of $desc.
10678#
10679proc is_certain {desc anc} {
10680 global arcnos arcout arcstart arcend growing problems
10681
10682 set certain {}
10683 if {[llength $arcnos($anc)] == 1} {
10684 # tags on the same arc are certain
10685 if {$arcnos($desc) eq $arcnos($anc)} {
10686 return 1
10687 }
10688 if {![info exists arcout($anc)]} {
10689 # if $anc is partway along an arc, use the start of the arc instead
10690 set a [lindex $arcnos($anc) 0]
10691 set anc $arcstart($a)
10692 }
10693 }
10694 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
10695 set x $desc
10696 } else {
10697 set a [lindex $arcnos($desc) 0]
10698 set x $arcend($a)
10699 }
10700 if {$x == $anc} {
10701 return 1
10702 }
10703 set anclist [list $x]
10704 set dl($x) 1
10705 set nnh 1
10706 set ngrowanc 0
10707 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
10708 set x [lindex $anclist $i]
10709 if {$dl($x)} {
10710 incr nnh -1
10711 }
10712 set done($x) 1
10713 foreach a $arcout($x) {
10714 if {[info exists growing($a)]} {
10715 if {![info exists growanc($x)] && $dl($x)} {
10716 set growanc($x) 1
10717 incr ngrowanc
10718 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010719 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010720 set y $arcend($a)
10721 if {[info exists dl($y)]} {
10722 if {$dl($y)} {
10723 if {!$dl($x)} {
10724 set dl($y) 0
10725 if {![info exists done($y)]} {
10726 incr nnh -1
10727 }
10728 if {[info exists growanc($x)]} {
10729 incr ngrowanc -1
10730 }
10731 set xl [list $y]
10732 for {set k 0} {$k < [llength $xl]} {incr k} {
10733 set z [lindex $xl $k]
10734 foreach c $arcout($z) {
10735 if {[info exists arcend($c)]} {
10736 set v $arcend($c)
10737 if {[info exists dl($v)] && $dl($v)} {
10738 set dl($v) 0
10739 if {![info exists done($v)]} {
10740 incr nnh -1
10741 }
10742 if {[info exists growanc($v)]} {
10743 incr ngrowanc -1
10744 }
10745 lappend xl $v
10746 }
10747 }
10748 }
10749 }
10750 }
10751 }
10752 } elseif {$y eq $anc || !$dl($x)} {
10753 set dl($y) 0
10754 lappend anclist $y
10755 } else {
10756 set dl($y) 1
10757 lappend anclist $y
10758 incr nnh
10759 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010760 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010761 }
10762 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010763 foreach x [array names growanc] {
10764 if {$dl($x)} {
10765 return 0
10766 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010767 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010768 }
10769 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010770}
10771
Paul Mackerrase11f1232007-06-16 20:29:25 +100010772proc validate_arctags {a} {
10773 global arctags idtags
10774
10775 set i -1
10776 set na $arctags($a)
10777 foreach id $arctags($a) {
10778 incr i
10779 if {![info exists idtags($id)]} {
10780 set na [lreplace $na $i $i]
10781 incr i -1
10782 }
10783 }
10784 set arctags($a) $na
10785}
10786
10787proc validate_archeads {a} {
10788 global archeads idheads
10789
10790 set i -1
10791 set na $archeads($a)
10792 foreach id $archeads($a) {
10793 incr i
10794 if {![info exists idheads($id)]} {
10795 set na [lreplace $na $i $i]
10796 incr i -1
10797 }
10798 }
10799 set archeads($a) $na
10800}
10801
10802# Return the list of IDs that have tags that are descendents of id,
10803# ignoring IDs that are descendents of IDs already reported.
10804proc desctags {id} {
10805 global arcnos arcstart arcids arctags idtags allparents
10806 global growing cached_dtags
10807
10808 if {![info exists allparents($id)]} {
10809 return {}
10810 }
10811 set t1 [clock clicks -milliseconds]
10812 set argid $id
10813 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10814 # part-way along an arc; check that arc first
10815 set a [lindex $arcnos($id) 0]
10816 if {$arctags($a) ne {}} {
10817 validate_arctags $a
10818 set i [lsearch -exact $arcids($a) $id]
10819 set tid {}
10820 foreach t $arctags($a) {
10821 set j [lsearch -exact $arcids($a) $t]
10822 if {$j >= $i} break
10823 set tid $t
10824 }
10825 if {$tid ne {}} {
10826 return $tid
10827 }
10828 }
10829 set id $arcstart($a)
10830 if {[info exists idtags($id)]} {
10831 return $id
10832 }
10833 }
10834 if {[info exists cached_dtags($id)]} {
10835 return $cached_dtags($id)
10836 }
10837
10838 set origid $id
10839 set todo [list $id]
10840 set queued($id) 1
10841 set nc 1
10842 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10843 set id [lindex $todo $i]
10844 set done($id) 1
10845 set ta [info exists hastaggedancestor($id)]
10846 if {!$ta} {
10847 incr nc -1
10848 }
10849 # ignore tags on starting node
10850 if {!$ta && $i > 0} {
10851 if {[info exists idtags($id)]} {
10852 set tagloc($id) $id
10853 set ta 1
10854 } elseif {[info exists cached_dtags($id)]} {
10855 set tagloc($id) $cached_dtags($id)
10856 set ta 1
10857 }
10858 }
10859 foreach a $arcnos($id) {
10860 set d $arcstart($a)
10861 if {!$ta && $arctags($a) ne {}} {
10862 validate_arctags $a
10863 if {$arctags($a) ne {}} {
10864 lappend tagloc($id) [lindex $arctags($a) end]
10865 }
10866 }
10867 if {$ta || $arctags($a) ne {}} {
10868 set tomark [list $d]
10869 for {set j 0} {$j < [llength $tomark]} {incr j} {
10870 set dd [lindex $tomark $j]
10871 if {![info exists hastaggedancestor($dd)]} {
10872 if {[info exists done($dd)]} {
10873 foreach b $arcnos($dd) {
10874 lappend tomark $arcstart($b)
10875 }
10876 if {[info exists tagloc($dd)]} {
10877 unset tagloc($dd)
10878 }
10879 } elseif {[info exists queued($dd)]} {
10880 incr nc -1
10881 }
10882 set hastaggedancestor($dd) 1
10883 }
10884 }
10885 }
10886 if {![info exists queued($d)]} {
10887 lappend todo $d
10888 set queued($d) 1
10889 if {![info exists hastaggedancestor($d)]} {
10890 incr nc
10891 }
10892 }
10893 }
10894 }
10895 set tags {}
10896 foreach id [array names tagloc] {
10897 if {![info exists hastaggedancestor($id)]} {
10898 foreach t $tagloc($id) {
10899 if {[lsearch -exact $tags $t] < 0} {
10900 lappend tags $t
10901 }
10902 }
10903 }
10904 }
10905 set t2 [clock clicks -milliseconds]
10906 set loopix $i
10907
10908 # remove tags that are descendents of other tags
10909 for {set i 0} {$i < [llength $tags]} {incr i} {
10910 set a [lindex $tags $i]
10911 for {set j 0} {$j < $i} {incr j} {
10912 set b [lindex $tags $j]
10913 set r [anc_or_desc $a $b]
10914 if {$r == 1} {
10915 set tags [lreplace $tags $j $j]
10916 incr j -1
10917 incr i -1
10918 } elseif {$r == -1} {
10919 set tags [lreplace $tags $i $i]
10920 incr i -1
10921 break
10922 }
10923 }
10924 }
10925
10926 if {[array names growing] ne {}} {
10927 # graph isn't finished, need to check if any tag could get
10928 # eclipsed by another tag coming later. Simply ignore any
10929 # tags that could later get eclipsed.
10930 set ctags {}
10931 foreach t $tags {
10932 if {[is_certain $t $origid]} {
10933 lappend ctags $t
10934 }
10935 }
10936 if {$tags eq $ctags} {
10937 set cached_dtags($origid) $tags
10938 } else {
10939 set tags $ctags
10940 }
10941 } else {
10942 set cached_dtags($origid) $tags
10943 }
10944 set t3 [clock clicks -milliseconds]
10945 if {0 && $t3 - $t1 >= 100} {
10946 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
10947 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10948 }
10949 return $tags
10950}
10951
10952proc anctags {id} {
10953 global arcnos arcids arcout arcend arctags idtags allparents
10954 global growing cached_atags
10955
10956 if {![info exists allparents($id)]} {
10957 return {}
10958 }
10959 set t1 [clock clicks -milliseconds]
10960 set argid $id
10961 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10962 # part-way along an arc; check that arc first
10963 set a [lindex $arcnos($id) 0]
10964 if {$arctags($a) ne {}} {
10965 validate_arctags $a
10966 set i [lsearch -exact $arcids($a) $id]
10967 foreach t $arctags($a) {
10968 set j [lsearch -exact $arcids($a) $t]
10969 if {$j > $i} {
10970 return $t
10971 }
10972 }
10973 }
10974 if {![info exists arcend($a)]} {
10975 return {}
10976 }
10977 set id $arcend($a)
10978 if {[info exists idtags($id)]} {
10979 return $id
10980 }
10981 }
10982 if {[info exists cached_atags($id)]} {
10983 return $cached_atags($id)
10984 }
10985
10986 set origid $id
10987 set todo [list $id]
10988 set queued($id) 1
10989 set taglist {}
10990 set nc 1
10991 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10992 set id [lindex $todo $i]
10993 set done($id) 1
10994 set td [info exists hastaggeddescendent($id)]
10995 if {!$td} {
10996 incr nc -1
10997 }
10998 # ignore tags on starting node
10999 if {!$td && $i > 0} {
11000 if {[info exists idtags($id)]} {
11001 set tagloc($id) $id
11002 set td 1
11003 } elseif {[info exists cached_atags($id)]} {
11004 set tagloc($id) $cached_atags($id)
11005 set td 1
11006 }
11007 }
11008 foreach a $arcout($id) {
11009 if {!$td && $arctags($a) ne {}} {
11010 validate_arctags $a
11011 if {$arctags($a) ne {}} {
11012 lappend tagloc($id) [lindex $arctags($a) 0]
11013 }
11014 }
11015 if {![info exists arcend($a)]} continue
11016 set d $arcend($a)
11017 if {$td || $arctags($a) ne {}} {
11018 set tomark [list $d]
11019 for {set j 0} {$j < [llength $tomark]} {incr j} {
11020 set dd [lindex $tomark $j]
11021 if {![info exists hastaggeddescendent($dd)]} {
11022 if {[info exists done($dd)]} {
11023 foreach b $arcout($dd) {
11024 if {[info exists arcend($b)]} {
11025 lappend tomark $arcend($b)
11026 }
11027 }
11028 if {[info exists tagloc($dd)]} {
11029 unset tagloc($dd)
11030 }
11031 } elseif {[info exists queued($dd)]} {
11032 incr nc -1
11033 }
11034 set hastaggeddescendent($dd) 1
11035 }
11036 }
11037 }
11038 if {![info exists queued($d)]} {
11039 lappend todo $d
11040 set queued($d) 1
11041 if {![info exists hastaggeddescendent($d)]} {
11042 incr nc
11043 }
11044 }
11045 }
11046 }
11047 set t2 [clock clicks -milliseconds]
11048 set loopix $i
11049 set tags {}
11050 foreach id [array names tagloc] {
11051 if {![info exists hastaggeddescendent($id)]} {
11052 foreach t $tagloc($id) {
11053 if {[lsearch -exact $tags $t] < 0} {
11054 lappend tags $t
11055 }
11056 }
11057 }
11058 }
11059
11060 # remove tags that are ancestors of other tags
11061 for {set i 0} {$i < [llength $tags]} {incr i} {
11062 set a [lindex $tags $i]
11063 for {set j 0} {$j < $i} {incr j} {
11064 set b [lindex $tags $j]
11065 set r [anc_or_desc $a $b]
11066 if {$r == -1} {
11067 set tags [lreplace $tags $j $j]
11068 incr j -1
11069 incr i -1
11070 } elseif {$r == 1} {
11071 set tags [lreplace $tags $i $i]
11072 incr i -1
11073 break
11074 }
11075 }
11076 }
11077
11078 if {[array names growing] ne {}} {
11079 # graph isn't finished, need to check if any tag could get
11080 # eclipsed by another tag coming later. Simply ignore any
11081 # tags that could later get eclipsed.
11082 set ctags {}
11083 foreach t $tags {
11084 if {[is_certain $origid $t]} {
11085 lappend ctags $t
11086 }
11087 }
11088 if {$tags eq $ctags} {
11089 set cached_atags($origid) $tags
11090 } else {
11091 set tags $ctags
11092 }
11093 } else {
11094 set cached_atags($origid) $tags
11095 }
11096 set t3 [clock clicks -milliseconds]
11097 if {0 && $t3 - $t1 >= 100} {
11098 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
11099 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
11100 }
11101 return $tags
11102}
11103
11104# Return the list of IDs that have heads that are descendents of id,
11105# including id itself if it has a head.
11106proc descheads {id} {
11107 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011108 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100011109
11110 if {![info exists allparents($id)]} {
11111 return {}
11112 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011113 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011114 if {![info exists arcout($id)]} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011115 # part-way along an arc; check it first
11116 set a [lindex $arcnos($id) 0]
11117 if {$archeads($a) ne {}} {
11118 validate_archeads $a
11119 set i [lsearch -exact $arcids($a) $id]
11120 foreach t $archeads($a) {
11121 set j [lsearch -exact $arcids($a) $t]
11122 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011123 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100011124 }
11125 }
11126 set id $arcstart($a)
11127 }
11128 set origid $id
11129 set todo [list $id]
11130 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011131 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011132 for {set i 0} {$i < [llength $todo]} {incr i} {
11133 set id [lindex $todo $i]
11134 if {[info exists cached_dheads($id)]} {
11135 set ret [concat $ret $cached_dheads($id)]
11136 } else {
11137 if {[info exists idheads($id)]} {
11138 lappend ret $id
11139 }
11140 foreach a $arcnos($id) {
11141 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100011142 validate_archeads $a
11143 if {$archeads($a) ne {}} {
11144 set ret [concat $ret $archeads($a)]
11145 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011146 }
11147 set d $arcstart($a)
11148 if {![info exists seen($d)]} {
11149 lappend todo $d
11150 set seen($d) 1
11151 }
11152 }
11153 }
11154 }
11155 set ret [lsort -unique $ret]
11156 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011157 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100011158}
11159
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011160proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011161 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011162
Paul Mackerrase11f1232007-06-16 20:29:25 +100011163 if {![info exists arcnos($id)]} return
11164 if {![info exists arcout($id)]} {
11165 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011166 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011167 unset -nocomplain cached_dtags
11168 unset -nocomplain cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011169}
11170
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011171proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011172 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011173
Paul Mackerrase11f1232007-06-16 20:29:25 +100011174 if {![info exists arcnos($hid)]} return
11175 if {![info exists arcout($hid)]} {
11176 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011177 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011178 unset -nocomplain cached_dheads
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011179}
11180
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011181proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011182 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011183
Paul Mackerras009409f2015-05-02 20:53:36 +100011184 unset -nocomplain cached_dheads
Paul Mackerras10299152006-08-02 09:52:01 +100011185}
11186
Paul Mackerrase11f1232007-06-16 20:29:25 +100011187proc movedhead {hid head} {
11188 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011189
Paul Mackerrase11f1232007-06-16 20:29:25 +100011190 if {![info exists arcnos($hid)]} return
11191 if {![info exists arcout($hid)]} {
11192 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011193 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011194 unset -nocomplain cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011195}
11196
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011197proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070011198 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100011199 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011200
Paul Mackerrase11f1232007-06-16 20:29:25 +100011201 foreach id [concat [array names idheads] [array names idtags]] {
11202 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
11203 set a [lindex $arcnos($id) 0]
11204 if {![info exists donearc($a)]} {
11205 recalcarc $a
11206 set donearc($a) 1
11207 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011208 }
11209 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011210 unset -nocomplain cached_tagcontent
11211 unset -nocomplain cached_dtags
11212 unset -nocomplain cached_atags
11213 unset -nocomplain cached_dheads
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011214}
11215
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011216proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011217 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011218
11219 set refids [concat [array names idtags] \
11220 [array names idheads] [array names idotherrefs]]
11221 foreach id $refids {
11222 if {![info exists ref($id)]} {
11223 set ref($id) [listrefs $id]
11224 }
11225 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011226 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011227 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011228 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011229 set refids [lsort -unique [concat $refids [array names idtags] \
11230 [array names idheads] [array names idotherrefs]]]
11231 foreach id $refids {
11232 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011233 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011234 redrawtags $id
11235 }
11236 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011237 if {$oldmainhead ne $mainheadid} {
11238 redrawtags $oldmainhead
11239 redrawtags $mainheadid
11240 }
Paul Mackerras887c9962007-08-20 19:36:20 +100011241 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011242}
11243
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011244proc listrefs {id} {
11245 global idtags idheads idotherrefs
11246
11247 set x {}
11248 if {[info exists idtags($id)]} {
11249 set x $idtags($id)
11250 }
11251 set y {}
11252 if {[info exists idheads($id)]} {
11253 set y $idheads($id)
11254 }
11255 set z {}
11256 if {[info exists idotherrefs($id)]} {
11257 set z $idotherrefs($id)
11258 }
11259 return [list $x $y $z]
11260}
11261
Paul Mackerras4399fe32013-01-03 10:10:31 +110011262proc add_tag_ctext {tag} {
11263 global ctext cached_tagcontent tagids
11264
11265 if {![info exists cached_tagcontent($tag)]} {
11266 catch {
11267 set cached_tagcontent($tag) [exec git cat-file -p $tag]
11268 }
11269 }
11270 $ctext insert end "[mc "Tag"]: $tag\n" bold
11271 if {[info exists cached_tagcontent($tag)]} {
11272 set text $cached_tagcontent($tag)
11273 } else {
11274 set text "[mc "Id"]: $tagids($tag)"
11275 }
11276 appendwithlinks $text {}
11277}
11278
Paul Mackerras106288c2005-08-19 23:11:39 +100011279proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070011280 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100011281
11282 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +110011283 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100011284 }
11285 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100011286 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011287 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100011288 set linknum 0
Paul Mackerras4399fe32013-01-03 10:10:31 +110011289 add_tag_ctext $tag
11290 maybe_scroll_ctext 1
11291 $ctext conf -state disabled
11292 init_flist {}
11293}
11294
11295proc showtags {id isnew} {
11296 global idtags ctext linknum
11297
11298 if {$isnew} {
11299 addtohistory [list showtags $id 0] savectextpos
Paul Mackerras62d3ea62006-09-11 10:36:53 +100011300 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011301 $ctext conf -state normal
11302 clear_ctext
11303 settabs 0
11304 set linknum 0
11305 set sep {}
11306 foreach tag $idtags($id) {
11307 $ctext insert end $sep
11308 add_tag_ctext $tag
11309 set sep "\n\n"
Paul Mackerras106288c2005-08-19 23:11:39 +100011310 }
Pat Thoytsa80e82f2009-11-14 13:21:09 +000011311 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100011312 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100011313 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100011314}
11315
Paul Mackerras1d10f362005-05-15 12:55:47 +000011316proc doquit {} {
11317 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010011318 global gitktmpdir
11319
Paul Mackerras1d10f362005-05-15 12:55:47 +000011320 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050011321 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000011322 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010011323
11324 if {[info exists gitktmpdir]} {
11325 catch {file delete -force $gitktmpdir}
11326 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000011327}
11328
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011329proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011330 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011331
11332 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011333 ${NS}::button $top.${font}but -text $which \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011334 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011335 ${NS}::label $top.$font -relief flat -font $font \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011336 -text $fontattr($font,family) -justify left
11337 grid x $top.${font}but $top.$font -sticky w
11338}
11339
11340proc choosefont {font which} {
11341 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010011342 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011343
11344 set fontparam(which) $which
11345 set fontparam(font) $font
11346 set fontparam(family) [font actual $font -family]
11347 set fontparam(size) $fontattr($font,size)
11348 set fontparam(weight) $fontattr($font,weight)
11349 set fontparam(slant) $fontattr($font,slant)
11350 set top .gitkfont
11351 set fonttop $top
11352 if {![winfo exists $top]} {
11353 font create sample
11354 eval font config sample [font actual $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011355 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011356 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010011357 wm title $top [mc "Gitk font chooser"]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011358 ${NS}::label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011359 pack $top.l -side top
11360 set fontlist [lsort [font families]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011361 ${NS}::frame $top.f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011362 listbox $top.f.fam -listvariable fontlist \
11363 -yscrollcommand [list $top.f.sb set]
11364 bind $top.f.fam <<ListboxSelect>> selfontfam
Pat Thoytsd93f1712009-04-17 01:24:35 +010011365 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011366 pack $top.f.sb -side right -fill y
11367 pack $top.f.fam -side left -fill both -expand 1
11368 pack $top.f -side top -fill both -expand 1
Pat Thoytsd93f1712009-04-17 01:24:35 +010011369 ${NS}::frame $top.g
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011370 spinbox $top.g.size -from 4 -to 40 -width 4 \
11371 -textvariable fontparam(size) \
11372 -validatecommand {string is integer -strict %s}
11373 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011374 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011375 -variable fontparam(weight) -onvalue bold -offvalue normal
11376 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011377 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011378 -variable fontparam(slant) -onvalue italic -offvalue roman
11379 pack $top.g.size $top.g.bold $top.g.ital -side left
11380 pack $top.g -side top
11381 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
11382 -background white
11383 $top.c create text 100 25 -anchor center -text $which -font sample \
11384 -fill black -tags text
11385 bind $top.c <Configure> [list centertext $top.c]
11386 pack $top.c -side top -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +010011387 ${NS}::frame $top.buts
11388 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
11389 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011390 bind $top <Key-Return> fontok
11391 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011392 grid $top.buts.ok $top.buts.can
11393 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11394 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11395 pack $top.buts -side bottom -fill x
11396 trace add variable fontparam write chg_fontparam
11397 } else {
11398 raise $top
11399 $top.c itemconf text -text $which
11400 }
11401 set i [lsearch -exact $fontlist $fontparam(family)]
11402 if {$i >= 0} {
11403 $top.f.fam selection set $i
11404 $top.f.fam see $i
11405 }
11406}
11407
11408proc centertext {w} {
11409 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11410}
11411
11412proc fontok {} {
11413 global fontparam fontpref prefstop
11414
11415 set f $fontparam(font)
11416 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11417 if {$fontparam(weight) eq "bold"} {
11418 lappend fontpref($f) "bold"
11419 }
11420 if {$fontparam(slant) eq "italic"} {
11421 lappend fontpref($f) "italic"
11422 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011423 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011424 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011425
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011426 fontcan
11427}
11428
11429proc fontcan {} {
11430 global fonttop fontparam
11431
11432 if {[info exists fonttop]} {
11433 catch {destroy $fonttop}
11434 catch {font delete sample}
11435 unset fonttop
11436 unset fontparam
11437 }
11438}
11439
Pat Thoytsd93f1712009-04-17 01:24:35 +010011440if {[package vsatisfies [package provide Tk] 8.6]} {
11441 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11442 # function to make use of it.
11443 proc choosefont {font which} {
11444 tk fontchooser configure -title $which -font $font \
11445 -command [list on_choosefont $font $which]
11446 tk fontchooser show
11447 }
11448 proc on_choosefont {font which newfont} {
11449 global fontparam
11450 puts stderr "$font $newfont"
11451 array set f [font actual $newfont]
11452 set fontparam(which) $which
11453 set fontparam(font) $font
11454 set fontparam(family) $f(-family)
11455 set fontparam(size) $f(-size)
11456 set fontparam(weight) $f(-weight)
11457 set fontparam(slant) $f(-slant)
11458 fontok
11459 }
11460}
11461
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011462proc selfontfam {} {
11463 global fonttop fontparam
11464
11465 set i [$fonttop.f.fam curselection]
11466 if {$i ne {}} {
11467 set fontparam(family) [$fonttop.f.fam get $i]
11468 }
11469}
11470
11471proc chg_fontparam {v sub op} {
11472 global fontparam
11473
11474 font config sample -$sub $fontparam($sub)
11475}
11476
Pat Thoyts44acce02011-12-13 14:56:49 +000011477# Create a property sheet tab page
11478proc create_prefs_page {w} {
11479 global NS
11480 set parent [join [lrange [split $w .] 0 end-1] .]
11481 if {[winfo class $parent] eq "TNotebook"} {
11482 ${NS}::frame $w
11483 } else {
11484 ${NS}::labelframe $w
11485 }
11486}
11487
11488proc prefspage_general {notebook} {
11489 global NS maxwidth maxgraphpct showneartags showlocalchanges
11490 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011491 global hideremotes want_ttk have_ttk maxrefs
Pat Thoyts44acce02011-12-13 14:56:49 +000011492
11493 set page [create_prefs_page $notebook.general]
11494
11495 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11496 grid $page.ldisp - -sticky w -pady 10
11497 ${NS}::label $page.spacer -text " "
11498 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11499 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11500 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
Alex Henrie8a1692f2015-01-22 01:19:39 -070011501 #xgettext:no-tcl-format
Pat Thoyts44acce02011-12-13 14:56:49 +000011502 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11503 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11504 grid x $page.maxpctl $page.maxpct -sticky w
11505 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
11506 -variable showlocalchanges
11507 grid x $page.showlocal -sticky w
11508 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
11509 -variable autoselect
11510 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11511 grid x $page.autoselect $page.autosellen -sticky w
11512 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
11513 -variable hideremotes
11514 grid x $page.hideremotes -sticky w
11515
11516 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11517 grid $page.ddisp - -sticky w -pady 10
11518 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11519 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11520 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011521 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Pat Thoyts44acce02011-12-13 14:56:49 +000011522 -variable showneartags
11523 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011524 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11525 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11526 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011527 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
11528 -variable limitdiffs
11529 grid x $page.ldiff -sticky w
11530 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
11531 -variable perfile_attrs
11532 grid x $page.lattr -sticky w
11533
11534 ${NS}::entry $page.extdifft -textvariable extdifftool
11535 ${NS}::frame $page.extdifff
11536 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11537 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11538 pack $page.extdifff.l $page.extdifff.b -side left
11539 pack configure $page.extdifff.l -padx 10
11540 grid x $page.extdifff $page.extdifft -sticky ew
11541
11542 ${NS}::label $page.lgen -text [mc "General options"]
11543 grid $page.lgen - -sticky w -pady 10
11544 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
11545 -text [mc "Use themed widgets"]
11546 if {$have_ttk} {
11547 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
11548 } else {
11549 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
11550 }
11551 grid x $page.want_ttk $page.ttk_note -sticky w
11552 return $page
11553}
11554
11555proc prefspage_colors {notebook} {
11556 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
11557
11558 set page [create_prefs_page $notebook.colors]
11559
11560 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11561 grid $page.cdisp - -sticky w -pady 10
11562 label $page.ui -padx 40 -relief sunk -background $uicolor
11563 ${NS}::button $page.uibut -text [mc "Interface"] \
11564 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11565 grid x $page.uibut $page.ui -sticky w
11566 label $page.bg -padx 40 -relief sunk -background $bgcolor
11567 ${NS}::button $page.bgbut -text [mc "Background"] \
11568 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
11569 grid x $page.bgbut $page.bg -sticky w
11570 label $page.fg -padx 40 -relief sunk -background $fgcolor
11571 ${NS}::button $page.fgbut -text [mc "Foreground"] \
11572 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
11573 grid x $page.fgbut $page.fg -sticky w
11574 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11575 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
11576 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11577 [list $ctext tag conf d0 -foreground]]
11578 grid x $page.diffoldbut $page.diffold -sticky w
11579 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11580 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
11581 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11582 [list $ctext tag conf dresult -foreground]]
11583 grid x $page.diffnewbut $page.diffnew -sticky w
11584 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11585 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
11586 -command [list choosecolor diffcolors 2 $page.hunksep \
11587 [mc "diff hunk header"] \
11588 [list $ctext tag conf hunksep -foreground]]
11589 grid x $page.hunksepbut $page.hunksep -sticky w
11590 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11591 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
11592 -command [list choosecolor markbgcolor {} $page.markbgsep \
11593 [mc "marked line background"] \
11594 [list $ctext tag conf omark -background]]
11595 grid x $page.markbgbut $page.markbgsep -sticky w
11596 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11597 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
11598 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
11599 grid x $page.selbgbut $page.selbgsep -sticky w
11600 return $page
11601}
11602
11603proc prefspage_fonts {notebook} {
11604 global NS
11605 set page [create_prefs_page $notebook.fonts]
11606 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11607 grid $page.cfont - -sticky w -pady 10
11608 mkfontdisp mainfont $page [mc "Main font"]
11609 mkfontdisp textfont $page [mc "Diff display font"]
11610 mkfontdisp uifont $page [mc "User interface font"]
11611 return $page
11612}
11613
Paul Mackerras712fcc02005-11-30 09:28:16 +110011614proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011615 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011616 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011617 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011618 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011619 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011620
Paul Mackerras712fcc02005-11-30 09:28:16 +110011621 set top .gitkprefs
11622 set prefstop $top
11623 if {[winfo exists $top]} {
11624 raise $top
11625 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011626 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011627 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011628 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110011629 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011630 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011631 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011632 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011633 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011634
Pat Thoyts44acce02011-12-13 14:56:49 +000011635 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
11636 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011637 } else {
Pat Thoyts44acce02011-12-13 14:56:49 +000011638 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011639 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011640
Pat Thoyts44acce02011-12-13 14:56:49 +000011641 lappend pages [prefspage_general $notebook] [mc "General"]
11642 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11643 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011644 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011645 foreach {page title} $pages {
11646 if {$use_notebook} {
11647 $notebook add $page -text $title
11648 } else {
11649 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11650 -text $title -command [list raise $page]]
11651 $page configure -text $title
11652 grid $btn -row 0 -column [incr col] -sticky w
11653 grid $page -row 1 -column 0 -sticky news -columnspan 100
11654 }
11655 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011656
Pat Thoyts44acce02011-12-13 14:56:49 +000011657 if {!$use_notebook} {
11658 grid columnconfigure $notebook 0 -weight 1
11659 grid rowconfigure $notebook 1 -weight 1
11660 raise [lindex $pages 0]
11661 }
11662
11663 grid $notebook -sticky news -padx 2 -pady 2
11664 grid rowconfigure $top 0 -weight 1
11665 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011666
Pat Thoytsd93f1712009-04-17 01:24:35 +010011667 ${NS}::frame $top.buts
11668 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11669 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011670 bind $top <Key-Return> prefsok
11671 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011672 grid $top.buts.ok $top.buts.can
11673 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11674 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11675 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011676 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011677 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011678}
11679
Thomas Arcila314f5de2008-03-24 12:55:36 +010011680proc choose_extdiff {} {
11681 global extdifftool
11682
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011683 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011684 if {$prog ne {}} {
11685 set extdifftool $prog
11686 }
11687}
11688
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011689proc choosecolor {v vi w x cmd} {
11690 global $v
11691
11692 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011693 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011694 if {$c eq {}} return
11695 $w conf -background $c
11696 lset $v $vi $c
11697 eval $cmd $c
11698}
11699
Mark Levedahl60378c02007-05-20 12:12:48 -040011700proc setselbg {c} {
11701 global bglist cflist
11702 foreach w $bglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011703 if {[winfo exists $w]} {
11704 $w configure -selectbackground $c
11705 }
Mark Levedahl60378c02007-05-20 12:12:48 -040011706 }
11707 $cflist tag configure highlight \
11708 -background [$cflist cget -selectbackground]
11709 allcanvs itemconf secsel -fill $c
11710}
11711
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011712# This sets the background color and the color scheme for the whole UI.
11713# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11714# if we don't specify one ourselves, which makes the checkbuttons and
11715# radiobuttons look bad. This chooses white for selectColor if the
11716# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011717proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011718 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011719 set bg [winfo rgb . $c]
11720 set selc black
11721 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
11722 set selc white
11723 }
11724 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011725}
11726
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011727proc setbg {c} {
11728 global bglist
11729
11730 foreach w $bglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011731 if {[winfo exists $w]} {
11732 $w conf -background $c
11733 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011734 }
11735}
11736
11737proc setfg {c} {
11738 global fglist canv
11739
11740 foreach w $fglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011741 if {[winfo exists $w]} {
11742 $w conf -foreground $c
11743 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011744 }
11745 allcanvs itemconf text -fill $c
11746 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011747 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011748}
11749
Paul Mackerras712fcc02005-11-30 09:28:16 +110011750proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011751 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011752
Paul Mackerras3de07112007-10-23 22:40:50 +100011753 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011754 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras94503912007-10-23 10:33:38 +100011755 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110011756 set $v $oldprefs($v)
11757 }
11758 catch {destroy $prefstop}
11759 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011760 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011761}
11762
11763proc prefsok {} {
11764 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011765 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011766 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011767 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011768 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011769
11770 catch {destroy $prefstop}
11771 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011772 fontcan
11773 set fontchanged 0
11774 if {$mainfont ne $fontpref(mainfont)} {
11775 set mainfont $fontpref(mainfont)
11776 parsefont mainfont $mainfont
11777 eval font configure mainfont [fontflags mainfont]
11778 eval font configure mainfontbold [fontflags mainfont 1]
11779 setcoords
11780 set fontchanged 1
11781 }
11782 if {$textfont ne $fontpref(textfont)} {
11783 set textfont $fontpref(textfont)
11784 parsefont textfont $textfont
11785 eval font configure textfont [fontflags textfont]
11786 eval font configure textfontbold [fontflags textfont 1]
11787 }
11788 if {$uifont ne $fontpref(uifont)} {
11789 set uifont $fontpref(uifont)
11790 parsefont uifont $uifont
11791 eval font configure uifont [fontflags uifont]
11792 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011793 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011794 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
11795 if {$showlocalchanges} {
11796 doshowlocalchanges
11797 } else {
11798 dohidelocalchanges
11799 }
11800 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011801 if {$limitdiffs != $oldprefs(limitdiffs) ||
11802 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11803 # treediffs elements are limited by path;
11804 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras009409f2015-05-02 20:53:36 +100011805 unset -nocomplain treediffs
Paul Mackerras74a40c72007-10-24 10:16:56 +100011806 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011807 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011808 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11809 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011810 } elseif {$showneartags != $oldprefs(showneartags) ||
11811 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011812 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011813 }
Thomas Rastffe15292009-08-03 23:53:36 +020011814 if {$hideremotes != $oldprefs(hideremotes)} {
11815 rereadrefs
11816 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011817}
11818
11819proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011820 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011821 if {$d ne {}} {
Anders Kaseorg019e1632014-05-12 07:25:58 -040011822 # If $datetimeformat includes a timezone, display in the
11823 # timezone of the argument. Otherwise, display in local time.
11824 if {[string match {*%[zZ]*} $datetimeformat]} {
11825 if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
11826 # Tcl < 8.5 does not support -timezone. Emulate it by
11827 # setting TZ (e.g. TZ=<-0430>+04:30).
11828 global env
11829 if {[info exists env(TZ)]} {
11830 set savedTZ $env(TZ)
11831 }
11832 set zone [lindex $d 1]
11833 set sign [string map {+ - - +} [string index $zone 0]]
11834 set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
11835 set d [clock format [lindex $d 0] -format $datetimeformat]
11836 if {[info exists savedTZ]} {
11837 set env(TZ) $savedTZ
11838 } else {
11839 unset env(TZ)
11840 }
11841 }
11842 } else {
11843 set d [clock format [lindex $d 0] -format $datetimeformat]
11844 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011845 }
11846 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011847}
11848
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011849# This list of encoding names and aliases is distilled from
11850# http://www.iana.org/assignments/character-sets.
11851# Not all of them are supported by Tcl.
11852set encoding_aliases {
11853 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11854 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11855 { ISO-10646-UTF-1 csISO10646UTF1 }
11856 { ISO_646.basic:1983 ref csISO646basic1983 }
11857 { INVARIANT csINVARIANT }
11858 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11859 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11860 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11861 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11862 { NATS-DANO iso-ir-9-1 csNATSDANO }
11863 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11864 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11865 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11866 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11867 { ISO-2022-KR csISO2022KR }
11868 { EUC-KR csEUCKR }
11869 { ISO-2022-JP csISO2022JP }
11870 { ISO-2022-JP-2 csISO2022JP2 }
11871 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11872 csISO13JISC6220jp }
11873 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11874 { IT iso-ir-15 ISO646-IT csISO15Italian }
11875 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11876 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11877 { greek7-old iso-ir-18 csISO18Greek7Old }
11878 { latin-greek iso-ir-19 csISO19LatinGreek }
11879 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11880 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11881 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11882 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11883 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11884 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11885 { INIS iso-ir-49 csISO49INIS }
11886 { INIS-8 iso-ir-50 csISO50INIS8 }
11887 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11888 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11889 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11890 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
11891 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
11892 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
11893 csISO60Norwegian1 }
11894 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
11895 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
11896 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
11897 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
11898 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
11899 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
11900 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
11901 { greek7 iso-ir-88 csISO88Greek7 }
11902 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
11903 { iso-ir-90 csISO90 }
11904 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
11905 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
11906 csISO92JISC62991984b }
11907 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
11908 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
11909 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
11910 csISO95JIS62291984handadd }
11911 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
11912 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
11913 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
11914 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
11915 CP819 csISOLatin1 }
11916 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
11917 { T.61-7bit iso-ir-102 csISO102T617bit }
11918 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
11919 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
11920 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
11921 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
11922 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
11923 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
11924 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
11925 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
11926 arabic csISOLatinArabic }
11927 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
11928 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
11929 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
11930 greek greek8 csISOLatinGreek }
11931 { T.101-G2 iso-ir-128 csISO128T101G2 }
11932 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
11933 csISOLatinHebrew }
11934 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
11935 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
11936 { CSN_369103 iso-ir-139 csISO139CSN369103 }
11937 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
11938 { ISO_6937-2-add iso-ir-142 csISOTextComm }
11939 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
11940 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
11941 csISOLatinCyrillic }
11942 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
11943 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
11944 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
11945 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
11946 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
11947 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
11948 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
11949 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
11950 { ISO_10367-box iso-ir-155 csISO10367Box }
11951 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
11952 { latin-lap lap iso-ir-158 csISO158Lap }
11953 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
11954 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
11955 { us-dk csUSDK }
11956 { dk-us csDKUS }
11957 { JIS_X0201 X0201 csHalfWidthKatakana }
11958 { KSC5636 ISO646-KR csKSC5636 }
11959 { ISO-10646-UCS-2 csUnicode }
11960 { ISO-10646-UCS-4 csUCS4 }
11961 { DEC-MCS dec csDECMCS }
11962 { hp-roman8 roman8 r8 csHPRoman8 }
11963 { macintosh mac csMacintosh }
11964 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
11965 csIBM037 }
11966 { IBM038 EBCDIC-INT cp038 csIBM038 }
11967 { IBM273 CP273 csIBM273 }
11968 { IBM274 EBCDIC-BE CP274 csIBM274 }
11969 { IBM275 EBCDIC-BR cp275 csIBM275 }
11970 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
11971 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
11972 { IBM280 CP280 ebcdic-cp-it csIBM280 }
11973 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
11974 { IBM284 CP284 ebcdic-cp-es csIBM284 }
11975 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
11976 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
11977 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
11978 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
11979 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
11980 { IBM424 cp424 ebcdic-cp-he csIBM424 }
11981 { IBM437 cp437 437 csPC8CodePage437 }
11982 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
11983 { IBM775 cp775 csPC775Baltic }
11984 { IBM850 cp850 850 csPC850Multilingual }
11985 { IBM851 cp851 851 csIBM851 }
11986 { IBM852 cp852 852 csPCp852 }
11987 { IBM855 cp855 855 csIBM855 }
11988 { IBM857 cp857 857 csIBM857 }
11989 { IBM860 cp860 860 csIBM860 }
11990 { IBM861 cp861 861 cp-is csIBM861 }
11991 { IBM862 cp862 862 csPC862LatinHebrew }
11992 { IBM863 cp863 863 csIBM863 }
11993 { IBM864 cp864 csIBM864 }
11994 { IBM865 cp865 865 csIBM865 }
11995 { IBM866 cp866 866 csIBM866 }
11996 { IBM868 CP868 cp-ar csIBM868 }
11997 { IBM869 cp869 869 cp-gr csIBM869 }
11998 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
11999 { IBM871 CP871 ebcdic-cp-is csIBM871 }
12000 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
12001 { IBM891 cp891 csIBM891 }
12002 { IBM903 cp903 csIBM903 }
12003 { IBM904 cp904 904 csIBBM904 }
12004 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
12005 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
12006 { IBM1026 CP1026 csIBM1026 }
12007 { EBCDIC-AT-DE csIBMEBCDICATDE }
12008 { EBCDIC-AT-DE-A csEBCDICATDEA }
12009 { EBCDIC-CA-FR csEBCDICCAFR }
12010 { EBCDIC-DK-NO csEBCDICDKNO }
12011 { EBCDIC-DK-NO-A csEBCDICDKNOA }
12012 { EBCDIC-FI-SE csEBCDICFISE }
12013 { EBCDIC-FI-SE-A csEBCDICFISEA }
12014 { EBCDIC-FR csEBCDICFR }
12015 { EBCDIC-IT csEBCDICIT }
12016 { EBCDIC-PT csEBCDICPT }
12017 { EBCDIC-ES csEBCDICES }
12018 { EBCDIC-ES-A csEBCDICESA }
12019 { EBCDIC-ES-S csEBCDICESS }
12020 { EBCDIC-UK csEBCDICUK }
12021 { EBCDIC-US csEBCDICUS }
12022 { UNKNOWN-8BIT csUnknown8BiT }
12023 { MNEMONIC csMnemonic }
12024 { MNEM csMnem }
12025 { VISCII csVISCII }
12026 { VIQR csVIQR }
12027 { KOI8-R csKOI8R }
12028 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
12029 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
12030 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
12031 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
12032 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
12033 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
12034 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
12035 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
12036 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
12037 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
12038 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
12039 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
12040 { IBM1047 IBM-1047 }
12041 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
12042 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
12043 { UNICODE-1-1 csUnicode11 }
12044 { CESU-8 csCESU-8 }
12045 { BOCU-1 csBOCU-1 }
12046 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
12047 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
12048 l8 }
12049 { ISO-8859-15 ISO_8859-15 Latin-9 }
12050 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
12051 { GBK CP936 MS936 windows-936 }
12052 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012053 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012054 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
12055 EUC-JP }
12056 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
12057 { ISO-10646-UCS-Basic csUnicodeASCII }
12058 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
12059 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
12060 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
12061 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
12062 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
12063 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
12064 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
12065 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
12066 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
12067 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
12068 { Adobe-Standard-Encoding csAdobeStandardEncoding }
12069 { Ventura-US csVenturaUS }
12070 { Ventura-International csVenturaInternational }
12071 { PC8-Danish-Norwegian csPC8DanishNorwegian }
12072 { PC8-Turkish csPC8Turkish }
12073 { IBM-Symbols csIBMSymbols }
12074 { IBM-Thai csIBMThai }
12075 { HP-Legal csHPLegal }
12076 { HP-Pi-font csHPPiFont }
12077 { HP-Math8 csHPMath8 }
12078 { Adobe-Symbol-Encoding csHPPSMath }
12079 { HP-DeskTop csHPDesktop }
12080 { Ventura-Math csVenturaMath }
12081 { Microsoft-Publishing csMicrosoftPublishing }
12082 { Windows-31J csWindows31J }
12083 { GB2312 csGB2312 }
12084 { Big5 csBig5 }
12085}
12086
12087proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012088 global encoding_aliases tcl_encoding_cache
12089 if {[info exists tcl_encoding_cache($enc)]} {
12090 return $tcl_encoding_cache($enc)
12091 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012092 set names [encoding names]
12093 set lcnames [string tolower $names]
12094 set enc [string tolower $enc]
12095 set i [lsearch -exact $lcnames $enc]
12096 if {$i < 0} {
12097 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012098 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012099 set i [lsearch -exact $lcnames $encx]
12100 }
12101 }
12102 if {$i < 0} {
12103 foreach l $encoding_aliases {
12104 set ll [string tolower $l]
12105 if {[lsearch -exact $ll $enc] < 0} continue
12106 # look through the aliases for one that tcl knows about
12107 foreach e $ll {
12108 set i [lsearch -exact $lcnames $e]
12109 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012110 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012111 set i [lsearch -exact $lcnames $ex]
12112 }
12113 }
12114 if {$i >= 0} break
12115 }
12116 break
12117 }
12118 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012119 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012120 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012121 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012122 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012123 set tcl_encoding_cache($enc) $tclenc
12124 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012125}
12126
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012127proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012128 global path_attr_cache
12129 if {[info exists path_attr_cache($attr,$path)]} {
12130 set r $path_attr_cache($attr,$path)
12131 } else {
12132 set r "unspecified"
12133 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020012134 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012135 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012136 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012137 }
12138 if {$r eq "unspecified"} {
12139 return $default
12140 }
12141 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012142}
12143
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012144proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012145 global path_attr_cache
12146 set newlist {}
12147 foreach path $pathlist {
12148 if {![info exists path_attr_cache($attr,$path)]} {
12149 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012150 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012151 }
12152 set lim 1000
12153 if {[tk windowingsystem] == "win32"} {
12154 # windows has a 32k limit on the arguments to a command...
12155 set lim 30
12156 }
12157 while {$newlist ne {}} {
12158 set head [lrange $newlist 0 [expr {$lim - 1}]]
12159 set newlist [lrange $newlist $lim end]
12160 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
12161 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020012162 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012163 if {[string index $path 0] eq "\""} {
12164 set path [encoding convertfrom [lindex $path 0]]
12165 }
12166 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012167 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012168 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012169 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012170 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012171}
12172
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012173proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012174 global gui_encoding perfile_attrs
12175 set tcl_enc $gui_encoding
12176 if {$path ne {} && $perfile_attrs} {
12177 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
12178 if {$enc2 ne {}} {
12179 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012180 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012181 }
12182 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012183}
12184
Alex Henrieef87a482015-05-11 13:26:41 -060012185## For msgcat loading, first locate the installation location.
12186if { [info exists ::env(GITK_MSGSDIR)] } {
12187 ## Msgsdir was manually set in the environment.
12188 set gitk_msgsdir $::env(GITK_MSGSDIR)
12189} else {
12190 ## Let's guess the prefix from argv0.
12191 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
12192 set gitk_libdir [file join $gitk_prefix share gitk lib]
12193 set gitk_msgsdir [file join $gitk_libdir msgs]
12194 unset gitk_prefix
12195}
12196
12197## Internationalization (i18n) through msgcat and gettext. See
12198## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
12199package require msgcat
12200namespace import ::msgcat::mc
12201## And eventually load the actual message catalog
12202::msgcat::mcload $gitk_msgsdir
12203
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012204# First check that Tcl/Tk is recent enough
12205if {[catch {package require Tk 8.4} err]} {
Alex Henrieef87a482015-05-11 13:26:41 -060012206 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
12207 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012208 exit 1
12209}
12210
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060012211# on OSX bring the current Wish process window to front
12212if {[tk windowingsystem] eq "aqua"} {
12213 exec osascript -e [format {
12214 tell application "System Events"
12215 set frontmost of processes whose unix id is %d to true
12216 end tell
12217 } [pid] ]
12218}
12219
Aske Olsson0ae10352012-05-10 12:13:43 +020012220# Unset GIT_TRACE var if set
12221if { [info exists ::env(GIT_TRACE)] } {
12222 unset ::env(GIT_TRACE)
12223}
12224
Paul Mackerras1d10f362005-05-15 12:55:47 +000012225# defaults...
Chris Packhame203d1d2014-11-02 21:37:50 +130012226set wrcomcmd "git diff-tree --stdin -p --pretty=email"
Junio C Hamano671bc152005-11-27 16:12:51 -080012227
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012228set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080012229catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110012230 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080012231}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030012232catch {
12233 set gitencoding [exec git config --get i18n.logoutputencoding]
12234}
Junio C Hamano671bc152005-11-27 16:12:51 -080012235if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012236 set gitencoding "utf-8"
12237}
12238set tclencoding [tcl_encoding $gitencoding]
12239if {$tclencoding == {}} {
12240 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080012241}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012242
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012243set gui_encoding [encoding system]
12244catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012245 set enc [exec git config --get gui.encoding]
12246 if {$enc ne {}} {
12247 set tclenc [tcl_encoding $enc]
12248 if {$tclenc ne {}} {
12249 set gui_encoding $tclenc
12250 } else {
12251 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
12252 }
12253 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012254}
12255
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020012256set log_showroot true
12257catch {
12258 set log_showroot [exec git config --bool --get log.showroot]
12259}
12260
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012261if {[tk windowingsystem] eq "aqua"} {
12262 set mainfont {{Lucida Grande} 9}
12263 set textfont {Monaco 9}
12264 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060012265} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
12266 # fontconfig!
12267 set mainfont {sans 9}
12268 set textfont {monospace 9}
12269 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012270} else {
12271 set mainfont {Helvetica 9}
12272 set textfont {Courier 9}
12273 set uifont {Helvetica 9 bold}
12274}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040012275set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040012276set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100012277set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100012278set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110012279set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110012280set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100012281set uparrowlen 5
12282set downarrowlen 5
12283set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100012284set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040012285set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100012286set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020012287set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100012288set maxrefs 20
Max Kirillovbde4a0f2014-06-24 08:19:44 +030012289set visiblerefs {"master"}
Paul Mackerras322a8cc2006-10-15 18:03:46 +100012290set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012291set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100012292set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020012293set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050012294set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110012295set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012296set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012297set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000012298
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012299if {[tk windowingsystem] eq "aqua"} {
12300 set extdifftool "opendiff"
12301} else {
12302 set extdifftool "meld"
12303}
Thomas Arcila314f5de2008-03-24 12:55:36 +010012304
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012305set colors {"#00ff00" red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012306if {[tk windowingsystem] eq "win32"} {
12307 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012308 set uifgcolor SystemButtonText
12309 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012310 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012311 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012312 set selectbgcolor SystemHighlight
12313} else {
12314 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012315 set uifgcolor black
12316 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012317 set bgcolor white
12318 set fgcolor black
12319 set selectbgcolor gray85
12320}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100012321set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020012322set diffcontext 3
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012323set mergecolors {red blue "#00ff00" purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010012324set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020012325set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110012326set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000012327
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012328set headbgcolor "#00ff00"
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012329set headfgcolor black
12330set headoutlinecolor black
12331set remotebgcolor #ffddaa
12332set tagbgcolor yellow
12333set tagfgcolor black
12334set tagoutlinecolor black
12335set reflinecolor black
12336set filesepbgcolor #aaaaaa
12337set filesepfgcolor black
12338set linehoverbgcolor #ffff80
12339set linehoverfgcolor black
12340set linehoveroutlinecolor black
12341set mainheadcirclecolor yellow
12342set workingfilescirclecolor red
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012343set indexcirclecolor "#00ff00"
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012344set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012345set linkfgcolor blue
12346set circleoutlinecolor $fgcolor
12347set foundbgcolor yellow
12348set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012349
Paul Mackerrasd277e892008-09-21 18:11:37 -050012350# button for popping up context menus
12351if {[tk windowingsystem] eq "aqua"} {
12352 set ctxbut <Button-2>
12353} else {
12354 set ctxbut <Button-3>
12355}
12356
Astril Hayato8f863392014-01-21 19:10:16 +000012357catch {
12358 # follow the XDG base directory specification by default. See
12359 # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
12360 if {[info exists env(XDG_CONFIG_HOME)] && $env(XDG_CONFIG_HOME) ne ""} {
12361 # XDG_CONFIG_HOME environment variable is set
12362 set config_file [file join $env(XDG_CONFIG_HOME) git gitk]
12363 set config_file_tmp [file join $env(XDG_CONFIG_HOME) git gitk-tmp]
12364 } else {
12365 # default XDG_CONFIG_HOME
12366 set config_file "~/.config/git/gitk"
12367 set config_file_tmp "~/.config/git/gitk-tmp"
12368 }
12369 if {![file exists $config_file]} {
12370 # for backward compatibility use the old config file if it exists
12371 if {[file exists "~/.gitk"]} {
12372 set config_file "~/.gitk"
12373 set config_file_tmp "~/.gitk-tmp"
12374 } elseif {![file exists [file dirname $config_file]]} {
12375 file mkdir [file dirname $config_file]
12376 }
12377 }
12378 source $config_file
12379}
Max Kirilloveaf7e832015-03-04 05:58:18 +020012380config_check_tmp_exists 50
Paul Mackerras1d10f362005-05-15 12:55:47 +000012381
Max Kirillov9fabefb2014-09-14 23:35:57 +030012382set config_variables {
12383 mainfont textfont uifont tabstop findmergefiles maxgraphpct maxwidth
12384 cmitmode wrapcomment autoselect autosellen showneartags maxrefs visiblerefs
12385 hideremotes showlocalchanges datetimeformat limitdiffs uicolor want_ttk
12386 bgcolor fgcolor uifgcolor uifgdisabledcolor colors diffcolors mergecolors
12387 markbgcolor diffcontext selectbgcolor foundbgcolor currentsearchhitbgcolor
12388 extdifftool perfile_attrs headbgcolor headfgcolor headoutlinecolor
12389 remotebgcolor tagbgcolor tagfgcolor tagoutlinecolor reflinecolor
12390 filesepbgcolor filesepfgcolor linehoverbgcolor linehoverfgcolor
12391 linehoveroutlinecolor mainheadcirclecolor workingfilescirclecolor
12392 indexcirclecolor circlecolors linkfgcolor circleoutlinecolor
12393}
Max Kirillov995f7922015-03-04 05:58:16 +020012394foreach var $config_variables {
12395 config_init_trace $var
12396 trace add variable $var write config_variable_change_cb
12397}
Max Kirillov9fabefb2014-09-14 23:35:57 +030012398
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100012399parsefont mainfont $mainfont
12400eval font create mainfont [fontflags mainfont]
12401eval font create mainfontbold [fontflags mainfont 1]
12402
12403parsefont textfont $textfont
12404eval font create textfont [fontflags textfont]
12405eval font create textfontbold [fontflags textfont 1]
12406
12407parsefont uifont $uifont
12408eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000012409
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110012410setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020012411
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110012412setoptions
12413
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012414# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040012415if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012416 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020012417 exit 1
12418}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012419
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012420set selecthead {}
12421set selectheadid {}
12422
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012423set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012424set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012425set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010012426set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012427foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010012428 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100012429 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012430 "--" {
12431 set cmdline_files [lrange $argv [expr {$i + 1}] end]
12432 break
12433 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012434 "--select-commit=*" {
12435 set selecthead [string range $arg 16 end]
12436 }
Yann Dirson2d480852008-02-21 21:23:31 +010012437 "--argscmd=*" {
12438 set revtreeargscmd [string range $arg 10 end]
12439 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012440 default {
12441 lappend revtreeargs $arg
12442 }
12443 }
12444 incr i
12445}
12446
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012447if {$selecthead eq "HEAD"} {
12448 set selecthead {}
12449}
12450
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012451if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012452 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012453 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030012454 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012455 set cmdline_files [split $f "\n"]
12456 set n [llength $cmdline_files]
12457 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012458 # Unfortunately git rev-parse doesn't produce an error when
12459 # something is both a revision and a filename. To be consistent
12460 # with git log and git rev-list, check revtreeargs for filenames.
12461 foreach arg $revtreeargs {
12462 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012463 show_error {} . [mc "Ambiguous argument '%s': both revision\
12464 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012465 exit 1
12466 }
12467 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012468 } err]} {
12469 # unfortunately we get both stdout and stderr in $err,
12470 # so look for "fatal:".
12471 set i [string first "fatal:" $err]
12472 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070012473 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012474 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010012475 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012476 exit 1
12477 }
12478}
12479
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012480set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012481set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012482set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012483
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012484set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012485if {![info exists have_ttk]} {
12486 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012487}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012488set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012489set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012490
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +010012491if {$use_ttk} {
12492 setttkstyle
12493}
12494
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012495regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012496
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012497set show_notes {}
12498if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12499 set show_notes "--show-notes"
12500}
12501
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012502set appname "gitk"
12503
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012504set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012505set history {}
12506set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012507set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012508set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012509set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012510set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012511set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012512set boldids {}
12513set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012514set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012515set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012516set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012517set need_redisplay 0
12518set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012519set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012520
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012521set nextviewnum 1
12522set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012523set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012524set selectedhlview [mc "None"]
12525set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012526set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012527set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012528set viewperm(0) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012529set viewchanged(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012530set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012531set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012532
Paul Mackerras94b4a692008-05-20 20:51:06 +100012533set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012534set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012535set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012536set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012537set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012538set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012539set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012540set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012541set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012542set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012543if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012544 set cdup [exec git rev-parse --show-cdup]
12545}
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -040012546set worktree [exec git rev-parse --show-toplevel]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012547setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012548makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012549catch {
12550 image create photo gitlogo -width 16 -height 16
12551
12552 image create photo gitlogominus -width 4 -height 2
12553 gitlogominus put #C00000 -to 0 0 4 2
12554 gitlogo copy gitlogominus -to 1 5
12555 gitlogo copy gitlogominus -to 6 5
12556 gitlogo copy gitlogominus -to 11 5
12557 image delete gitlogominus
12558
12559 image create photo gitlogoplus -width 4 -height 4
12560 gitlogoplus put #008000 -to 1 0 3 4
12561 gitlogoplus put #008000 -to 0 1 4 3
12562 gitlogo copy gitlogoplus -to 1 9
12563 gitlogo copy gitlogoplus -to 6 9
12564 gitlogo copy gitlogoplus -to 11 9
12565 image delete gitlogoplus
12566
Stephen Boydd38d7d42009-03-19 01:54:18 -070012567 image create photo gitlogo32 -width 32 -height 32
12568 gitlogo32 copy gitlogo -zoom 2 2
12569
12570 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012571}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012572# wait for the window to become visible
12573tkwait visibility .
Marc Branchaud9922c5a2015-04-07 11:51:51 -040012574set_window_title
Pat Thoyts478afad2009-04-15 17:14:03 +010012575update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012576readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012577
Yann Dirson2d480852008-02-21 21:23:31 +010012578if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012579 # create a view for the files/dirs specified on the command line
12580 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012581 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012582 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012583 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012584 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012585 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012586 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012587 set viewperm(1) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012588 set viewchanged(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012589 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012590 addviewmenu 1
Beat Bolli28de5682015-09-30 21:50:11 +020012591 .bar.view entryconf [mca "&Edit view..."] -state normal
12592 .bar.view entryconf [mca "&Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012593}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012594
12595if {[info exists permviews]} {
12596 foreach v $permviews {
12597 set n $nextviewnum
12598 incr nextviewnum
12599 set viewname($n) [lindex $v 0]
12600 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012601 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010012602 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012603 set viewperm($n) 1
Max Kirillov995f7922015-03-04 05:58:16 +020012604 set viewchanged($n) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012605 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012606 }
12607}
Johannes Sixte4df5192008-12-18 08:30:49 +010012608
12609if {[tk windowingsystem] eq "win32"} {
12610 focus -force .
12611}
12612
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012613getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012614
12615# Local variables:
12616# mode: tcl
12617# indent-tabs-mode: t
12618# tab-width: 8
12619# End: