blob: 805a1c703040d4b08fc0d6992c92e2a044c5ddc5 [file] [log] [blame]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
Paul Mackerras9e026d32005-09-27 10:29:41 +10003exec wish "$0" -- "$@"
Paul Mackerras1db95b02005-05-09 04:08:39 +00004
Paul Mackerras6c626a02014-01-21 22:02:27 +11005# Copyright © 2005-2014 Paul Mackerras. All rights reserved.
Paul Mackerras1db95b02005-05-09 04:08:39 +00006# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
Pat Thoytsd93f1712009-04-17 01:24:35 +010010package require Tk
11
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012proc hasworktree {} {
13 return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
14 [exec git rev-parse --is-inside-git-dir] == "false"}]
15}
16
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010017proc reponame {} {
18 global gitdir
19 set n [file normalize $gitdir]
20 if {[string match "*/.git" $n]} {
21 set n [string range $n 0 end-5]
22 }
23 return [file tail $n]
24}
25
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000026proc gitworktree {} {
27 variable _gitworktree
28 if {[info exists _gitworktree]} {
29 return $_gitworktree
30 }
31 # v1.7.0 introduced --show-toplevel to return the canonical work-tree
32 if {[catch {set _gitworktree [exec git rev-parse --show-toplevel]}]} {
33 # try to set work tree from environment, core.worktree or use
34 # cdup to obtain a relative path to the top of the worktree. If
35 # run from the top, the ./ prefix ensures normalize expands pwd.
36 if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
37 catch {set _gitworktree [exec git config --get core.worktree]}
38 if {$_gitworktree eq ""} {
39 set _gitworktree [file normalize ./[exec git rev-parse --show-cdup]]
40 }
41 }
42 }
43 return $_gitworktree
44}
45
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100046# A simple scheduler for compute-intensive stuff.
47# The aim is to make sure that event handlers for GUI actions can
48# run at least every 50-100 ms. Unfortunately fileevent handlers are
49# run before X event handlers, so reading from a fast source can
50# make the GUI completely unresponsive.
51proc run args {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040052 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100053
54 set script $args
55 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040056 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100057 after idle dorunq
58 }
59 lappend runq [list {} $script]
60 set isonrunq($script) 1
61}
62
63proc filerun {fd script} {
64 fileevent $fd readable [list filereadable $fd $script]
65}
66
67proc filereadable {fd script} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040068 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100069
70 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040071 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 after idle dorunq
73 }
74 lappend runq [list $fd $script]
75}
76
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110077proc nukefile {fd} {
78 global runq
79
80 for {set i 0} {$i < [llength $runq]} {} {
81 if {[lindex $runq $i 0] eq $fd} {
82 set runq [lreplace $runq $i $i]
83 } else {
84 incr i
85 }
86 }
87}
88
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100089proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040090 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100091
92 set tstart [clock clicks -milliseconds]
93 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110094 while {[llength $runq] > 0} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100095 set fd [lindex $runq 0 0]
96 set script [lindex $runq 0 1]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040097 set currunq [lindex $runq 0]
98 set runq [lrange $runq 1 end]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100099 set repeat [eval $script]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +0400100 unset currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000101 set t1 [clock clicks -milliseconds]
102 set t [expr {$t1 - $t0}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000103 if {$repeat ne {} && $repeat} {
104 if {$fd eq {} || $repeat == 2} {
105 # script returns 1 if it wants to be readded
106 # file readers return 2 if they could do more straight away
107 lappend runq [list $fd $script]
108 } else {
109 fileevent $fd readable [list filereadable $fd $script]
110 }
111 } elseif {$fd eq {}} {
112 unset isonrunq($script)
113 }
114 set t0 $t1
115 if {$t1 - $tstart >= 80} break
116 }
117 if {$runq ne {}} {
118 after idle dorunq
119 }
120}
121
Alexander Gavrilove439e092008-07-13 16:40:47 +0400122proc reg_instance {fd} {
123 global commfd leftover loginstance
124
125 set i [incr loginstance]
126 set commfd($i) $fd
127 set leftover($i) {}
128 return $i
129}
130
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000131proc unmerged_files {files} {
132 global nr_unmerged
133
134 # find the list of unmerged files
135 set mlist {}
136 set nr_unmerged 0
137 if {[catch {
138 set fd [open "| git ls-files -u" r]
139 } err]} {
140 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
141 exit 1
142 }
143 while {[gets $fd line] >= 0} {
144 set i [string first "\t" $line]
145 if {$i < 0} continue
146 set fname [string range $line [expr {$i+1}] end]
147 if {[lsearch -exact $mlist $fname] >= 0} continue
148 incr nr_unmerged
149 if {$files eq {} || [path_filter $files $fname]} {
150 lappend mlist $fname
151 }
152 }
153 catch {close $fd}
154 return $mlist
155}
156
157proc parseviewargs {n arglist} {
Christian Couderc2f2dab2009-12-12 05:52:39 +0100158 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
Thomas Rast9403bd02013-11-16 18:37:43 +0100159 global vinlinediff
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200160 global worddiff git_version
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000161
162 set vdatemode($n) 0
163 set vmergeonly($n) 0
Thomas Rast9403bd02013-11-16 18:37:43 +0100164 set vinlinediff($n) 0
Paul Mackerrasee66e082008-05-09 10:14:07 +1000165 set glflags {}
166 set diffargs {}
167 set nextisval 0
168 set revargs {}
169 set origargs $arglist
170 set allknown 1
171 set filtered 0
172 set i -1
173 foreach arg $arglist {
174 incr i
175 if {$nextisval} {
176 lappend glflags $arg
177 set nextisval 0
178 continue
179 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000180 switch -glob -- $arg {
181 "-d" -
182 "--date-order" {
183 set vdatemode($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000184 # remove from origargs in case we hit an unknown option
185 set origargs [lreplace $origargs $i $i]
186 incr i -1
187 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000188 "-[puabwcrRBMC]" -
189 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
190 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
191 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
192 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
193 "--ignore-space-change" - "-U*" - "--unified=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100194 # These request or affect diff output, which we don't want.
195 # Some could be used to set our defaults for diff display.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000196 lappend diffargs $arg
197 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000198 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200199 "--name-only" - "--name-status" - "--color" -
Paul Mackerrasee66e082008-05-09 10:14:07 +1000200 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
201 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
202 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
203 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
204 "--objects" - "--objects-edge" - "--reverse" {
Paul Mackerras29582282008-11-18 19:44:20 +1100205 # These cause our parsing of git log's output to fail, or else
206 # they're options we want to set ourselves, so ignore them.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000207 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200208 "--color-words*" - "--word-diff=color" {
209 # These trigger a word diff in the console interface,
210 # so help the user by enabling our own support
211 if {[package vcompare $git_version "1.7.2"] >= 0} {
212 set worddiff [mc "Color words"]
213 }
214 }
215 "--word-diff*" {
216 if {[package vcompare $git_version "1.7.2"] >= 0} {
217 set worddiff [mc "Markup words"]
218 }
219 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000220 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
221 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
222 "--full-history" - "--dense" - "--sparse" -
223 "--follow" - "--left-right" - "--encoding=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100224 # These are harmless, and some are even useful
Paul Mackerrasee66e082008-05-09 10:14:07 +1000225 lappend glflags $arg
226 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000227 "--diff-filter=*" - "--no-merges" - "--unpacked" -
228 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
229 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
230 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
231 "--remove-empty" - "--first-parent" - "--cherry-pick" -
Thomas Rast71846c52013-11-16 18:37:40 +0100232 "-S*" - "-G*" - "--pickaxe-all" - "--pickaxe-regex" -
Dirk Suesserottf687aaa2009-05-21 15:35:40 +0200233 "--simplify-by-decoration" {
Paul Mackerras29582282008-11-18 19:44:20 +1100234 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000235 set filtered 1
236 lappend glflags $arg
237 }
Thomas Rastce2c58c2013-11-16 18:37:44 +0100238 "-L*" {
239 # Line-log with 'stuck' argument (unstuck form is
240 # not supported)
241 set filtered 1
242 set vinlinediff($n) 1
243 set allknown 0
244 lappend glflags $arg
245 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000246 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100247 # This appears to be the only one that has a value as a
248 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000249 set filtered 1
250 set nextisval 1
251 lappend glflags $arg
252 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100253 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000254 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000255 }
256 "--merge" {
257 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000258 # git rev-parse doesn't understand --merge
259 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000260 }
Christian Couderc2f2dab2009-12-12 05:52:39 +0100261 "--no-replace-objects" {
262 set env(GIT_NO_REPLACE_OBJECTS) "1"
263 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000264 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100265 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000266 if {[string is digit -strict [string range $arg 1 end]]} {
267 set filtered 1
268 } else {
269 # a flag argument that we don't recognize;
270 # that means we can't optimize
271 set allknown 0
272 }
273 lappend glflags $arg
274 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000275 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100276 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000277 if {[string match "*...*" $arg]} {
278 lappend revargs --gitk-symmetric-diff-marker
279 }
280 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000281 }
282 }
283 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000284 set vdflags($n) $diffargs
285 set vflags($n) $glflags
286 set vrevs($n) $revargs
287 set vfiltered($n) $filtered
288 set vorigargs($n) $origargs
289 return $allknown
290}
291
292proc parseviewrevs {view revs} {
293 global vposids vnegids
294
295 if {$revs eq {}} {
296 set revs HEAD
Max Kirillov4d5e1b12014-09-09 10:29:16 +0300297 } elseif {[lsearch -exact $revs --all] >= 0} {
298 lappend revs HEAD
Paul Mackerrasee66e082008-05-09 10:14:07 +1000299 }
300 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
301 # we get stdout followed by stderr in $err
302 # for an unknown rev, git rev-parse echoes it and then errors out
303 set errlines [split $err "\n"]
304 set badrev {}
305 for {set l 0} {$l < [llength $errlines]} {incr l} {
306 set line [lindex $errlines $l]
307 if {!([string length $line] == 40 && [string is xdigit $line])} {
308 if {[string match "fatal:*" $line]} {
309 if {[string match "fatal: ambiguous argument*" $line]
310 && $badrev ne {}} {
311 if {[llength $badrev] == 1} {
312 set err "unknown revision $badrev"
313 } else {
314 set err "unknown revisions: [join $badrev ", "]"
315 }
316 } else {
317 set err [join [lrange $errlines $l end] "\n"]
318 }
319 break
320 }
321 lappend badrev $line
322 }
Pat Thoytsd93f1712009-04-17 01:24:35 +0100323 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200324 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000325 return {}
326 }
327 set ret {}
328 set pos {}
329 set neg {}
330 set sdm 0
331 foreach id [split $ids "\n"] {
332 if {$id eq "--gitk-symmetric-diff-marker"} {
333 set sdm 4
334 } elseif {[string match "^*" $id]} {
335 if {$sdm != 1} {
336 lappend ret $id
337 if {$sdm == 3} {
338 set sdm 0
339 }
340 }
341 lappend neg [string range $id 1 end]
342 } else {
343 if {$sdm != 2} {
344 lappend ret $id
345 } else {
Thomas Rast2b1fbf92009-08-05 23:15:36 +0200346 lset ret end $id...[lindex $ret end]
Paul Mackerrasee66e082008-05-09 10:14:07 +1000347 }
348 lappend pos $id
349 }
350 incr sdm -1
351 }
352 set vposids($view) $pos
353 set vnegids($view) $neg
354 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000355}
356
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100357# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000358proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000359 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400360 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000361 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100362 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400363 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100364 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000365 global vcanopt vflags vrevs vorigargs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400366 global show_notes
Paul Mackerras38ad0912005-12-01 22:42:46 +1100367
368 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000369 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000370 # these are set this way for the error exits
371 set viewcomplete($view) 1
372 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100373 varcinit $view
374
Yann Dirson2d480852008-02-21 21:23:31 +0100375 set args $viewargs($view)
376 if {$viewargscmd($view) ne {}} {
377 if {[catch {
378 set str [exec sh -c $viewargscmd($view)]
379 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200380 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000381 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100382 }
383 set args [concat $args [split $str "\n"]]
384 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000385 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000386
387 set files $viewfiles($view)
388 if {$vmergeonly($view)} {
389 set files [unmerged_files $files]
390 if {$files eq {}} {
391 global nr_unmerged
392 if {$nr_unmerged == 0} {
393 error_popup [mc "No files selected: --merge specified but\
394 no files are unmerged."]
395 } else {
396 error_popup [mc "No files selected: --merge specified but\
397 no unmerged files are within file limit."]
398 }
399 return 0
400 }
401 }
402 set vfilelimit($view) $files
403
Paul Mackerrasee66e082008-05-09 10:14:07 +1000404 if {$vcanopt($view)} {
405 set revs [parseviewrevs $view $vrevs($view)]
406 if {$revs eq {}} {
407 return 0
408 }
409 set args [concat $vflags($view) $revs]
410 } else {
411 set args $vorigargs($view)
412 }
413
Paul Mackerras418c4c72006-02-07 09:10:18 +1100414 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400415 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
416 --parents --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100417 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100418 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000419 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100420 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400421 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100422 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100423 set viewmainheadid($view) $mainheadid
424 set viewmainheadid_orig($view) $mainheadid
425 if {$files ne {} && $mainheadid ne {}} {
426 get_viewmainhead $view
427 }
428 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
429 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000430 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400431 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100432 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000433 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100434 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100435 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100436 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000437 set viewcomplete($view) 0
438 set viewactive($view) 1
439 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100440}
441
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400442proc stop_instance {inst} {
443 global commfd leftover
444
445 set fd $commfd($inst)
446 catch {
447 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400448
449 if {$::tcl_platform(platform) eq {windows}} {
Sebastian Schuberth7b68b0ee2014-10-23 21:30:54 +0200450 exec taskkill /pid $pid
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400451 } else {
452 exec kill $pid
453 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400454 }
455 catch {close $fd}
456 nukefile $fd
457 unset commfd($inst)
458 unset leftover($inst)
459}
460
461proc stop_backends {} {
462 global commfd
463
464 foreach inst [array names commfd] {
465 stop_instance $inst
466 }
467}
468
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100469proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400470 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000471
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100472 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400473 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000474 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100475 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000476}
477
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400478proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400479 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400480
481 if {$selid ne {}} {
482 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400483 } elseif {$selectheadid ne {}} {
484 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400485 } else {
486 set pending_select $mainheadid
487 }
488}
489
490proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000491 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100492
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000493 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000494 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400495 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000496 show_status [mc "Reading commits..."]
497 set need_redisplay 1
498 } else {
499 show_status [mc "No commits selected"]
500 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000501}
502
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100503proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000504 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400505 global viewactive viewcomplete tclencoding
506 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100507 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400508 global hasworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000509 global varcid vposids vnegids vflags vrevs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400510 global show_notes
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100511
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400512 set hasworktree [hasworktree]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100513 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100514 set view $curview
515 if {$mainheadid ne $viewmainheadid_orig($view)} {
516 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100517 dohidelocalchanges
518 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100519 set viewmainheadid($view) $mainheadid
520 set viewmainheadid_orig($view) $mainheadid
521 if {$vfilelimit($view) ne {}} {
522 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100523 }
524 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100525 if {$showlocalchanges} {
526 doshowlocalchanges
527 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000528 if {$vcanopt($view)} {
529 set oldpos $vposids($view)
530 set oldneg $vnegids($view)
531 set revs [parseviewrevs $view $vrevs($view)]
532 if {$revs eq {}} {
533 return
534 }
535 # note: getting the delta when negative refs change is hard,
536 # and could require multiple git log invocations, so in that
537 # case we ask git log for all the commits (not just the delta)
538 if {$oldneg eq $vnegids($view)} {
539 set newrevs {}
540 set npos 0
541 # take out positive refs that we asked for before or
542 # that we have already seen
543 foreach rev $revs {
544 if {[string length $rev] == 40} {
545 if {[lsearch -exact $oldpos $rev] < 0
546 && ![info exists varcid($view,$rev)]} {
547 lappend newrevs $rev
548 incr npos
549 }
550 } else {
551 lappend $newrevs $rev
552 }
553 }
554 if {$npos == 0} return
555 set revs $newrevs
556 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
557 }
558 set args [concat $vflags($view) $revs --not $oldpos]
559 } else {
560 set args $vorigargs($view)
561 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100562 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400563 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
564 --parents --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100565 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200566 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000567 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100568 }
569 if {$viewactive($view) == 0} {
570 set startmsecs [clock clicks -milliseconds]
571 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400572 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100573 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100574 fconfigure $fd -blocking 0 -translation lf -eofchar {}
575 if {$tclencoding != {}} {
576 fconfigure $fd -encoding $tclencoding
577 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100578 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100579 incr viewactive($view)
580 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400581 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200582 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100583 if {$showneartags} {
584 getallcommits
585 }
586}
587
588proc reloadcommits {} {
589 global curview viewcomplete selectedline currentid thickerline
590 global showneartags treediffs commitinterest cached_commitrow
Paul Mackerras6df74032008-05-11 22:13:02 +1000591 global targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100592
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400593 set selid {}
594 if {$selectedline ne {}} {
595 set selid $currentid
596 }
597
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100598 if {!$viewcomplete($curview)} {
599 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100600 }
601 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000602 set selectedline {}
Paul 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
Paul Mackerras009409f2015-05-02 20:53:36 +1000612 unset -nocomplain commitinterest
613 unset -nocomplain cached_commitrow
614 unset -nocomplain targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100615 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400616 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100617 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100618}
619
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000620# This makes a string representation of a positive integer which
621# sorts as a string in numerical order
622proc strrep {n} {
623 if {$n < 16} {
624 return [format "%x" $n]
625 } elseif {$n < 256} {
626 return [format "x%.2x" $n]
627 } elseif {$n < 65536} {
628 return [format "y%.4x" $n]
629 }
630 return [format "z%.8x" $n]
631}
632
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100633# Procedures used in reordering commits from git log (without
634# --topo-order) into the order for display.
635
636proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100637 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
638 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100639
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100640 set varcstart($view) {{}}
641 set vupptr($view) {0}
642 set vdownptr($view) {0}
643 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100644 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100645 set varctok($view) {{}}
646 set varcrow($view) {{}}
647 set vtokmod($view) {}
648 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100649 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100650 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100651 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100652}
653
654proc resetvarcs {view} {
655 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100656 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100657
658 foreach vid [array names varcid $view,*] {
659 unset varcid($vid)
660 unset children($vid)
661 unset parents($vid)
662 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100663 foreach vid [array names vshortids $view,*] {
664 unset vshortids($vid)
665 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100666 # some commits might have children but haven't been seen yet
667 foreach vid [array names children $view,*] {
668 unset children($vid)
669 }
670 foreach va [array names varccommits $view,*] {
671 unset varccommits($va)
672 }
673 foreach vd [array names vseedcount $view,*] {
674 unset vseedcount($vd)
675 }
Paul Mackerras009409f2015-05-02 20:53:36 +1000676 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100677}
678
Paul Mackerras468bcae2008-03-03 10:19:35 +1100679# returns a list of the commits with no children
680proc seeds {v} {
681 global vdownptr vleftptr varcstart
682
683 set ret {}
684 set a [lindex $vdownptr($v) 0]
685 while {$a != 0} {
686 lappend ret [lindex $varcstart($v) $a]
687 set a [lindex $vleftptr($v) $a]
688 }
689 return $ret
690}
691
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100692proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000693 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100694 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
695 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100696
697 set a [llength $varctok($view)]
698 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000699 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100700 if {![info exists commitinfo($id)]} {
701 parsecommit $id $commitdata($id) 1
702 }
Anders Kaseorgf5974d92011-01-19 14:47:25 -0500703 set cdate [lindex [lindex $commitinfo($id) 4] 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100704 if {![string is integer -strict $cdate]} {
705 set cdate 0
706 }
707 if {![info exists vseedcount($view,$cdate)]} {
708 set vseedcount($view,$cdate) -1
709 }
710 set c [incr vseedcount($view,$cdate)]
711 set cdate [expr {$cdate ^ 0xffffffff}]
712 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100713 } else {
714 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100715 }
716 set ka 0
717 if {[llength $children($vid)] > 0} {
718 set kid [lindex $children($vid) end]
719 set k $varcid($view,$kid)
720 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
721 set ki $kid
722 set ka $k
723 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100724 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100725 }
726 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100727 set i [lsearch -exact $parents($view,$ki) $id]
728 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100729 append tok [strrep $j]
730 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100731 set c [lindex $vlastins($view) $ka]
732 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
733 set c $ka
734 set b [lindex $vdownptr($view) $ka]
735 } else {
736 set b [lindex $vleftptr($view) $c]
737 }
738 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
739 set c $b
740 set b [lindex $vleftptr($view) $c]
741 }
742 if {$c == $ka} {
743 lset vdownptr($view) $ka $a
744 lappend vbackptr($view) 0
745 } else {
746 lset vleftptr($view) $c $a
747 lappend vbackptr($view) $c
748 }
749 lset vlastins($view) $ka $a
750 lappend vupptr($view) $ka
751 lappend vleftptr($view) $b
752 if {$b != 0} {
753 lset vbackptr($view) $b $a
754 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100755 lappend varctok($view) $tok
756 lappend varcstart($view) $id
757 lappend vdownptr($view) 0
758 lappend varcrow($view) {}
759 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100760 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100761 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100762 return $a
763}
764
765proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100766 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100767 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100768
769 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100770 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100771 set ac $varccommits($v,$oa)
772 set i [lsearch -exact $varccommits($v,$oa) $p]
773 if {$i <= 0} return
774 set na [llength $varctok($v)]
775 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100776 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100777 lappend varctok($v) $tok
778 lappend varcrow($v) {}
779 lappend varcix($v) {}
780 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
781 set varccommits($v,$na) [lrange $ac $i end]
782 lappend varcstart($v) $p
783 foreach id $varccommits($v,$na) {
784 set varcid($v,$id) $na
785 }
786 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100787 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100788 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100789 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100790 lappend vupptr($v) $oa
791 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100792 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100793 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
794 lset vupptr($v) $b $na
795 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100796 if {[string compare $otok $vtokmod($v)] <= 0} {
797 modify_arc $v $oa
798 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100799}
800
801proc renumbervarc {a v} {
802 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000803 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100804
805 set t1 [clock clicks -milliseconds]
806 set todo {}
807 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100808 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100809 set ntot 0
810 while {$a != 0} {
811 if {[info exists isrelated($a)]} {
812 lappend todo $a
813 set id [lindex $varccommits($v,$a) end]
814 foreach p $parents($v,$id) {
815 if {[info exists varcid($v,$p)]} {
816 set isrelated($varcid($v,$p)) 1
817 }
818 }
819 }
820 incr ntot
821 set b [lindex $vdownptr($v) $a]
822 if {$b == 0} {
823 while {$a != 0} {
824 set b [lindex $vleftptr($v) $a]
825 if {$b != 0} break
826 set a [lindex $vupptr($v) $a]
827 }
828 }
829 set a $b
830 }
831 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100832 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100833 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100834 if {[llength $children($v,$id)] > 1} {
835 set children($v,$id) [lsort -command [list vtokcmp $v] \
836 $children($v,$id)]
837 }
838 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000839 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100840 set tok {}
841 } else {
842 set tok $oldtok
843 }
844 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100845 set kid [last_real_child $v,$id]
846 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100847 set k $varcid($v,$kid)
848 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
849 set ki $kid
850 set ka $k
851 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100852 }
853 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100854 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100855 set i [lsearch -exact $parents($v,$ki) $id]
856 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
857 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100858 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100859 if {$tok eq $oldtok} {
860 continue
861 }
862 set id [lindex $varccommits($v,$a) end]
863 foreach p $parents($v,$id) {
864 if {[info exists varcid($v,$p)]} {
865 set kidchanged($varcid($v,$p)) 1
866 } else {
867 set sortkids($p) 1
868 }
869 }
870 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100871 set b [lindex $vupptr($v) $a]
872 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100873 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
874 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100875 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100876 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
877 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100878 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100879 set c [lindex $vbackptr($v) $a]
880 set d [lindex $vleftptr($v) $a]
881 if {$c == 0} {
882 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100883 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100884 lset vleftptr($v) $c $d
885 }
886 if {$d != 0} {
887 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100888 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100889 if {[lindex $vlastins($v) $b] == $a} {
890 lset vlastins($v) $b $c
891 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100892 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100893 set c [lindex $vlastins($v) $ka]
894 if {$c == 0 || \
895 [string compare $tok [lindex $varctok($v) $c]] < 0} {
896 set c $ka
897 set b [lindex $vdownptr($v) $ka]
898 } else {
899 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100900 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100901 while {$b != 0 && \
902 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
903 set c $b
904 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100905 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100906 if {$c == $ka} {
907 lset vdownptr($v) $ka $a
908 lset vbackptr($v) $a 0
909 } else {
910 lset vleftptr($v) $c $a
911 lset vbackptr($v) $a $c
912 }
913 lset vleftptr($v) $a $b
914 if {$b != 0} {
915 lset vbackptr($v) $b $a
916 }
917 lset vlastins($v) $ka $a
918 }
919 }
920 foreach id [array names sortkids] {
921 if {[llength $children($v,$id)] > 1} {
922 set children($v,$id) [lsort -command [list vtokcmp $v] \
923 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100924 }
925 }
926 set t2 [clock clicks -milliseconds]
927 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
928}
929
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100930# Fix up the graph after we have found out that in view $v,
931# $p (a commit that we have already seen) is actually the parent
932# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100933proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100934 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100935
936 set pa $varcid($v,$p)
937 if {$p ne [lindex $varcstart($v) $pa]} {
938 splitvarc $p $v
939 set pa $varcid($v,$p)
940 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100941 # seeds always need to be renumbered
942 if {[lindex $vupptr($v) $pa] == 0 ||
943 [string compare [lindex $varctok($v) $a] \
944 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100945 renumbervarc $pa $v
946 }
947}
948
949proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100950 global cmitlisted children parents varcid varctok vtokmod
951 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100952 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100953
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100954 readcommit $id
955 set vid $v,$id
956 set cmitlisted($vid) 1
957 set children($vid) {}
958 set parents($vid) [list $p]
959 set a [newvarc $v $id]
960 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100961 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100962 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
963 modify_arc $v $a
964 }
965 lappend varccommits($v,$a) $id
966 set vp $v,$p
967 if {[llength [lappend children($vp) $id]] > 1} {
968 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
Paul Mackerras009409f2015-05-02 20:53:36 +1000969 unset -nocomplain ordertok
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100970 }
971 fix_reversal $p $a $v
972 incr commitidx($v)
973 if {$v == $curview} {
974 set numcommits $commitidx($v)
975 setcanvscroll
976 if {[info exists targetid]} {
977 if {![comes_before $targetid $p]} {
978 incr targetrow
979 }
980 }
981 }
982}
983
984proc insertfakerow {id p} {
985 global varcid varccommits parents children cmitlisted
986 global commitidx varctok vtokmod targetid targetrow curview numcommits
987
988 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100989 set a $varcid($v,$p)
990 set i [lsearch -exact $varccommits($v,$a) $p]
991 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100992 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100993 return
994 }
995 set children($v,$id) {}
996 set parents($v,$id) [list $p]
997 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100998 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100999 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001000 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001001 # note we deliberately don't update varcstart($v) even if $i == 0
1002 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001003 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +11001004 if {[info exists targetid]} {
1005 if {![comes_before $targetid $p]} {
1006 incr targetrow
1007 }
1008 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001009 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001010 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001011}
1012
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001013proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001014 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001015 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001016 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001017
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001018 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001019 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001020 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001021 return
1022 }
1023 set p [lindex $parents($v,$id) 0]
1024 set a $varcid($v,$id)
1025 set i [lsearch -exact $varccommits($v,$a) $id]
1026 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001027 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001028 return
1029 }
1030 unset varcid($v,$id)
1031 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1032 unset parents($v,$id)
1033 unset children($v,$id)
1034 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001035 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001036 set j [lsearch -exact $children($v,$p) $id]
1037 if {$j >= 0} {
1038 set children($v,$p) [lreplace $children($v,$p) $j $j]
1039 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001040 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001041 if {[info exist currentid] && $id eq $currentid} {
1042 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +10001043 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001044 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001045 if {[info exists targetid] && $targetid eq $id} {
1046 set targetid $p
1047 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001048 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001049 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001050}
1051
Paul Mackerrasaa435612009-09-10 21:58:40 +10001052proc real_children {vp} {
1053 global children nullid nullid2
1054
1055 set kids {}
1056 foreach id $children($vp) {
1057 if {$id ne $nullid && $id ne $nullid2} {
1058 lappend kids $id
1059 }
1060 }
1061 return $kids
1062}
1063
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001064proc first_real_child {vp} {
1065 global children nullid nullid2
1066
1067 foreach id $children($vp) {
1068 if {$id ne $nullid && $id ne $nullid2} {
1069 return $id
1070 }
1071 }
1072 return {}
1073}
1074
1075proc last_real_child {vp} {
1076 global children nullid nullid2
1077
1078 set kids $children($vp)
1079 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1080 set id [lindex $kids $i]
1081 if {$id ne $nullid && $id ne $nullid2} {
1082 return $id
1083 }
1084 }
1085 return {}
1086}
1087
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001088proc vtokcmp {v a b} {
1089 global varctok varcid
1090
1091 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1092 [lindex $varctok($v) $varcid($v,$b)]]
1093}
1094
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001095# This assumes that if lim is not given, the caller has checked that
1096# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001097proc modify_arc {v a {lim {}}} {
1098 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001099
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001100 if {$lim ne {}} {
1101 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1102 if {$c > 0} return
1103 if {$c == 0} {
1104 set r [lindex $varcrow($v) $a]
1105 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1106 }
1107 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001108 set vtokmod($v) [lindex $varctok($v) $a]
1109 set varcmod($v) $a
1110 if {$v == $curview} {
1111 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1112 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001113 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001114 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001115 set r 0
1116 if {$a != 0} {
1117 if {$lim eq {}} {
1118 set lim [llength $varccommits($v,$a)]
1119 }
1120 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1121 }
1122 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001123 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001124 }
1125}
1126
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001127proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001128 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001129 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001130 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001131 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001132
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001133 if {$vrowmod($v) == $commitidx($v)} return
1134 if {$v == $curview} {
1135 if {[llength $displayorder] > $vrowmod($v)} {
1136 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1137 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1138 }
Paul Mackerras009409f2015-05-02 20:53:36 +10001139 unset -nocomplain cached_commitrow
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001140 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001141 set narctot [expr {[llength $varctok($v)] - 1}]
1142 set a $varcmod($v)
1143 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1144 # go up the tree until we find something that has a row number,
1145 # or we get to a seed
1146 set a [lindex $vupptr($v) $a]
1147 }
1148 if {$a == 0} {
1149 set a [lindex $vdownptr($v) 0]
1150 if {$a == 0} return
1151 set vrownum($v) {0}
1152 set varcorder($v) [list $a]
1153 lset varcix($v) $a 0
1154 lset varcrow($v) $a 0
1155 set arcn 0
1156 set row 0
1157 } else {
1158 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001159 if {[llength $vrownum($v)] > $arcn + 1} {
1160 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1161 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1162 }
1163 set row [lindex $varcrow($v) $a]
1164 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001165 while {1} {
1166 set p $a
1167 incr row [llength $varccommits($v,$a)]
1168 # go down if possible
1169 set b [lindex $vdownptr($v) $a]
1170 if {$b == 0} {
1171 # if not, go left, or go up until we can go left
1172 while {$a != 0} {
1173 set b [lindex $vleftptr($v) $a]
1174 if {$b != 0} break
1175 set a [lindex $vupptr($v) $a]
1176 }
1177 if {$a == 0} break
1178 }
1179 set a $b
1180 incr arcn
1181 lappend vrownum($v) $row
1182 lappend varcorder($v) $a
1183 lset varcix($v) $a $arcn
1184 lset varcrow($v) $a $row
1185 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001186 set vtokmod($v) [lindex $varctok($v) $p]
1187 set varcmod($v) $p
1188 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001189 if {[info exists currentid]} {
1190 set selectedline [rowofcommit $currentid]
1191 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001192}
1193
1194# Test whether view $v contains commit $id
1195proc commitinview {id v} {
1196 global varcid
1197
1198 return [info exists varcid($v,$id)]
1199}
1200
1201# Return the row number for commit $id in the current view
1202proc rowofcommit {id} {
1203 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001204 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001205
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001206 set v $curview
1207 if {![info exists varcid($v,$id)]} {
1208 puts "oops rowofcommit no arc for [shortids $id]"
1209 return {}
1210 }
1211 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001212 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001213 update_arcrows $v
1214 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001215 if {[info exists cached_commitrow($id)]} {
1216 return $cached_commitrow($id)
1217 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001218 set i [lsearch -exact $varccommits($v,$a) $id]
1219 if {$i < 0} {
1220 puts "oops didn't find commit [shortids $id] in arc $a"
1221 return {}
1222 }
1223 incr i [lindex $varcrow($v) $a]
1224 set cached_commitrow($id) $i
1225 return $i
1226}
1227
Paul Mackerras42a671f2008-01-02 09:59:39 +11001228# Returns 1 if a is on an earlier row than b, otherwise 0
1229proc comes_before {a b} {
1230 global varcid varctok curview
1231
1232 set v $curview
1233 if {$a eq $b || ![info exists varcid($v,$a)] || \
1234 ![info exists varcid($v,$b)]} {
1235 return 0
1236 }
1237 if {$varcid($v,$a) != $varcid($v,$b)} {
1238 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1239 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1240 }
1241 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1242}
1243
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001244proc bsearch {l elt} {
1245 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1246 return 0
1247 }
1248 set lo 0
1249 set hi [llength $l]
1250 while {$hi - $lo > 1} {
1251 set mid [expr {int(($lo + $hi) / 2)}]
1252 set t [lindex $l $mid]
1253 if {$elt < $t} {
1254 set hi $mid
1255 } elseif {$elt > $t} {
1256 set lo $mid
1257 } else {
1258 return $mid
1259 }
1260 }
1261 return $lo
1262}
1263
1264# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1265proc make_disporder {start end} {
1266 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001267 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001268 global d_valid_start d_valid_end
1269
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001270 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001271 update_arcrows $curview
1272 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001273 set ai [bsearch $vrownum($curview) $start]
1274 set start [lindex $vrownum($curview) $ai]
1275 set narc [llength $vrownum($curview)]
1276 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1277 set a [lindex $varcorder($curview) $ai]
1278 set l [llength $displayorder]
1279 set al [llength $varccommits($curview,$a)]
1280 if {$l < $r + $al} {
1281 if {$l < $r} {
1282 set pad [ntimes [expr {$r - $l}] {}]
1283 set displayorder [concat $displayorder $pad]
1284 set parentlist [concat $parentlist $pad]
1285 } elseif {$l > $r} {
1286 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1287 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1288 }
1289 foreach id $varccommits($curview,$a) {
1290 lappend displayorder $id
1291 lappend parentlist $parents($curview,$id)
1292 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001293 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001294 set i $r
1295 foreach id $varccommits($curview,$a) {
1296 lset displayorder $i $id
1297 lset parentlist $i $parents($curview,$id)
1298 incr i
1299 }
1300 }
1301 incr r $al
1302 }
1303}
1304
1305proc commitonrow {row} {
1306 global displayorder
1307
1308 set id [lindex $displayorder $row]
1309 if {$id eq {}} {
1310 make_disporder $row [expr {$row + 1}]
1311 set id [lindex $displayorder $row]
1312 }
1313 return $id
1314}
1315
1316proc closevarcs {v} {
1317 global varctok varccommits varcid parents children
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001318 global cmitlisted commitidx vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001319
1320 set missing_parents 0
1321 set scripts {}
1322 set narcs [llength $varctok($v)]
1323 for {set a 1} {$a < $narcs} {incr a} {
1324 set id [lindex $varccommits($v,$a) end]
1325 foreach p $parents($v,$id) {
1326 if {[info exists varcid($v,$p)]} continue
1327 # add p as a new commit
1328 incr missing_parents
1329 set cmitlisted($v,$p) 0
1330 set parents($v,$p) {}
1331 if {[llength $children($v,$p)] == 1 &&
1332 [llength $parents($v,$id)] == 1} {
1333 set b $a
1334 } else {
1335 set b [newvarc $v $p]
1336 }
1337 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001338 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1339 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001340 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001341 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001342 incr commitidx($v)
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001343 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001344 }
1345 }
1346 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001347 foreach s $scripts {
1348 eval $s
1349 }
1350 }
1351}
1352
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001353# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1354# Assumes we already have an arc for $rwid.
1355proc rewrite_commit {v id rwid} {
1356 global children parents varcid varctok vtokmod varccommits
1357
1358 foreach ch $children($v,$id) {
1359 # make $rwid be $ch's parent in place of $id
1360 set i [lsearch -exact $parents($v,$ch) $id]
1361 if {$i < 0} {
1362 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1363 }
1364 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1365 # add $ch to $rwid's children and sort the list if necessary
1366 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1367 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1368 $children($v,$rwid)]
1369 }
1370 # fix the graph after joining $id to $rwid
1371 set a $varcid($v,$ch)
1372 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001373 # parentlist is wrong for the last element of arc $a
1374 # even if displayorder is right, hence the 3rd arg here
1375 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001376 }
1377}
1378
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001379# Mechanism for registering a command to be executed when we come
1380# across a particular commit. To handle the case when only the
1381# prefix of the commit is known, the commitinterest array is now
1382# indexed by the first 4 characters of the ID. Each element is a
1383# list of id, cmd pairs.
1384proc interestedin {id cmd} {
1385 global commitinterest
1386
1387 lappend commitinterest([string range $id 0 3]) $id $cmd
1388}
1389
1390proc check_interest {id scripts} {
1391 global commitinterest
1392
1393 set prefix [string range $id 0 3]
1394 if {[info exists commitinterest($prefix)]} {
1395 set newlist {}
1396 foreach {i script} $commitinterest($prefix) {
1397 if {[string match "$i*" $id]} {
1398 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1399 } else {
1400 lappend newlist $i $script
1401 }
1402 }
1403 if {$newlist ne {}} {
1404 set commitinterest($prefix) $newlist
1405 } else {
1406 unset commitinterest($prefix)
1407 }
1408 }
1409 return $scripts
1410}
1411
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001412proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001413 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001414 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001415 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001416 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001417 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001418
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001419 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001420 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001421 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001422 set stuff "\0"
1423 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001424 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001425 if {![eof $fd]} {
1426 return 1
1427 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001428 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001429 global viewinstances
1430 unset commfd($inst)
1431 set i [lsearch -exact $viewinstances($view) $inst]
1432 if {$i >= 0} {
1433 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001434 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001435 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001436 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001437 if {[catch {close $fd} err]} {
1438 set fv {}
1439 if {$view != $curview} {
1440 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001441 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001442 if {[string range $err 0 4] == "usage"} {
1443 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001444 bad arguments to git log."
Marc Branchaud5ee1c992015-04-07 11:53:37 -04001445 if {$viewname($view) eq [mc "Command line"]} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001446 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001447 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001448 to allow selection of commits to be displayed.)"
1449 }
1450 } else {
1451 set err "Error reading commits$fv: $err"
1452 }
1453 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001454 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001455 if {[incr viewactive($view) -1] <= 0} {
1456 set viewcomplete($view) 1
1457 # Check if we have seen any ids listed as parents that haven't
1458 # appeared in the list
1459 closevarcs $view
1460 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001461 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001462 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001463 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001464 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001465 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001466 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001467 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001468 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001469 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001470 while 1 {
1471 set i [string first "\0" $stuff $start]
1472 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001473 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001474 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001475 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001476 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001477 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001478 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001479 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001480 } else {
1481 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001482 }
1483 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001484 set j [string first "\n" $cmit]
1485 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001486 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001487 if {$j >= 0 && [string match "commit *" $cmit]} {
1488 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001489 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001490 switch -- [string index $ids 0] {
1491 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001492 "^" {set listed 2}
1493 "<" {set listed 3}
1494 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001495 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001496 set ids [string range $ids 1 end]
1497 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001498 set ok 1
1499 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001500 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001501 set ok 0
1502 break
1503 }
1504 }
1505 }
1506 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001507 set shortcmit $cmit
1508 if {[string length $shortcmit] > 80} {
1509 set shortcmit "[string range $shortcmit 0 80]..."
1510 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001511 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001512 exit 1
1513 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001514 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001515 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001516
Paul Mackerras22387f22012-03-19 11:21:08 +11001517 lappend vshortids($view,[string range $id 0 3]) $id
1518
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001519 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001520 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001521 # git log doesn't rewrite parents for unlisted commits
1522 # when doing path limiting, so work around that here
1523 # by working out the rewritten parent with git rev-list
1524 # and if we already know about it, using the rewritten
1525 # parent as a substitute parent for $id's children.
1526 if {![catch {
1527 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001528 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001529 }]} {
1530 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1531 # use $rwid in place of $id
1532 rewrite_commit $view $id $rwid
1533 continue
1534 }
1535 }
1536 }
1537
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001538 set a 0
1539 if {[info exists varcid($vid)]} {
1540 if {$cmitlisted($vid) || !$listed} continue
1541 set a $varcid($vid)
1542 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001543 if {$listed} {
1544 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001545 } else {
1546 set olds {}
1547 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001548 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001549 set cmitlisted($vid) $listed
1550 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001551 if {![info exists children($vid)]} {
1552 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001553 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001554 set k [lindex $children($vid) 0]
1555 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001556 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001557 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1558 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001559 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001560 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001561 if {$a == 0} {
1562 # new arc
1563 set a [newvarc $view $id]
1564 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001565 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1566 modify_arc $view $a
1567 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001568 if {![info exists varcid($vid)]} {
1569 set varcid($vid) $a
1570 lappend varccommits($view,$a) $id
1571 incr commitidx($view)
1572 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001573
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001574 set i 0
1575 foreach p $olds {
1576 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1577 set vp $view,$p
1578 if {[llength [lappend children($vp) $id]] > 1 &&
1579 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1580 set children($vp) [lsort -command [list vtokcmp $view] \
1581 $children($vp)]
Paul Mackerras009409f2015-05-02 20:53:36 +10001582 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001583 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001584 if {[info exists varcid($view,$p)]} {
1585 fix_reversal $p $a $view
1586 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001587 }
1588 incr i
1589 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001590
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001591 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001592 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001593 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001594 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001595 global numcommits hlview
1596
1597 if {$view == $curview} {
1598 set numcommits $commitidx($view)
1599 run chewcommits
1600 }
1601 if {[info exists hlview] && $view == $hlview} {
1602 # we never actually get here...
1603 run vhighlightmore
1604 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001605 foreach s $scripts {
1606 eval $s
1607 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001608 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001609 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001610}
1611
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001612proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001613 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001614 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001615
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001616 layoutmore
1617 if {$viewcomplete($curview)} {
1618 global commitidx varctok
1619 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001620
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001621 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001622 update
1623 reset_pending_select {}
1624
1625 if {[commitinview $pending_select $curview]} {
1626 selectline [rowofcommit $pending_select] 1
1627 } else {
1628 set row [first_real_row]
1629 selectline $row 1
1630 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001631 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001632 if {$commitidx($curview) > 0} {
1633 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1634 #puts "overall $ms ms for $numcommits commits"
1635 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1636 } else {
1637 show_status [mc "No commits selected"]
1638 }
1639 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001640 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001641 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001642}
1643
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001644proc do_readcommit {id} {
1645 global tclencoding
1646
1647 # Invoke git-log to handle automatic encoding conversion
1648 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1649 # Read the results using i18n.logoutputencoding
1650 fconfigure $fd -translation lf -eofchar {}
1651 if {$tclencoding != {}} {
1652 fconfigure $fd -encoding $tclencoding
1653 }
1654 set contents [read $fd]
1655 close $fd
1656 # Remove the heading line
1657 regsub {^commit [0-9a-f]+\n} $contents {} contents
1658
1659 return $contents
1660}
1661
Paul Mackerras1db95b02005-05-09 04:08:39 +00001662proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001663 if {[catch {set contents [do_readcommit $id]}]} return
1664 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001665}
1666
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001667proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001668 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001669
1670 set inhdr 1
1671 set comment {}
1672 set headline {}
1673 set auname {}
1674 set audate {}
1675 set comname {}
1676 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001677 set hdrend [string first "\n\n" $contents]
1678 if {$hdrend < 0} {
1679 # should never happen...
1680 set hdrend [string length $contents]
1681 }
1682 set header [string range $contents 0 [expr {$hdrend - 1}]]
1683 set comment [string range $contents [expr {$hdrend + 2}] end]
1684 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001685 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001686 set tag [lindex $line 0]
1687 if {$tag == "author"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001688 set audate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001689 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001690 } elseif {$tag == "committer"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001691 set comdate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001692 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001693 }
1694 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001695 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001696 # take the first non-blank line of the comment as the headline
1697 set headline [string trimleft $comment]
1698 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001699 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001700 set headline [string range $headline 0 $i]
1701 }
1702 set headline [string trimright $headline]
1703 set i [string first "\r" $headline]
1704 if {$i >= 0} {
1705 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001706 }
1707 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001708 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001709 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001710 set newcomment {}
1711 foreach line [split $comment "\n"] {
1712 append newcomment " "
1713 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001714 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001715 }
1716 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001717 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001718 set hasnote [string first "\nNotes:\n" $contents]
Thomas Rastb449eb22013-11-16 18:37:42 +01001719 set diff ""
1720 # If there is diff output shown in the git-log stream, split it
1721 # out. But get rid of the empty line that always precedes the
1722 # diff.
1723 set i [string first "\n\ndiff" $comment]
1724 if {$i >= 0} {
1725 set diff [string range $comment $i+1 end]
1726 set comment [string range $comment 0 $i-1]
1727 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001728 set commitinfo($id) [list $headline $auname $audate \
Thomas Rastb449eb22013-11-16 18:37:42 +01001729 $comname $comdate $comment $hasnote $diff]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001730}
1731
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001732proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001733 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001734
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001735 if {[info exists commitdata($id)]} {
1736 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001737 } else {
1738 readcommit $id
1739 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001740 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001741 }
1742 }
1743 return 1
1744}
1745
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001746# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1747# and are present in the current view.
1748# This is fairly slow...
1749proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001750 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001751
1752 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001753 if {[string length $prefix] >= 4} {
1754 set vshortid $curview,[string range $prefix 0 3]
1755 if {[info exists vshortids($vshortid)]} {
1756 foreach id $vshortids($vshortid) {
1757 if {[string match "$prefix*" $id]} {
1758 if {[lsearch -exact $ids $id] < 0} {
1759 lappend ids $id
1760 if {[llength $ids] >= 2} break
1761 }
1762 }
1763 }
1764 }
1765 } else {
1766 foreach match [array names varcid "$curview,$prefix*"] {
1767 lappend ids [lindex [split $match ","] 1]
1768 if {[llength $ids] >= 2} break
1769 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001770 }
1771 return $ids
1772}
1773
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001774proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001775 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001776 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001777 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001778 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001779
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001780 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
Paul Mackerras009409f2015-05-02 20:53:36 +10001781 unset -nocomplain $v
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001782 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001783 set refd [open [list | git show-ref -d] r]
1784 while {[gets $refd line] >= 0} {
1785 if {[string index $line 40] ne " "} continue
1786 set id [string range $line 0 39]
1787 set ref [string range $line 41 end]
1788 if {![string match "refs/*" $ref]} continue
1789 set name [string range $ref 5 end]
1790 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001791 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001792 set headids($name) $id
1793 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001794 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001795 } elseif {[string match "heads/*" $name]} {
1796 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001797 set headids($name) $id
1798 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001799 } elseif {[string match "tags/*" $name]} {
1800 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1801 # which is what we want since the former is the commit ID
1802 set name [string range $name 5 end]
1803 if {[string match "*^{}" $name]} {
1804 set name [string range $name 0 end-3]
1805 } else {
1806 set tagobjid($name) $id
1807 }
1808 set tagids($name) $id
1809 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001810 } else {
1811 set otherrefids($name) $id
1812 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001813 }
1814 }
Alex Riesen062d6712007-07-29 22:28:40 +02001815 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001816 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001817 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001818 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001819 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001820 set thehead [exec git symbolic-ref HEAD]
1821 if {[string match "refs/heads/*" $thehead]} {
1822 set mainhead [string range $thehead 11 end]
1823 }
1824 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001825 set selectheadid {}
1826 if {$selecthead ne {}} {
1827 catch {
1828 set selectheadid [exec git rev-parse --verify $selecthead]
1829 }
1830 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001831}
1832
Paul Mackerras8f489362007-07-13 19:49:37 +10001833# skip over fake commits
1834proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001835 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001836
1837 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001838 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001839 if {$id ne $nullid && $id ne $nullid2} {
1840 break
1841 }
1842 }
1843 return $row
1844}
1845
Paul Mackerrase11f1232007-06-16 20:29:25 +10001846# update things for a head moved to a child of its previous location
1847proc movehead {id name} {
1848 global headids idheads
1849
1850 removehead $headids($name) $name
1851 set headids($name) $id
1852 lappend idheads($id) $name
1853}
1854
1855# update things when a head has been removed
1856proc removehead {id name} {
1857 global headids idheads
1858
1859 if {$idheads($id) eq $name} {
1860 unset idheads($id)
1861 } else {
1862 set i [lsearch -exact $idheads($id) $name]
1863 if {$i >= 0} {
1864 set idheads($id) [lreplace $idheads($id) $i $i]
1865 }
1866 }
1867 unset headids($name)
1868}
1869
Pat Thoytsd93f1712009-04-17 01:24:35 +01001870proc ttk_toplevel {w args} {
1871 global use_ttk
1872 eval [linsert $args 0 ::toplevel $w]
1873 if {$use_ttk} {
1874 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1875 }
1876 return $w
1877}
1878
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001879proc make_transient {window origin} {
1880 global have_tk85
1881
1882 # In MacOS Tk 8.4 transient appears to work by setting
1883 # overrideredirect, which is utterly useless, since the
1884 # windows get no border, and are not even kept above
1885 # the parent.
1886 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1887
1888 wm transient $window $origin
1889
1890 # Windows fails to place transient windows normally, so
1891 # schedule a callback to center them on the parent.
1892 if {[tk windowingsystem] eq {win32}} {
1893 after idle [list tk::PlaceWindow $window widget $origin]
1894 }
1895}
1896
Alex Henrieef87a482015-05-11 13:26:41 -06001897proc show_error {w top msg} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001898 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001899 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001900 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001901 message $w.m -text $msg -justify center -aspect 400
1902 pack $w.m -side top -fill x -padx 20 -pady 20
Alex Henrieef87a482015-05-11 13:26:41 -06001903 ${NS}::button $w.ok -default active -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001904 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001905 bind $top <Visibility> "grab $top; focus $top"
1906 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001907 bind $top <Key-space> "destroy $top"
1908 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001909 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001910}
1911
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001912proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001913 if {[tk windowingsystem] eq "win32"} {
1914 tk_messageBox -icon error -type ok -title [wm title .] \
1915 -parent $owner -message $msg
1916 } else {
1917 set w .error
1918 ttk_toplevel $w
1919 make_transient $w $owner
1920 show_error $w $w $msg
1921 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001922}
1923
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001924proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001925 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001926 set confirm_ok 0
1927 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001928 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001929 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001930 message $w.m -text $msg -justify center -aspect 400
1931 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001932 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001933 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001934 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001935 pack $w.cancel -side right -fill x
1936 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001937 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1938 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1939 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001940 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001941 tkwait window $w
1942 return $confirm_ok
1943}
1944
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001945proc setoptions {} {
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001946 global use_ttk
1947
Pat Thoytsd93f1712009-04-17 01:24:35 +01001948 if {[tk windowingsystem] ne "win32"} {
1949 option add *Panedwindow.showHandle 1 startupFile
1950 option add *Panedwindow.sashRelief raised startupFile
1951 if {[tk windowingsystem] ne "aqua"} {
1952 option add *Menu.font uifont startupFile
1953 }
1954 } else {
1955 option add *Menu.TearOff 0 startupFile
1956 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001957 option add *Button.font uifont startupFile
1958 option add *Checkbutton.font uifont startupFile
1959 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001960 option add *Menubutton.font uifont startupFile
1961 option add *Label.font uifont startupFile
1962 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001963 option add *Entry.font textfont startupFile
1964 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001965 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001966 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001967 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001968}
1969
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001970proc setttkstyle {} {
1971 eval font configure TkDefaultFont [fontflags mainfont]
1972 eval font configure TkTextFont [fontflags textfont]
1973 eval font configure TkHeadingFont [fontflags mainfont]
1974 eval font configure TkCaptionFont [fontflags mainfont] -weight bold
1975 eval font configure TkTooltipFont [fontflags uifont]
1976 eval font configure TkFixedFont [fontflags textfont]
1977 eval font configure TkIconFont [fontflags uifont]
1978 eval font configure TkMenuFont [fontflags uifont]
1979 eval font configure TkSmallCaptionFont [fontflags uifont]
1980}
1981
Paul Mackerras79056032008-10-18 16:24:46 +11001982# Make a menu and submenus.
1983# m is the window name for the menu, items is the list of menu items to add.
1984# Each item is a list {mc label type description options...}
1985# mc is ignored; it's so we can put mc there to alert xgettext
1986# label is the string that appears in the menu
1987# type is cascade, command or radiobutton (should add checkbutton)
1988# description depends on type; it's the sublist for cascade, the
1989# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001990proc makemenu {m items} {
1991 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001992 if {[tk windowingsystem] eq {aqua}} {
1993 set Meta1 Cmd
1994 } else {
1995 set Meta1 Ctrl
1996 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001997 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11001998 set name [mc [lindex $i 1]]
1999 set type [lindex $i 2]
2000 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002001 set params [list $type]
2002 if {$name ne {}} {
2003 set u [string first "&" [string map {&& x} $name]]
2004 lappend params -label [string map {&& & & {}} $name]
2005 if {$u >= 0} {
2006 lappend params -underline $u
2007 }
2008 }
2009 switch -- $type {
2010 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11002011 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002012 lappend params -menu $m.$submenu
2013 }
2014 "command" {
2015 lappend params -command $thing
2016 }
2017 "radiobutton" {
2018 lappend params -variable [lindex $thing 0] \
2019 -value [lindex $thing 1]
2020 }
2021 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002022 set tail [lrange $i 4 end]
2023 regsub -all {\yMeta1\y} $tail $Meta1 tail
2024 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002025 if {$type eq "cascade"} {
2026 makemenu $m.$submenu $thing
2027 }
2028 }
2029}
2030
2031# translate string and remove ampersands
2032proc mca {str} {
2033 return [string map {&& & & {}} [mc $str]]
2034}
2035
Paul Mackerras39c12692013-05-11 17:08:41 +10002036proc cleardropsel {w} {
2037 $w selection clear
2038}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002039proc makedroplist {w varname args} {
2040 global use_ttk
2041 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002042 set width 0
2043 foreach label $args {
2044 set cx [string length $label]
2045 if {$cx > $width} {set width $cx}
2046 }
2047 set gm [ttk::combobox $w -width $width -state readonly\
Paul Mackerras39c12692013-05-11 17:08:41 +10002048 -textvariable $varname -values $args \
2049 -exportselection false]
2050 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002051 } else {
2052 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
2053 }
2054 return $gm
2055}
2056
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002057proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002058 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002059 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002060 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002061 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002062 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002063 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002064 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002065 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002066 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002067 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04002068 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002069 global uifgcolor uifgdisabledcolor
2070 global filesepbgcolor filesepfgcolor
2071 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002072 global headctxmenu progresscanv progressitem progresscoords statusw
2073 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002074 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002075 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002076 global git_version
2077 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002078
Paul Mackerras79056032008-10-18 16:24:46 +11002079 # The "mc" arguments here are purely so that xgettext
2080 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002081 set file {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002082 mc "&File" cascade {
2083 {mc "&Update" command updatecommits -accelerator F5}
2084 {mc "&Reload" command reloadcommits -accelerator Shift-F5}
2085 {mc "Reread re&ferences" command rereadrefs}
2086 {mc "&List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002087 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002088 {mc "Start git &gui" command {exec git gui &}}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002089 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002090 {mc "&Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002091 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002092 set edit {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002093 mc "&Edit" cascade {
2094 {mc "&Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002095 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002096 set view {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002097 mc "&View" cascade {
2098 {mc "&New view..." command {newview 0} -accelerator Shift-F4}
2099 {mc "&Edit view..." command editview -state disabled -accelerator F4}
2100 {mc "&Delete view" command delview -state disabled}
Paul Mackerras79056032008-10-18 16:24:46 +11002101 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002102 {mc "&All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002103 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002104 if {[tk windowingsystem] ne "aqua"} {
2105 set help {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002106 mc "&Help" cascade {
2107 {mc "&About gitk" command about}
2108 {mc "&Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002109 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002110 set bar [list $file $edit $view $help]
2111 } else {
2112 proc ::tk::mac::ShowPreferences {} {doprefs}
2113 proc ::tk::mac::Quit {} {doquit}
2114 lset file end [lreplace [lindex $file end] end-1 end]
2115 set apple {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002116 xx "&Apple" cascade {
2117 {mc "&About gitk" command about}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002118 {xx "" separator}
2119 }}
2120 set help {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002121 mc "&Help" cascade {
2122 {mc "&Key bindings" command keys}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002123 }}
2124 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002125 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002126 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002127 . configure -menu .bar
2128
Pat Thoytsd93f1712009-04-17 01:24:35 +01002129 if {$use_ttk} {
2130 # cover the non-themed toplevel with a themed frame.
2131 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2132 }
2133
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002134 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002135 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002136
2137 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002138 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002139 set geometry(topheight) [expr {15 * $linespc}]
2140 set geometry(topwidth) [expr {80 * $charspc}]
2141 set geometry(botheight) [expr {15 * $linespc}]
2142 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002143 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2144 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002145 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002146
2147 # 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 +01002148 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2149 ${NS}::frame .tf.histframe
2150 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2151 if {!$use_ttk} {
2152 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
2153 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002154
2155 # create three canvases
2156 set cscroll .tf.histframe.csb
2157 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002158 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04002159 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002160 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002161 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002162 .tf.histframe.pwclist add $canv
2163 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002164 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002165 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002166 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002167 .tf.histframe.pwclist add $canv2
2168 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002169 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002170 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002171 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002172 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002173 if {$use_ttk} {
2174 bind .tf.histframe.pwclist <Map> {
2175 bind %W <Map> {}
2176 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2177 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2178 }
2179 } else {
2180 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2181 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
2182 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002183
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002184 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002185 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2186 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002187 pack $cscroll -side right -fill y
2188 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2189 lappend bglist $canv $canv2 $canv3
2190 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2191
2192 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002193 ${NS}::frame .tf.bar
2194 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002195
2196 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002197 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002198 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002199 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002200 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002201 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002202 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002203 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002204 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002205 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002206
Stefan Hallerf062e502012-09-22 09:46:48 +02002207 set bm_left_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002208 #define left_width 16
2209 #define left_height 16
2210 static unsigned char left_bits[] = {
2211 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2212 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2213 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2214 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002215 set bm_right_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002216 #define right_width 16
2217 #define right_height 16
2218 static unsigned char right_bits[] = {
2219 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2220 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2221 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2222 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002223 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2224 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2225 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2226 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002227
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002228 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2229 if {$use_ttk} {
2230 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
2231 } else {
2232 .tf.bar.leftbut configure -image bm-left
2233 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002234 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002235 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2236 if {$use_ttk} {
2237 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
2238 } else {
2239 .tf.bar.rightbut configure -image bm-right
2240 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002241 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002242
Pat Thoytsd93f1712009-04-17 01:24:35 +01002243 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002244 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002245 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Paul Mackerras6df74032008-05-11 22:13:02 +10002246 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002247 ${NS}::label .tf.bar.rowlabel2 -text "/"
2248 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Paul Mackerras6df74032008-05-11 22:13:02 +10002249 -relief sunken -anchor e
2250 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2251 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002252 if {!$use_ttk} {
2253 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2254 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002255 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002256 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002257
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002258 # Status label and progress bar
2259 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002260 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002261 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002262 if {$use_ttk} {
2263 set progresscanv [ttk::progressbar .tf.bar.progress]
2264 } else {
2265 set h [expr {[font metrics uifont -linespace] + 2}]
2266 set progresscanv .tf.bar.progress
2267 canvas $progresscanv -relief sunken -height $h -borderwidth 2
YOKOTA Hiroshi66db14c2015-10-25 01:58:41 +09002268 set progressitem [$progresscanv create rect -1 0 0 $h -fill lime]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002269 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2270 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
2271 }
2272 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002273 set progresscoords {0 0}
2274 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002275 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002276 bind $progresscanv <Configure> adjustprogress
2277 set lastprogupdate [clock clicks -milliseconds]
2278 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002279
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002280 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002281 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002282
2283 set bm_down_data {
2284 #define down_width 16
2285 #define down_height 16
2286 static unsigned char down_bits[] = {
2287 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2288 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2289 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
2290 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
2291 }
2292 image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
2293 ${NS}::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
2294 .tf.lbar.fnext configure -image bm-down
2295
2296 set bm_up_data {
2297 #define up_width 16
2298 #define up_height 16
2299 static unsigned char up_bits[] = {
2300 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
2301 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
2302 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2303 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
2304 }
2305 image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
2306 ${NS}::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
2307 .tf.lbar.fprev configure -image bm-up
2308
Pat Thoytsd93f1712009-04-17 01:24:35 +01002309 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002310
Paul Mackerras687c8762007-09-22 12:49:33 +10002311 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2312 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002313 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002314 set gm [makedroplist .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002315 [mc "containing:"] \
2316 [mc "touching paths:"] \
Martin Langhoffc33cb902012-06-14 20:34:11 +02002317 [mc "adding/removing string:"] \
2318 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002319 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002320 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002321
2322 set findstring {}
2323 set fstring .tf.lbar.findstring
2324 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002325 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002326 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002327 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002328 set findtypemenu [makedroplist .tf.lbar.findtype \
2329 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002330 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002331 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002332 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002333 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002334 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002335 pack .tf.lbar.findloc -side right
2336 pack .tf.lbar.findtype -side right
2337 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002338
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002339 # Finish putting the upper half of the viewer together
2340 pack .tf.lbar -in .tf -side bottom -fill x
2341 pack .tf.bar -in .tf -side bottom -fill x
2342 pack .tf.histframe -fill both -side top -expand 1
2343 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002344 if {!$use_ttk} {
2345 .ctop paneconfigure .tf -height $geometry(topheight)
2346 .ctop paneconfigure .tf -width $geometry(topwidth)
2347 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002348
2349 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002350 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002351
2352 # lower left, a text box over search bar, scroll bar to the right
2353 # if we know window height, then that will set the lower text height, otherwise
2354 # we set lower text height which will drive window height
2355 if {[info exists geometry(main)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002356 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002357 } else {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002358 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002359 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002360 ${NS}::frame .bleft.top
2361 ${NS}::frame .bleft.mid
2362 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002363
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002364 # gap between sub-widgets
2365 set wgap [font measure uifont "i"]
2366
Pat Thoytsd93f1712009-04-17 01:24:35 +01002367 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002368 pack .bleft.top.search -side left -padx 5
2369 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002370 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002371 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002372 lappend entries $sstring
2373 trace add variable searchstring write incrsearch
2374 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002375 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002376 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002377 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002378 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002379 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002380 -command changediffdisp -variable diffelide -value {1 0}
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002381
Pat Thoytsd93f1712009-04-17 01:24:35 +01002382 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002383 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left -ipadx $wgap
Mark Hills0933b042010-01-13 20:40:19 +00002384 spinbox .bleft.mid.diffcontext -width 5 \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002385 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002386 -validate all -validatecommand "diffcontextvalidate %P" \
2387 -textvariable diffcontextstring
2388 .bleft.mid.diffcontext set $diffcontext
2389 trace add variable diffcontextstring write diffcontextchange
2390 lappend entries .bleft.mid.diffcontext
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002391 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left -ipadx $wgap
Pat Thoytsd93f1712009-04-17 01:24:35 +01002392 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002393 -command changeignorespace -variable ignorespace
2394 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002395
2396 set worddiff [mc "Line diff"]
2397 if {[package vcompare $git_version "1.7.2"] >= 0} {
2398 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2399 [mc "Markup words"] [mc "Color words"]
2400 trace add variable worddiff write changeworddiff
2401 pack .bleft.mid.worddiff -side left -padx 5
2402 }
2403
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002404 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002405 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002406 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002407 -yscrollcommand scrolltext -wrap none \
2408 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002409 if {$have_tk85} {
2410 $ctext conf -tabstyle wordprocessor
2411 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002412 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2413 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002414 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002415 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002416 grid $ctext .bleft.bottom.sb -sticky nsew
2417 grid .bleft.bottom.sbhorizontal -sticky ew
2418 grid columnconfigure .bleft.bottom 0 -weight 1
2419 grid rowconfigure .bleft.bottom 0 -weight 1
2420 grid rowconfigure .bleft.bottom 1 -weight 0
2421 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002422 lappend bglist $ctext
2423 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002424
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002425 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002426 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002427 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2428 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002429 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002430 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2431 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2432 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2433 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2434 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2435 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2436 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2437 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2438 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2439 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2440 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2441 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2442 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2443 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2444 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2445 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002446 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002447 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002448 $ctext tag conf mresult -font textfontbold
2449 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002450 $ctext tag conf found -back $foundbgcolor
2451 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerras76d64ca2014-01-23 22:06:22 +11002452 $ctext tag conf wwrap -wrap word -lmargin2 1c
Paul Mackerras4399fe32013-01-03 10:10:31 +11002453 $ctext tag conf bold -font textfontbold
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002454
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002455 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002456 if {!$use_ttk} {
2457 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
2458 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002459
2460 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002461 ${NS}::frame .bright
2462 ${NS}::frame .bright.mode
2463 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002464 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002465 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002466 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002467 grid .bright.mode.patch .bright.mode.tree -sticky ew
2468 pack .bright.mode -side top -fill x
2469 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002470 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002471 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002472 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002473 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002474 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002475 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002476 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002477 -cursor [. cget -cursor] \
2478 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002479 lappend bglist $cflist
2480 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002481 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002482 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002483 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002484 $cflist tag configure highlight \
2485 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002486 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002487
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002488 .pwbottom add .bright
2489 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002490
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002491 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002492 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002493 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2494 if {$w > [winfo screenwidth .]} {
2495 set w [winfo screenwidth .]
2496 }
2497 if {$h > [winfo screenheight .]} {
2498 set h [winfo screenheight .]
2499 }
2500 wm geometry . "${w}x$h"
2501 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002502 }
2503
Pat Thoytsc876dba2009-04-14 22:09:53 +01002504 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2505 wm state . $geometry(state)
2506 }
2507
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002508 if {[tk windowingsystem] eq {aqua}} {
2509 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002510 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002511 } else {
2512 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002513 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002514 }
2515
Pat Thoytsd93f1712009-04-17 01:24:35 +01002516 if {$use_ttk} {
2517 bind .ctop <Map> {
2518 bind %W <Map> {}
2519 %W sashpos 0 $::geometry(topheight)
2520 }
2521 bind .pwbottom <Map> {
2522 bind %W <Map> {}
2523 %W sashpos 0 $::geometry(botwidth)
2524 }
2525 }
2526
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002527 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2528 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002529 bindall <1> {selcanvline %W %x %y}
2530 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002531 if {[tk windowingsystem] == "win32"} {
2532 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2533 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2534 } else {
2535 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2536 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Gabriele Mazzotta122b8072014-11-15 15:05:06 +01002537 bind $ctext <Button> {
2538 if {"%b" eq 6} {
2539 $ctext xview scroll -5 units
2540 } elseif {"%b" eq 7} {
2541 $ctext xview scroll 5 units
2542 }
2543 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002544 if {[tk windowingsystem] eq "aqua"} {
2545 bindall <MouseWheel> {
2546 set delta [expr {- (%D)}]
2547 allcanvs yview scroll $delta units
2548 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002549 bindall <Shift-MouseWheel> {
2550 set delta [expr {- (%D)}]
2551 $canv xview scroll $delta units
2552 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002553 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002554 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002555 bindall <$::BM> "canvscan mark %W %x %y"
2556 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002557 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2558 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002559 bindkey <Home> selfirstline
2560 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002561 bind . <Key-Up> "selnextline -1"
2562 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002563 bind . <Shift-Key-Up> "dofind -1 0"
2564 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002565 bindkey <Key-Right> "goforw"
2566 bindkey <Key-Left> "goback"
2567 bind . <Key-Prior> "selnextpage -1"
2568 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002569 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2570 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2571 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2572 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2573 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2574 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002575 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2576 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2577 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002578 bindkey p "selnextline -1"
2579 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002580 bindkey z "goback"
2581 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002582 bindkey k "selnextline -1"
2583 bindkey j "selnextline 1"
2584 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002585 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002586 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002587 bindkey d "$ctext yview scroll 18 units"
2588 bindkey u "$ctext yview scroll -18 units"
Ismael Luceno0deb5c92015-04-15 13:18:17 -03002589 bindkey g {$sha1entry delete 0 end; focus $sha1entry}
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002590 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002591 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002592 bindkey <Key-Return> {dofind 1 1}
2593 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002594 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002595 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002596 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002597 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002598 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002599 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002600 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002601 bind . <$M1B-f> {dofind 1 1}
2602 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002603 bind . <$M1B-r> dosearchback
2604 bind . <$M1B-s> dosearch
2605 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002606 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002607 bind . <$M1B-KP_Add> {incrfont 1}
2608 bind . <$M1B-minus> {incrfont -1}
2609 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002610 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002611 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002612 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002613 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002614 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002615 bind $sha1entry <<PasteSelection>> clearsha1
Ilya Bobyrada2ea12014-03-20 01:58:51 -07002616 bind $sha1entry <<Paste>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002617 bind $cflist <1> {sel_flist %W %x %y; break}
2618 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002619 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002620 global ctxbut
2621 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002622 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002623 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002624 bind $ctext <<Selection>> rehighlight_search_results
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002625 for {set i 1} {$i < 10} {incr i} {
2626 bind . <$M1B-Key-$i> [list go_to_parent $i]
2627 }
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002628
2629 set maincursor [. cget -cursor]
2630 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002631 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002632
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002633 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002634 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002635 {mc "Diff this -> selected" command {diffvssel 0}}
2636 {mc "Diff selected -> this" command {diffvssel 1}}
2637 {mc "Make patch" command mkpatch}
2638 {mc "Create tag" command mktag}
Beat Bollid835dbb2015-07-18 13:15:39 +02002639 {mc "Copy commit summary" command copysummary}
Paul Mackerras79056032008-10-18 16:24:46 +11002640 {mc "Write commit to file" command writecommit}
2641 {mc "Create new branch" command mkbranch}
2642 {mc "Cherry-pick this commit" command cherrypick}
2643 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002644 {mc "Mark this commit" command markhere}
2645 {mc "Return to mark" command gotomark}
2646 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002647 {mc "Compare with marked commit" command compare_commits}
Paul Mackerras6febded2012-03-23 22:07:27 +11002648 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2649 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Knut Franke8f3ff932013-04-27 16:36:13 +02002650 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002651 }
2652 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002653
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002654 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002655 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002656 {mc "Diff this -> selected" command {diffvssel 0}}
2657 {mc "Diff selected -> this" command {diffvssel 1}}
2658 {mc "Make patch" command mkpatch}
Paul Mackerras6febded2012-03-23 22:07:27 +11002659 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2660 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002661 }
2662 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002663
Paul Mackerras10299152006-08-02 09:52:01 +10002664 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002665 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002666 {mc "Check out this branch" command cobranch}
2667 {mc "Remove this branch" command rmbranch}
Michael Rappazzo427cf162015-05-07 22:29:20 -04002668 {mc "Copy branch name" command {clipboard clear; clipboard append $headmenuhead}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002669 }
2670 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002671
2672 global flist_menu
2673 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002674 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002675 {mc "Highlight this too" command {flist_hl 0}}
2676 {mc "Highlight this only" command {flist_hl 1}}
2677 {mc "External diff" command {external_diff}}
2678 {mc "Blame parent commit" command {external_blame 1}}
Michael Rappazzo427cf162015-05-07 22:29:20 -04002679 {mc "Copy path" command {clipboard clear; clipboard append $flist_menu_file}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002680 }
2681 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002682
2683 global diff_menu
2684 set diff_menu .diffctxmenu
2685 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002686 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002687 {mc "Run git gui blame on this line" command {external_blame_diff}}
2688 }
2689 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002690}
2691
Mark Levedahl314c3092007-08-07 21:40:35 -04002692# Windows sends all mouse wheel events to the current focused window, not
2693# the one where the mouse hovers, so bind those events here and redirect
2694# to the correct window
2695proc windows_mousewheel_redirector {W X Y D} {
2696 global canv canv2 canv3
2697 set w [winfo containing -displayof $W $X $Y]
2698 if {$w ne ""} {
2699 set u [expr {$D < 0 ? 5 : -5}]
2700 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2701 allcanvs yview scroll $u units
2702 } else {
2703 catch {
2704 $w yview scroll $u units
2705 }
2706 }
2707 }
2708}
2709
Paul Mackerras6df74032008-05-11 22:13:02 +10002710# Update row number label when selectedline changes
2711proc selectedline_change {n1 n2 op} {
2712 global selectedline rownumsel
2713
Paul Mackerras94b4a692008-05-20 20:51:06 +10002714 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002715 set rownumsel {}
2716 } else {
2717 set rownumsel [expr {$selectedline + 1}]
2718 }
2719}
2720
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002721# mouse-2 makes all windows scan vertically, but only the one
2722# the cursor is in scans horizontally
2723proc canvscan {op w x y} {
2724 global canv canv2 canv3
2725 foreach c [list $canv $canv2 $canv3] {
2726 if {$c == $w} {
2727 $c scan $op $x $y
2728 } else {
2729 $c scan $op 0 $y
2730 }
2731 }
2732}
2733
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002734proc scrollcanv {cscroll f0 f1} {
2735 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002736 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002737 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002738}
2739
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002740# when we make a key binding for the toplevel, make sure
2741# it doesn't get triggered when that key is pressed in the
2742# find string entry widget.
2743proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002744 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002745 bind . $ev $script
2746 set escript [bind Entry $ev]
2747 if {$escript == {}} {
2748 set escript [bind Entry <Key>]
2749 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002750 foreach e $entries {
2751 bind $e $ev "$escript; break"
2752 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002753}
2754
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002755proc bindmodfunctionkey {mod n script} {
2756 bind . <$mod-F$n> $script
2757 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2758}
2759
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002760# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002761# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002762proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002763 global ctext entries
2764 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002765 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002766 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002767 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002768}
2769
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002770# Adjust the progress bar for a change in requested extent or canvas size
2771proc adjustprogress {} {
2772 global progresscanv progressitem progresscoords
2773 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002774 global rprogitem rprogcoord use_ttk
2775
2776 if {$use_ttk} {
2777 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2778 return
2779 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002780
2781 set w [expr {[winfo width $progresscanv] - 4}]
2782 set x0 [expr {$w * [lindex $progresscoords 0]}]
2783 set x1 [expr {$w * [lindex $progresscoords 1]}]
2784 set h [winfo height $progresscanv]
2785 $progresscanv coords $progressitem $x0 0 $x1 $h
2786 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002787 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002788 set now [clock clicks -milliseconds]
2789 if {$now >= $lastprogupdate + 100} {
2790 set progupdatepending 0
2791 update
2792 } elseif {!$progupdatepending} {
2793 set progupdatepending 1
2794 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2795 }
2796}
2797
2798proc doprogupdate {} {
2799 global lastprogupdate progupdatepending
2800
2801 if {$progupdatepending} {
2802 set progupdatepending 0
2803 set lastprogupdate [clock clicks -milliseconds]
2804 update
2805 }
2806}
2807
Max Kirilloveaf7e832015-03-04 05:58:18 +02002808proc config_check_tmp_exists {tries_left} {
2809 global config_file_tmp
2810
2811 if {[file exists $config_file_tmp]} {
2812 incr tries_left -1
2813 if {$tries_left > 0} {
2814 after 100 [list config_check_tmp_exists $tries_left]
2815 } else {
2816 error_popup "There appears to be a stale $config_file_tmp\
2817 file, which will prevent gitk from saving its configuration on exit.\
2818 Please remove it if it is not being used by any existing gitk process."
2819 }
2820 }
2821}
2822
Max Kirillov995f7922015-03-04 05:58:16 +02002823proc config_init_trace {name} {
2824 global config_variable_changed config_variable_original
2825
2826 upvar #0 $name var
2827 set config_variable_changed($name) 0
2828 set config_variable_original($name) $var
2829}
2830
2831proc config_variable_change_cb {name name2 op} {
2832 global config_variable_changed config_variable_original
2833
2834 upvar #0 $name var
2835 if {$op eq "write" &&
2836 (![info exists config_variable_original($name)] ||
2837 $config_variable_original($name) ne $var)} {
2838 set config_variable_changed($name) 1
2839 }
2840}
2841
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002842proc savestuff {w} {
Max Kirillov9fabefb2014-09-14 23:35:57 +03002843 global stuffsaved
Astril Hayato8f863392014-01-21 19:10:16 +00002844 global config_file config_file_tmp
Max Kirillov995f7922015-03-04 05:58:16 +02002845 global config_variables config_variable_changed
2846 global viewchanged
2847
2848 upvar #0 viewname current_viewname
2849 upvar #0 viewfiles current_viewfiles
2850 upvar #0 viewargs current_viewargs
2851 upvar #0 viewargscmd current_viewargscmd
2852 upvar #0 viewperm current_viewperm
2853 upvar #0 nextviewnum current_nextviewnum
2854 upvar #0 use_ttk current_use_ttk
Paul Mackerras4ef17532005-07-27 22:16:51 -05002855
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002856 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002857 if {![winfo viewable .]} return
Max Kirilloveaf7e832015-03-04 05:58:18 +02002858 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002859 if {[catch {
Max Kirilloveaf7e832015-03-04 05:58:18 +02002860 set try_count 0
2861 while {[catch {set f [open $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2862 if {[incr try_count] > 50} {
2863 error "Unable to write config file: $config_file_tmp exists"
2864 }
2865 after 100
Astril Hayato8f863392014-01-21 19:10:16 +00002866 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002867 set remove_tmp 1
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002868 if {$::tcl_platform(platform) eq {windows}} {
Astril Hayato8f863392014-01-21 19:10:16 +00002869 file attributes $config_file_tmp -hidden true
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002870 }
Max Kirillov995f7922015-03-04 05:58:16 +02002871 if {[file exists $config_file]} {
2872 source $config_file
2873 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002874 foreach var_name $config_variables {
2875 upvar #0 $var_name var
Max Kirillov995f7922015-03-04 05:58:16 +02002876 upvar 0 $var_name old_var
2877 if {!$config_variable_changed($var_name) && [info exists old_var]} {
2878 puts $f [list set $var_name $old_var]
2879 } else {
2880 puts $f [list set $var_name $var]
2881 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002882 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002883
Mark Levedahlb6047c52007-02-08 22:22:24 -05002884 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002885 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002886 puts $f "set geometry(topwidth) [winfo width .tf]"
2887 puts $f "set geometry(topheight) [winfo height .tf]"
Max Kirillov995f7922015-03-04 05:58:16 +02002888 if {$current_use_ttk} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002889 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2890 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2891 } else {
2892 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2893 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2894 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002895 puts $f "set geometry(botwidth) [winfo width .bleft]"
2896 puts $f "set geometry(botheight) [winfo height .bleft]"
2897
Max Kirillov995f7922015-03-04 05:58:16 +02002898 array set view_save {}
2899 array set views {}
2900 if {![info exists permviews]} { set permviews {} }
2901 foreach view $permviews {
2902 set view_save([lindex $view 0]) 1
2903 set views([lindex $view 0]) $view
2904 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002905 puts -nonewline $f "set permviews {"
Max Kirillov995f7922015-03-04 05:58:16 +02002906 for {set v 1} {$v < $current_nextviewnum} {incr v} {
2907 if {$viewchanged($v)} {
2908 if {$current_viewperm($v)} {
2909 set views($current_viewname($v)) [list $current_viewname($v) $current_viewfiles($v) $current_viewargs($v) $current_viewargscmd($v)]
2910 } else {
2911 set view_save($current_viewname($v)) 0
2912 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002913 }
2914 }
Max Kirillov995f7922015-03-04 05:58:16 +02002915 # write old and updated view to their places and append remaining to the end
2916 foreach view $permviews {
2917 set view_name [lindex $view 0]
2918 if {$view_save($view_name)} {
2919 puts $f "{$views($view_name)}"
2920 }
2921 unset views($view_name)
2922 }
2923 foreach view_name [array names views] {
2924 puts $f "{$views($view_name)}"
2925 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002926 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002927 close $f
Astril Hayato8f863392014-01-21 19:10:16 +00002928 file rename -force $config_file_tmp $config_file
Max Kirilloveaf7e832015-03-04 05:58:18 +02002929 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002930 } err]} {
2931 puts "Error saving config: $err"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002932 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002933 if {$remove_tmp} {
2934 file delete -force $config_file_tmp
2935 }
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002936 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002937}
2938
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002939proc resizeclistpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002940 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002941 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002942 if {$use_ttk} {
2943 set s0 [$win sashpos 0]
2944 set s1 [$win sashpos 1]
2945 } else {
2946 set s0 [$win sash coord 0]
2947 set s1 [$win sash coord 1]
2948 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002949 if {$w < 60} {
2950 set sash0 [expr {int($w/2 - 2)}]
2951 set sash1 [expr {int($w*5/6 - 2)}]
2952 } else {
2953 set factor [expr {1.0 * $w / $oldwidth($win)}]
2954 set sash0 [expr {int($factor * [lindex $s0 0])}]
2955 set sash1 [expr {int($factor * [lindex $s1 0])}]
2956 if {$sash0 < 30} {
2957 set sash0 30
2958 }
2959 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002960 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002961 }
2962 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002963 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002964 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002965 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002966 }
2967 }
2968 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002969 if {$use_ttk} {
2970 $win sashpos 0 $sash0
2971 $win sashpos 1 $sash1
2972 } else {
2973 $win sash place 0 $sash0 [lindex $s0 1]
2974 $win sash place 1 $sash1 [lindex $s1 1]
2975 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002976 }
2977 set oldwidth($win) $w
2978}
2979
2980proc resizecdetpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002981 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002982 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002983 if {$use_ttk} {
2984 set s0 [$win sashpos 0]
2985 } else {
2986 set s0 [$win sash coord 0]
2987 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002988 if {$w < 60} {
2989 set sash0 [expr {int($w*3/4 - 2)}]
2990 } else {
2991 set factor [expr {1.0 * $w / $oldwidth($win)}]
2992 set sash0 [expr {int($factor * [lindex $s0 0])}]
2993 if {$sash0 < 45} {
2994 set sash0 45
2995 }
2996 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002997 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002998 }
2999 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003000 if {$use_ttk} {
3001 $win sashpos 0 $sash0
3002 } else {
3003 $win sash place 0 $sash0 [lindex $s0 1]
3004 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003005 }
3006 set oldwidth($win) $w
3007}
3008
Paul Mackerrasb5721c72005-05-10 12:08:22 +00003009proc allcanvs args {
3010 global canv canv2 canv3
3011 eval $canv $args
3012 eval $canv2 $args
3013 eval $canv3 $args
3014}
3015
3016proc bindall {event action} {
3017 global canv canv2 canv3
3018 bind $canv $event $action
3019 bind $canv2 $event $action
3020 bind $canv3 $event $action
3021}
3022
Paul Mackerras9a40c502005-05-12 23:46:16 +00003023proc about {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003024 global bgcolor NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00003025 set w .about
3026 if {[winfo exists $w]} {
3027 raise $w
3028 return
3029 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003030 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003031 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003032 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01003033 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003034Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00003035
Paul Mackerras6c626a02014-01-21 22:02:27 +11003036Copyright \u00a9 2005-2014 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00003037
Christian Stimmingd990ced2007-11-07 18:42:55 +01003038Use and redistribute under the terms of the GNU General Public License"] \
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003039 -justify center -aspect 400 -border 2 -bg $bgcolor -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003040 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003041 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00003042 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003043 bind $w <Visibility> "focus $w.ok"
3044 bind $w <Key-Escape> "destroy $w"
3045 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01003046 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00003047}
3048
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003049proc keys {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003050 global bgcolor NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003051 set w .keys
3052 if {[winfo exists $w]} {
3053 raise $w
3054 return
3055 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003056 if {[tk windowingsystem] eq {aqua}} {
3057 set M1T Cmd
3058 } else {
3059 set M1T Ctrl
3060 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003061 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003062 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003063 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003064 message $w.m -text "
3065[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003066
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003067[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01003068[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003069[mc "<Home> Move to first commit"]
3070[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05003071[mc "<Up>, p, k Move up one commit"]
3072[mc "<Down>, n, j Move down one commit"]
3073[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003074[mc "<Right>, x, l Go forward in history list"]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03003075[mc "<%s-n> Go to n-th parent of current commit in history list" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003076[mc "<PageUp> Move up one page in commit list"]
3077[mc "<PageDown> Move down one page in commit list"]
3078[mc "<%s-Home> Scroll to top of commit list" $M1T]
3079[mc "<%s-End> Scroll to bottom of commit list" $M1T]
3080[mc "<%s-Up> Scroll commit list up one line" $M1T]
3081[mc "<%s-Down> Scroll commit list down one line" $M1T]
3082[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
3083[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
3084[mc "<Shift-Up> Find backwards (upwards, later commits)"]
3085[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
3086[mc "<Delete>, b Scroll diff view up one page"]
3087[mc "<Backspace> Scroll diff view up one page"]
3088[mc "<Space> Scroll diff view down one page"]
3089[mc "u Scroll diff view up 18 lines"]
3090[mc "d Scroll diff view down 18 lines"]
3091[mc "<%s-F> Find" $M1T]
3092[mc "<%s-G> Move to next find hit" $M1T]
3093[mc "<Return> Move to next find hit"]
Ismael Luceno0deb5c92015-04-15 13:18:17 -03003094[mc "g Go to commit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01003095[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003096[mc "? Move to previous find hit"]
3097[mc "f Scroll diff view to next file"]
3098[mc "<%s-S> Search for next hit in diff view" $M1T]
3099[mc "<%s-R> Search for previous hit in diff view" $M1T]
3100[mc "<%s-KP+> Increase font size" $M1T]
3101[mc "<%s-plus> Increase font size" $M1T]
3102[mc "<%s-KP-> Decrease font size" $M1T]
3103[mc "<%s-minus> Decrease font size" $M1T]
3104[mc "<F5> Update"]
3105" \
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003106 -justify left -bg $bgcolor -border 2 -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003107 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003108 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003109 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003110 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003111 bind $w <Visibility> "focus $w.ok"
3112 bind $w <Key-Escape> "destroy $w"
3113 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003114}
3115
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003116# Procedures for manipulating the file list window at the
3117# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003118
3119proc treeview {w l openlevs} {
3120 global treecontents treediropen treeheight treeparent treeindex
3121
3122 set ix 0
3123 set treeindex() 0
3124 set lev 0
3125 set prefix {}
3126 set prefixend -1
3127 set prefendstack {}
3128 set htstack {}
3129 set ht 0
3130 set treecontents() {}
3131 $w conf -state normal
3132 foreach f $l {
3133 while {[string range $f 0 $prefixend] ne $prefix} {
3134 if {$lev <= $openlevs} {
3135 $w mark set e:$treeindex($prefix) "end -1c"
3136 $w mark gravity e:$treeindex($prefix) left
3137 }
3138 set treeheight($prefix) $ht
3139 incr ht [lindex $htstack end]
3140 set htstack [lreplace $htstack end end]
3141 set prefixend [lindex $prefendstack end]
3142 set prefendstack [lreplace $prefendstack end end]
3143 set prefix [string range $prefix 0 $prefixend]
3144 incr lev -1
3145 }
3146 set tail [string range $f [expr {$prefixend+1}] end]
3147 while {[set slash [string first "/" $tail]] >= 0} {
3148 lappend htstack $ht
3149 set ht 0
3150 lappend prefendstack $prefixend
3151 incr prefixend [expr {$slash + 1}]
3152 set d [string range $tail 0 $slash]
3153 lappend treecontents($prefix) $d
3154 set oldprefix $prefix
3155 append prefix $d
3156 set treecontents($prefix) {}
3157 set treeindex($prefix) [incr ix]
3158 set treeparent($prefix) $oldprefix
3159 set tail [string range $tail [expr {$slash+1}] end]
3160 if {$lev <= $openlevs} {
3161 set ht 1
3162 set treediropen($prefix) [expr {$lev < $openlevs}]
3163 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3164 $w mark set d:$ix "end -1c"
3165 $w mark gravity d:$ix left
3166 set str "\n"
3167 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3168 $w insert end $str
3169 $w image create end -align center -image $bm -padx 1 \
3170 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10003171 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003172 $w mark set s:$ix "end -1c"
3173 $w mark gravity s:$ix left
3174 }
3175 incr lev
3176 }
3177 if {$tail ne {}} {
3178 if {$lev <= $openlevs} {
3179 incr ht
3180 set str "\n"
3181 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3182 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003183 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003184 }
3185 lappend treecontents($prefix) $tail
3186 }
3187 }
3188 while {$htstack ne {}} {
3189 set treeheight($prefix) $ht
3190 incr ht [lindex $htstack end]
3191 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05003192 set prefixend [lindex $prefendstack end]
3193 set prefendstack [lreplace $prefendstack end end]
3194 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003195 }
3196 $w conf -state disabled
3197}
3198
3199proc linetoelt {l} {
3200 global treeheight treecontents
3201
3202 set y 2
3203 set prefix {}
3204 while {1} {
3205 foreach e $treecontents($prefix) {
3206 if {$y == $l} {
3207 return "$prefix$e"
3208 }
3209 set n 1
3210 if {[string index $e end] eq "/"} {
3211 set n $treeheight($prefix$e)
3212 if {$y + $n > $l} {
3213 append prefix $e
3214 incr y
3215 break
3216 }
3217 }
3218 incr y $n
3219 }
3220 }
3221}
3222
Paul Mackerras45a9d502006-05-20 22:56:27 +10003223proc highlight_tree {y prefix} {
3224 global treeheight treecontents cflist
3225
3226 foreach e $treecontents($prefix) {
3227 set path $prefix$e
3228 if {[highlight_tag $path] ne {}} {
3229 $cflist tag add bold $y.0 "$y.0 lineend"
3230 }
3231 incr y
3232 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3233 set y [highlight_tree $y $path]
3234 }
3235 }
3236 return $y
3237}
3238
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003239proc treeclosedir {w dir} {
3240 global treediropen treeheight treeparent treeindex
3241
3242 set ix $treeindex($dir)
3243 $w conf -state normal
3244 $w delete s:$ix e:$ix
3245 set treediropen($dir) 0
3246 $w image configure a:$ix -image tri-rt
3247 $w conf -state disabled
3248 set n [expr {1 - $treeheight($dir)}]
3249 while {$dir ne {}} {
3250 incr treeheight($dir) $n
3251 set dir $treeparent($dir)
3252 }
3253}
3254
3255proc treeopendir {w dir} {
3256 global treediropen treeheight treeparent treecontents treeindex
3257
3258 set ix $treeindex($dir)
3259 $w conf -state normal
3260 $w image configure a:$ix -image tri-dn
3261 $w mark set e:$ix s:$ix
3262 $w mark gravity e:$ix right
3263 set lev 0
3264 set str "\n"
3265 set n [llength $treecontents($dir)]
3266 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
3267 incr lev
3268 append str "\t"
3269 incr treeheight($x) $n
3270 }
3271 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003272 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003273 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003274 set iy $treeindex($de)
3275 $w mark set d:$iy e:$ix
3276 $w mark gravity d:$iy left
3277 $w insert e:$ix $str
3278 set treediropen($de) 0
3279 $w image create e:$ix -align center -image tri-rt -padx 1 \
3280 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10003281 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003282 $w mark set s:$iy e:$ix
3283 $w mark gravity s:$iy left
3284 set treeheight($de) 1
3285 } else {
3286 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003287 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003288 }
3289 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003290 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003291 $w conf -state disabled
3292 set treediropen($dir) 1
3293 set top [lindex [split [$w index @0,0] .] 0]
3294 set ht [$w cget -height]
3295 set l [lindex [split [$w index s:$ix] .] 0]
3296 if {$l < $top} {
3297 $w yview $l.0
3298 } elseif {$l + $n + 1 > $top + $ht} {
3299 set top [expr {$l + $n + 2 - $ht}]
3300 if {$l < $top} {
3301 set top $l
3302 }
3303 $w yview $top.0
3304 }
3305}
3306
3307proc treeclick {w x y} {
3308 global treediropen cmitmode ctext cflist cflist_top
3309
3310 if {$cmitmode ne "tree"} return
3311 if {![info exists cflist_top]} return
3312 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3313 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3314 $cflist tag add highlight $l.0 "$l.0 lineend"
3315 set cflist_top $l
3316 if {$l == 1} {
3317 $ctext yview 1.0
3318 return
3319 }
3320 set e [linetoelt $l]
3321 if {[string index $e end] ne "/"} {
3322 showfile $e
3323 } elseif {$treediropen($e)} {
3324 treeclosedir $w $e
3325 } else {
3326 treeopendir $w $e
3327 }
3328}
3329
3330proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003331 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003332
3333 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003334 if {$jump_to_here ne {}} {
3335 set f [lindex $jump_to_here 0]
3336 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3337 showfile $f
3338 }
3339 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003340}
3341
3342image create bitmap tri-rt -background black -foreground blue -data {
3343 #define tri-rt_width 13
3344 #define tri-rt_height 13
3345 static unsigned char tri-rt_bits[] = {
3346 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3347 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3348 0x00, 0x00};
3349} -maskdata {
3350 #define tri-rt-mask_width 13
3351 #define tri-rt-mask_height 13
3352 static unsigned char tri-rt-mask_bits[] = {
3353 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3354 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3355 0x08, 0x00};
3356}
3357image create bitmap tri-dn -background black -foreground blue -data {
3358 #define tri-dn_width 13
3359 #define tri-dn_height 13
3360 static unsigned char tri-dn_bits[] = {
3361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3362 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3363 0x00, 0x00};
3364} -maskdata {
3365 #define tri-dn-mask_width 13
3366 #define tri-dn-mask_height 13
3367 static unsigned char tri-dn-mask_bits[] = {
3368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3369 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3370 0x00, 0x00};
3371}
3372
Paul Mackerras887c9962007-08-20 19:36:20 +10003373image create bitmap reficon-T -background black -foreground yellow -data {
3374 #define tagicon_width 13
3375 #define tagicon_height 9
3376 static unsigned char tagicon_bits[] = {
3377 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3378 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3379} -maskdata {
3380 #define tagicon-mask_width 13
3381 #define tagicon-mask_height 9
3382 static unsigned char tagicon-mask_bits[] = {
3383 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3384 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3385}
3386set rectdata {
3387 #define headicon_width 13
3388 #define headicon_height 9
3389 static unsigned char headicon_bits[] = {
3390 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3391 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3392}
3393set rectmask {
3394 #define headicon-mask_width 13
3395 #define headicon-mask_height 9
3396 static unsigned char headicon-mask_bits[] = {
3397 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3398 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3399}
YOKOTA Hiroshi66db14c2015-10-25 01:58:41 +09003400image create bitmap reficon-H -background black -foreground lime \
Paul Mackerras887c9962007-08-20 19:36:20 +10003401 -data $rectdata -maskdata $rectmask
3402image create bitmap reficon-o -background black -foreground "#ddddff" \
3403 -data $rectdata -maskdata $rectmask
3404
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003405proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003406 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003407
3408 $cflist conf -state normal
3409 $cflist delete 0.0 end
3410 if {$first ne {}} {
3411 $cflist insert end $first
3412 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003413 $cflist tag add highlight 1.0 "1.0 lineend"
3414 } else {
Paul Mackerras009409f2015-05-02 20:53:36 +10003415 unset -nocomplain cflist_top
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003416 }
3417 $cflist conf -state disabled
3418 set difffilestart {}
3419}
3420
Paul Mackerras63b79192006-05-20 21:31:52 +10003421proc highlight_tag {f} {
3422 global highlight_paths
3423
3424 foreach p $highlight_paths {
3425 if {[string match $p $f]} {
3426 return "bold"
3427 }
3428 }
3429 return {}
3430}
3431
3432proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003433 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003434
Paul Mackerras45a9d502006-05-20 22:56:27 +10003435 $cflist conf -state normal
3436 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003437 set end [lindex [split [$cflist index end] .] 0]
3438 for {set l 2} {$l < $end} {incr l} {
3439 set line [$cflist get $l.0 "$l.0 lineend"]
3440 if {[highlight_tag $line] ne {}} {
3441 $cflist tag add bold $l.0 "$l.0 lineend"
3442 }
3443 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003444 } else {
3445 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003446 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003447 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003448}
3449
3450proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003451 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003452
Paul Mackerras45a9d502006-05-20 22:56:27 +10003453 $cflist conf -state normal
3454 $cflist tag remove bold 1.0 end
3455 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003456}
3457
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003458proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003459 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003460
Paul Mackerras45a9d502006-05-20 22:56:27 +10003461 $cflist conf -state normal
3462 foreach f $fl {
3463 $cflist insert end "\n"
3464 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003465 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003466 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003467}
3468
3469proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003470 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003471
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003472 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003473 if {![info exists cflist_top]} return
3474 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003475 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3476 $cflist tag add highlight $l.0 "$l.0 lineend"
3477 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003478 if {$l == 1} {
3479 $ctext yview 1.0
3480 } else {
3481 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003482 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003483 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003484}
3485
Paul Mackerras32447292007-07-27 22:30:15 +10003486proc pop_flist_menu {w X Y x y} {
3487 global ctext cflist cmitmode flist_menu flist_menu_file
3488 global treediffs diffids
3489
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003490 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003491 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3492 if {$l <= 1} return
3493 if {$cmitmode eq "tree"} {
3494 set e [linetoelt $l]
3495 if {[string index $e end] eq "/"} return
3496 } else {
3497 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3498 }
3499 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003500 set xdiffstate "normal"
3501 if {$cmitmode eq "tree"} {
3502 set xdiffstate "disabled"
3503 }
3504 # Disable "External diff" item in tree mode
3505 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003506 tk_popup $flist_menu $X $Y
3507}
3508
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003509proc find_ctext_fileinfo {line} {
3510 global ctext_file_names ctext_file_lines
3511
3512 set ok [bsearch $ctext_file_lines $line]
3513 set tline [lindex $ctext_file_lines $ok]
3514
3515 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3516 return {}
3517 } else {
3518 return [list [lindex $ctext_file_names $ok] $tline]
3519 }
3520}
3521
3522proc pop_diff_menu {w X Y x y} {
3523 global ctext diff_menu flist_menu_file
3524 global diff_menu_txtpos diff_menu_line
3525 global diff_menu_filebase
3526
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003527 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3528 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003529 # don't pop up the menu on hunk-separator or file-separator lines
3530 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3531 return
3532 }
3533 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003534 set f [find_ctext_fileinfo $diff_menu_line]
3535 if {$f eq {}} return
3536 set flist_menu_file [lindex $f 0]
3537 set diff_menu_filebase [lindex $f 1]
3538 tk_popup $diff_menu $X $Y
3539}
3540
Paul Mackerras32447292007-07-27 22:30:15 +10003541proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003542 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003543
3544 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003545 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003546 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003547 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003548 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003549 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003550 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003551}
3552
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003553proc gitknewtmpdir {} {
David Aguilarc7664f12014-06-13 14:13:37 -07003554 global diffnum gitktmpdir gitdir env
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003555
3556 if {![info exists gitktmpdir]} {
David Aguilarc7664f12014-06-13 14:13:37 -07003557 if {[info exists env(GITK_TMPDIR)]} {
3558 set tmpdir $env(GITK_TMPDIR)
3559 } elseif {[info exists env(TMPDIR)]} {
3560 set tmpdir $env(TMPDIR)
3561 } else {
3562 set tmpdir $gitdir
3563 }
David Aguilar105b5d32014-06-13 14:43:48 -07003564 set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
David Aguilarac54a4b2014-06-18 19:53:14 -07003565 if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
3566 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
3567 }
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003568 if {[catch {file mkdir $gitktmpdir} err]} {
3569 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3570 unset gitktmpdir
3571 return {}
3572 }
3573 set diffnum 0
3574 }
3575 incr diffnum
3576 set diffdir [file join $gitktmpdir $diffnum]
3577 if {[catch {file mkdir $diffdir} err]} {
3578 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3579 return {}
3580 }
3581 return $diffdir
3582}
3583
Thomas Arcila314f5de2008-03-24 12:55:36 +01003584proc save_file_from_commit {filename output what} {
3585 global nullfile
3586
3587 if {[catch {exec git show $filename -- > $output} err]} {
3588 if {[string match "fatal: bad revision *" $err]} {
3589 return $nullfile
3590 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003591 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003592 return {}
3593 }
3594 return $output
3595}
3596
3597proc external_diff_get_one_file {diffid filename diffdir} {
3598 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003599 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003600
3601 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003602 set difffile [file join $worktree $filename]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003603 if {[file exists $difffile]} {
3604 return $difffile
3605 }
3606 return $nullfile
3607 }
3608 if {$diffid == $nullid2} {
3609 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3610 return [save_file_from_commit :$filename $difffile index]
3611 }
3612 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3613 return [save_file_from_commit $diffid:$filename $difffile \
3614 "revision $diffid"]
3615}
3616
3617proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003618 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003619 global flist_menu_file
3620 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003621 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003622
3623 if {[llength $diffids] == 1} {
3624 # no reference commit given
3625 set diffidto [lindex $diffids 0]
3626 if {$diffidto eq $nullid} {
3627 # diffing working copy with index
3628 set diffidfrom $nullid2
3629 } elseif {$diffidto eq $nullid2} {
3630 # diffing index with HEAD
3631 set diffidfrom "HEAD"
3632 } else {
3633 # use first parent commit
3634 global parentlist selectedline
3635 set diffidfrom [lindex $parentlist $selectedline 0]
3636 }
3637 } else {
3638 set diffidfrom [lindex $diffids 0]
3639 set diffidto [lindex $diffids 1]
3640 }
3641
3642 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003643 set diffdir [gitknewtmpdir]
3644 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003645
3646 # gather files to diff
3647 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3648 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3649
3650 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003651 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3652 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003653 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003654 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003655 } else {
3656 fconfigure $fl -blocking 0
3657 filerun $fl [list delete_at_eof $fl $diffdir]
3658 }
3659 }
3660}
3661
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003662proc find_hunk_blamespec {base line} {
3663 global ctext
3664
3665 # Find and parse the hunk header
3666 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3667 if {$s_lix eq {}} return
3668
3669 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3670 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3671 s_line old_specs osz osz1 new_line nsz]} {
3672 return
3673 }
3674
3675 # base lines for the parents
3676 set base_lines [list $new_line]
3677 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3678 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3679 old_spec old_line osz]} {
3680 return
3681 }
3682 lappend base_lines $old_line
3683 }
3684
3685 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003686 set max_parent [expr {[llength $base_lines]-2}]
3687 set dline 0
3688 set s_lno [lindex [split $s_lix "."] 0]
3689
Paul Mackerras190ec522008-10-27 21:13:37 +11003690 # Determine if the line is removed
3691 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3692 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003693 set removed_idx [string first "-" $chunk]
3694 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003695 if {$removed_idx >= 0} {
3696 set parent $removed_idx
3697 } else {
3698 set unchanged_idx [string first " " $chunk]
3699 if {$unchanged_idx >= 0} {
3700 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003701 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003702 # blame the current commit
3703 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003704 }
3705 }
3706 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003707 for {set i $line} {[incr i -1] > $s_lno} {} {
3708 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3709 # Determine if the line is removed
3710 set removed_idx [string first "-" $chunk]
3711 if {$parent >= 0} {
3712 set code [string index $chunk $parent]
3713 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3714 incr dline
3715 }
3716 } else {
3717 if {$removed_idx < 0} {
3718 incr dline
3719 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003720 }
3721 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003722 incr parent
3723 } else {
3724 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003725 }
3726
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003727 incr dline [lindex $base_lines $parent]
3728 return [list $parent $dline]
3729}
3730
3731proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003732 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003733 global diff_menu_txtpos diff_menu_line
3734 global diff_menu_filebase flist_menu_file
3735
3736 if {$cmitmode eq "tree"} {
3737 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003738 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003739 } else {
3740 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3741 if {$hinfo ne {}} {
3742 set parent_idx [lindex $hinfo 0]
3743 set line [lindex $hinfo 1]
3744 } else {
3745 set parent_idx 0
3746 set line 0
3747 }
3748 }
3749
3750 external_blame $parent_idx $line
3751}
3752
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003753# Find the SHA1 ID of the blob for file $fname in the index
3754# at stage 0 or 2
3755proc index_sha1 {fname} {
3756 set f [open [list | git ls-files -s $fname] r]
3757 while {[gets $f line] >= 0} {
3758 set info [lindex [split $line "\t"] 0]
3759 set stage [lindex $info 2]
3760 if {$stage eq "0" || $stage eq "2"} {
3761 close $f
3762 return [lindex $info 1]
3763 }
3764 }
3765 close $f
3766 return {}
3767}
3768
Paul Mackerras9712b812008-12-06 21:44:05 +11003769# Turn an absolute path into one relative to the current directory
3770proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003771 if {[file pathtype $f] eq "relative"} {
3772 return $f
3773 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003774 set elts [file split $f]
3775 set here [file split [pwd]]
3776 set ei 0
3777 set hi 0
3778 set res {}
3779 foreach d $here {
3780 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3781 lappend res ".."
3782 } else {
3783 incr ei
3784 }
3785 incr hi
3786 }
3787 set elts [concat $res [lrange $elts $ei end]]
3788 return [eval file join $elts]
3789}
3790
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003791proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003792 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003793 global nullid nullid2
3794 global parentlist selectedline currentid
3795
3796 if {$parent_idx > 0} {
3797 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3798 } else {
3799 set base_commit $currentid
3800 }
3801
3802 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3803 error_popup [mc "No such commit"]
3804 return
3805 }
3806
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003807 set cmdline [list git gui blame]
3808 if {$line ne {} && $line > 1} {
3809 lappend cmdline "--line=$line"
3810 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003811 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003812 # Unfortunately it seems git gui blame doesn't like
3813 # being given an absolute path...
3814 set f [make_relative $f]
3815 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003816 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003817 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003818 }
3819}
3820
Paul Mackerras8a897742008-10-27 21:36:25 +11003821proc show_line_source {} {
3822 global cmitmode currentid parents curview blamestuff blameinst
3823 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003824 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003825
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003826 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003827 if {$cmitmode eq "tree"} {
3828 set id $currentid
3829 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3830 } else {
3831 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3832 if {$h eq {}} return
3833 set pi [lindex $h 0]
3834 if {$pi == 0} {
3835 mark_ctext_line $diff_menu_line
3836 return
3837 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003838 incr pi -1
3839 if {$currentid eq $nullid} {
3840 if {$pi > 0} {
3841 # must be a merge in progress...
3842 if {[catch {
3843 # get the last line from .git/MERGE_HEAD
3844 set f [open [file join $gitdir MERGE_HEAD] r]
3845 set id [lindex [split [read $f] "\n"] end-1]
3846 close $f
3847 } err]} {
3848 error_popup [mc "Couldn't read merge head: %s" $err]
3849 return
3850 }
3851 } elseif {$parents($curview,$currentid) eq $nullid2} {
3852 # need to do the blame from the index
3853 if {[catch {
3854 set from_index [index_sha1 $flist_menu_file]
3855 } err]} {
3856 error_popup [mc "Error reading index: %s" $err]
3857 return
3858 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003859 } else {
3860 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003861 }
3862 } else {
3863 set id [lindex $parents($curview,$currentid) $pi]
3864 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003865 set line [lindex $h 1]
3866 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003867 set blameargs {}
3868 if {$from_index ne {}} {
3869 lappend blameargs | git cat-file blob $from_index
3870 }
3871 lappend blameargs | git blame -p -L$line,+1
3872 if {$from_index ne {}} {
3873 lappend blameargs --contents -
3874 } else {
3875 lappend blameargs $id
3876 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003877 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003878 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003879 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003880 } err]} {
3881 error_popup [mc "Couldn't start git blame: %s" $err]
3882 return
3883 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003884 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003885 fconfigure $f -blocking 0
3886 set i [reg_instance $f]
3887 set blamestuff($i) {}
3888 set blameinst $i
3889 filerun $f [list read_line_source $f $i]
3890}
3891
3892proc stopblaming {} {
3893 global blameinst
3894
3895 if {[info exists blameinst]} {
3896 stop_instance $blameinst
3897 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003898 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003899 }
3900}
3901
3902proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003903 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003904
3905 while {[gets $fd line] >= 0} {
3906 lappend blamestuff($inst) $line
3907 }
3908 if {![eof $fd]} {
3909 return 1
3910 }
3911 unset commfd($inst)
3912 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003913 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003914 fconfigure $fd -blocking 1
3915 if {[catch {close $fd} err]} {
3916 error_popup [mc "Error running git blame: %s" $err]
3917 return 0
3918 }
3919
3920 set fname {}
3921 set line [split [lindex $blamestuff($inst) 0] " "]
3922 set id [lindex $line 0]
3923 set lnum [lindex $line 1]
3924 if {[string length $id] == 40 && [string is xdigit $id] &&
3925 [string is digit -strict $lnum]} {
3926 # look for "filename" line
3927 foreach l $blamestuff($inst) {
3928 if {[string match "filename *" $l]} {
3929 set fname [string range $l 9 end]
3930 break
3931 }
3932 }
3933 }
3934 if {$fname ne {}} {
3935 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003936 if {$id eq $nullid} {
3937 # blame uses all-zeroes to mean not committed,
3938 # which would mean a change in the index
3939 set id $nullid2
3940 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003941 if {[commitinview $id $curview]} {
Max Kirillov4135d362014-04-05 23:38:50 +03003942 selectline [rowofcommit $id] 1 [list $fname $lnum] 1
Paul Mackerras8a897742008-10-27 21:36:25 +11003943 } else {
3944 error_popup [mc "That line comes from commit %s, \
3945 which is not in this view" [shortids $id]]
3946 }
3947 } else {
3948 puts "oops couldn't parse git blame output"
3949 }
3950 return 0
3951}
3952
Thomas Arcila314f5de2008-03-24 12:55:36 +01003953# delete $dir when we see eof on $f (presumably because the child has exited)
3954proc delete_at_eof {f dir} {
3955 while {[gets $f line] >= 0} {}
3956 if {[eof $f]} {
3957 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003958 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003959 }
3960 file delete -force $dir
3961 return 0
3962 }
3963 return 1
3964}
3965
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003966# Functions for adding and removing shell-type quoting
3967
3968proc shellquote {str} {
3969 if {![string match "*\['\"\\ \t]*" $str]} {
3970 return $str
3971 }
3972 if {![string match "*\['\"\\]*" $str]} {
3973 return "\"$str\""
3974 }
3975 if {![string match "*'*" $str]} {
3976 return "'$str'"
3977 }
3978 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3979}
3980
3981proc shellarglist {l} {
3982 set str {}
3983 foreach a $l {
3984 if {$str ne {}} {
3985 append str " "
3986 }
3987 append str [shellquote $a]
3988 }
3989 return $str
3990}
3991
3992proc shelldequote {str} {
3993 set ret {}
3994 set used -1
3995 while {1} {
3996 incr used
3997 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3998 append ret [string range $str $used end]
3999 set used [string length $str]
4000 break
4001 }
4002 set first [lindex $first 0]
4003 set ch [string index $str $first]
4004 if {$first > $used} {
4005 append ret [string range $str $used [expr {$first - 1}]]
4006 set used $first
4007 }
4008 if {$ch eq " " || $ch eq "\t"} break
4009 incr used
4010 if {$ch eq "'"} {
4011 set first [string first "'" $str $used]
4012 if {$first < 0} {
4013 error "unmatched single-quote"
4014 }
4015 append ret [string range $str $used [expr {$first - 1}]]
4016 set used $first
4017 continue
4018 }
4019 if {$ch eq "\\"} {
4020 if {$used >= [string length $str]} {
4021 error "trailing backslash"
4022 }
4023 append ret [string index $str $used]
4024 continue
4025 }
4026 # here ch == "\""
4027 while {1} {
4028 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
4029 error "unmatched double-quote"
4030 }
4031 set first [lindex $first 0]
4032 set ch [string index $str $first]
4033 if {$first > $used} {
4034 append ret [string range $str $used [expr {$first - 1}]]
4035 set used $first
4036 }
4037 if {$ch eq "\""} break
4038 incr used
4039 append ret [string index $str $used]
4040 incr used
4041 }
4042 }
4043 return [list $used $ret]
4044}
4045
4046proc shellsplit {str} {
4047 set l {}
4048 while {1} {
4049 set str [string trimleft $str]
4050 if {$str eq {}} break
4051 set dq [shelldequote $str]
4052 set n [lindex $dq 0]
4053 set word [lindex $dq 1]
4054 set str [string range $str $n end]
4055 lappend l $word
4056 }
4057 return $l
4058}
4059
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004060proc set_window_title {} {
4061 global appname curview viewname vrevs
4062 set rev [mc "All files"]
4063 if {$curview ne 0} {
4064 if {$viewname($curview) eq [mc "Command line"]} {
4065 set rev [string map {"--gitk-symmetric-diff-marker" "--merge"} $vrevs($curview)]
4066 } else {
4067 set rev $viewname($curview)
4068 }
4069 }
4070 wm title . "[reponame]: $rev - $appname"
4071}
4072
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004073# Code to implement multiple views
4074
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004075proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004076 global nextviewnum newviewname newishighlight
4077 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004078
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004079 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004080 set top .gitkview
4081 if {[winfo exists $top]} {
4082 raise $top
4083 return
4084 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004085 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01004086 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004087 set newviewopts($nextviewnum,perm) 0
4088 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01004089 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004090}
4091
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004092set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004093 {perm b . {} {mc "Remember this view"}}
4094 {reflabel l + {} {mc "References (space separated list):"}}
4095 {refs t15 .. {} {mc "Branches & tags:"}}
4096 {allrefs b *. "--all" {mc "All refs"}}
4097 {branches b . "--branches" {mc "All (local) branches"}}
4098 {tags b . "--tags" {mc "All tags"}}
4099 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
4100 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
4101 {author t15 .. "--author=*" {mc "Author:"}}
4102 {committer t15 . "--committer=*" {mc "Committer:"}}
4103 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
4104 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
Alex Henrie00132512015-04-02 15:05:06 -06004105 {igrep b .. "--invert-grep" {mc "Matches no Commit Info criteria"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004106 {changes_l l + {} {mc "Changes to Files:"}}
4107 {pickaxe_s r0 . {} {mc "Fixed String"}}
4108 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
4109 {pickaxe t15 .. "-S*" {mc "Search string:"}}
4110 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
4111 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
4112 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
4113 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
4114 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
4115 {skip t10 . "--skip=*" {mc "Number to skip:"}}
4116 {misc_lbl l + {} {mc "Miscellaneous options:"}}
4117 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
4118 {lright b . "--left-right" {mc "Mark branch sides"}}
4119 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02004120 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004121 {args t50 *. {} {mc "Additional arguments to git log:"}}
4122 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
4123 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004124 }
4125
Jonathan Niedere7feb692010-03-06 16:48:38 -06004126# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004127proc encode_view_opts {n} {
4128 global known_view_options newviewopts
4129
4130 set rargs [list]
4131 foreach opt $known_view_options {
4132 set patterns [lindex $opt 3]
4133 if {$patterns eq {}} continue
4134 set pattern [lindex $patterns 0]
4135
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004136 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004137 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004138 if {$val} {
4139 lappend rargs $pattern
4140 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004141 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4142 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4143 set val $newviewopts($n,$button_id)
4144 if {$val eq $value} {
4145 lappend rargs $pattern
4146 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004147 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004148 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004149 set val [string trim $val]
4150 if {$val ne {}} {
4151 set pfix [string range $pattern 0 end-1]
4152 lappend rargs $pfix$val
4153 }
4154 }
4155 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004156 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004157 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4158}
4159
Jonathan Niedere7feb692010-03-06 16:48:38 -06004160# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004161proc decode_view_opts {n view_args} {
4162 global known_view_options newviewopts
4163
4164 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004165 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004166 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004167 # Checkboxes
4168 set val 0
4169 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
4170 # Radiobuttons
4171 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004172 set val 0
4173 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004174 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004175 set val {}
4176 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004177 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004178 }
4179 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004180 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004181 foreach arg $view_args {
4182 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4183 && ![info exists found(limit)]} {
4184 set newviewopts($n,limit) $cnt
4185 set found(limit) 1
4186 continue
4187 }
4188 catch { unset val }
4189 foreach opt $known_view_options {
4190 set id [lindex $opt 0]
4191 if {[info exists found($id)]} continue
4192 foreach pattern [lindex $opt 3] {
4193 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004194 if {[lindex $opt 1] eq "b"} {
4195 # Check buttons
4196 set val 1
4197 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4198 # Radio buttons
4199 regexp {^(.*_)} $id uselessvar id
4200 set val $num
4201 } else {
4202 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004203 set size [string length $pattern]
4204 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004205 }
4206 set newviewopts($n,$id) $val
4207 set found($id) 1
4208 break
4209 }
4210 if {[info exists val]} break
4211 }
4212 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004213 if {[regexp {^-} $arg]} {
4214 lappend oargs $arg
4215 } else {
4216 lappend refargs $arg
4217 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004218 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004219 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004220 set newviewopts($n,args) [shellarglist $oargs]
4221}
4222
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004223proc edit_or_newview {} {
4224 global curview
4225
4226 if {$curview > 0} {
4227 editview
4228 } else {
4229 newview 0
4230 }
4231}
4232
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004233proc editview {} {
4234 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004235 global viewname viewperm newviewname newviewopts
4236 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004237
4238 set top .gitkvedit-$curview
4239 if {[winfo exists $top]} {
4240 raise $top
4241 return
4242 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004243 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004244 set newviewname($curview) $viewname($curview)
4245 set newviewopts($curview,perm) $viewperm($curview)
4246 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004247 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004248}
4249
4250proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004251 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004252 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004253
Pat Thoytsd93f1712009-04-17 01:24:35 +01004254 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004255 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004256 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004257
4258 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004259 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004260 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004261 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004262 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004263 pack $top.nl -in $top.nfr -side left -padx {0 5}
4264 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004265
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004266 # View options
4267 set cframe $top.nfr
4268 set cexpand 0
4269 set cnt 0
4270 foreach opt $known_view_options {
4271 set id [lindex $opt 0]
4272 set type [lindex $opt 1]
4273 set flags [lindex $opt 2]
4274 set title [eval [lindex $opt 4]]
4275 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004276
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004277 if {$flags eq "+" || $flags eq "*"} {
4278 set cframe $top.fr$cnt
4279 incr cnt
Pat Thoytsd93f1712009-04-17 01:24:35 +01004280 ${NS}::frame $cframe
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004281 pack $cframe -in $top -fill x -pady 3 -padx 3
4282 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004283 } elseif {$flags eq ".." || $flags eq "*."} {
4284 set cframe $top.fr$cnt
4285 incr cnt
Paul Mackerraseae7d642009-09-05 17:34:03 +10004286 ${NS}::frame $cframe
Elijah Newren13d40b62009-03-23 11:57:46 -06004287 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4288 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004289 } else {
4290 set lxpad 5
4291 }
4292
Elijah Newren13d40b62009-03-23 11:57:46 -06004293 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004294 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004295 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
4296 } elseif {$type eq "b"} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004297 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004298 pack $cframe.c_$id -in $cframe -side left \
4299 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06004300 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4301 regexp {^(.*_)} $id uselessvar button_id
Paul Mackerraseae7d642009-09-05 17:34:03 +10004302 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
Elijah Newren13d40b62009-03-23 11:57:46 -06004303 pack $cframe.c_$id -in $cframe -side left \
4304 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004305 } elseif {[regexp {^t(\d+)$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004306 ${NS}::label $cframe.l_$id -text $title
4307 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004308 -textvariable newviewopts($n,$id)
4309 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4310 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4311 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004312 ${NS}::label $cframe.l_$id -text $title
4313 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004314 -textvariable newviewopts($n,$id)
4315 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4316 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06004317 } elseif {$type eq "path"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004318 ${NS}::label $top.l -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004319 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
Mark Hillsb9b142f2010-01-13 20:40:22 +00004320 text $top.t -width 40 -height 5 -background $bgcolor
Elijah Newren13d40b62009-03-23 11:57:46 -06004321 if {[info exists viewfiles($n)]} {
4322 foreach f $viewfiles($n) {
4323 $top.t insert end $f
4324 $top.t insert end "\n"
4325 }
4326 $top.t delete {end - 1c} end
4327 $top.t mark set insert 0.0
4328 }
4329 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004330 }
4331 }
4332
Pat Thoytsd93f1712009-04-17 01:24:35 +01004333 ${NS}::frame $top.buts
4334 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4335 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4336 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004337 bind $top <Control-Return> [list newviewok $top $n]
4338 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004339 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004340 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004341 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4342 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004343 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4344 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004345 focus $top.t
4346}
4347
Paul Mackerras908c3582006-05-20 09:38:11 +10004348proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004349 set nmenu [$m index end]
4350 for {set i $first} {$i <= $nmenu} {incr i} {
4351 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004352 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004353 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004354 }
4355 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004356}
4357
4358proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004359 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004360
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004361 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004362 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004363}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004364
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004365proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004366 global nextviewnum newviewperm newviewname newishighlight
Max Kirillov995f7922015-03-04 05:58:16 +02004367 global viewname viewfiles viewperm viewchanged selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004368 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004369
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004370 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004371 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004372 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03004373 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004374 return
4375 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004376 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004377 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004378 set ft [string trim $f]
4379 if {$ft ne {}} {
4380 lappend files $ft
4381 }
4382 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004383 if {![info exists viewfiles($n)]} {
4384 # creating a new view
4385 incr nextviewnum
4386 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004387 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004388 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004389 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004390 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004391 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004392 addviewmenu $n
4393 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004394 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004395 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004396 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004397 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004398 } else {
4399 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004400 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004401 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004402 if {$newviewname($n) ne $viewname($n)} {
4403 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004404 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004405 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10004406 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4407 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004408 }
Yann Dirson2d480852008-02-21 21:23:31 +01004409 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004410 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004411 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004412 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004413 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004414 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004415 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004416 }
4417 }
4418 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004419 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004420 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004421}
4422
4423proc delview {} {
Max Kirillov995f7922015-03-04 05:58:16 +02004424 global curview viewperm hlview selectedhlview viewchanged
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004425
4426 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004427 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004428 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004429 unset hlview
4430 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004431 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004432 set viewperm($curview) 0
Max Kirillov995f7922015-03-04 05:58:16 +02004433 set viewchanged($curview) 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004434 showview 0
4435}
4436
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004437proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004438 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004439
4440 .bar.view add radiobutton -label $viewname($n) \
4441 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004442 #$viewhlmenu add radiobutton -label $viewname($n) \
4443 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004444}
4445
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004446proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004447 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004448 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004449 global colormap rowtextx nextcolor canvxmax
4450 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004451 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004452 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004453 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004454 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004455 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004456 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004457
4458 if {$n == $curview} return
4459 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004460 set ymax [lindex [$canv cget -scrollregion] 3]
4461 set span [$canv yview]
4462 set ytop [expr {[lindex $span 0] * $ymax}]
4463 set ybot [expr {[lindex $span 1] * $ymax}]
4464 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004465 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004466 set selid $currentid
4467 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004468 if {$ytop < $y && $y < $ybot} {
4469 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004470 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004471 } elseif {[info exists pending_select]} {
4472 set selid $pending_select
4473 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004474 }
4475 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004476 normalline
Paul Mackerras009409f2015-05-02 20:53:36 +10004477 unset -nocomplain treediffs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004478 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004479 if {[info exists hlview] && $hlview == $n} {
4480 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004481 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004482 }
Paul Mackerras009409f2015-05-02 20:53:36 +10004483 unset -nocomplain commitinterest
4484 unset -nocomplain cached_commitrow
4485 unset -nocomplain ordertok
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004486
4487 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004488 set selectedview $n
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02004489 .bar.view entryconf [mca "&Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4490 .bar.view entryconf [mca "&Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004491
Paul Mackerrasdf904492007-08-29 22:03:07 +10004492 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004493 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004494 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004495 return
4496 }
4497
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004498 set displayorder {}
4499 set parentlist {}
4500 set rowidlist {}
4501 set rowisopt {}
4502 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004503 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004504
Paul Mackerras009409f2015-05-02 20:53:36 +10004505 unset -nocomplain colormap
4506 unset -nocomplain rowtextx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004507 set nextcolor 0
4508 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004509 set curview $n
4510 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004511 setcanvscroll
4512 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004513 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004514 if {$selid ne {} && [commitinview $selid $n]} {
4515 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004516 # try to get the selected row in the same position on the screen
4517 set ymax [lindex [$canv cget -scrollregion] 3]
4518 set ytop [expr {[yc $row] - $yscreen}]
4519 if {$ytop < 0} {
4520 set ytop 0
4521 }
4522 set yf [expr {$ytop * 1.0 / $ymax}]
4523 }
4524 allcanvs yview moveto $yf
4525 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004526 if {$row ne {}} {
4527 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004528 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004529 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004530 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004531 reset_pending_select {}
4532
4533 if {[commitinview $pending_select $curview]} {
4534 selectline [rowofcommit $pending_select] 1
4535 } else {
4536 set row [first_real_row]
4537 if {$row < $numcommits} {
4538 selectline $row 0
4539 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004540 }
4541 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004542 if {!$viewcomplete($n)} {
4543 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004544 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004545 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004546 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004547 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004548 }
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004549 set_window_title
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004550}
4551
Paul Mackerras908c3582006-05-20 09:38:11 +10004552# Stuff relating to the highlighting facility
4553
Paul Mackerras476ca632008-01-07 22:16:31 +11004554proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004555 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004556
Paul Mackerras476ca632008-01-07 22:16:31 +11004557 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4558 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004559 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004560 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4561 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004562 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004563 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4564 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004565 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004566 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4567 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004568 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004569 return 0
4570}
4571
Paul Mackerras28593d32008-11-13 23:01:46 +11004572proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004573 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004574
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004575 # need_redisplay = 1 means the display is stale and about to be redrawn
4576 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004577 lappend boldids $id
4578 $canv itemconf $linehtag($id) -font $font
4579 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004580 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004581 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004582 -outline {{}} -tags secsel \
4583 -fill [$canv cget -selectbackground]]
4584 $canv lower $t
4585 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004586 if {[info exists markedid] && $id eq $markedid} {
4587 make_idmark $id
4588 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004589}
4590
Paul Mackerras28593d32008-11-13 23:01:46 +11004591proc bolden_name {id font} {
4592 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004593
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004594 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004595 lappend boldnameids $id
4596 $canv2 itemconf $linentag($id) -font $font
4597 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004598 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004599 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004600 -outline {{}} -tags secsel \
4601 -fill [$canv2 cget -selectbackground]]
4602 $canv2 lower $t
4603 }
4604}
4605
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004606proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004607 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004608
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004609 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004610 foreach id $boldids {
4611 if {![ishighlighted $id]} {
4612 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004613 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004614 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004615 }
4616 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004617 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004618}
4619
4620proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004621 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004622
4623 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004624 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004625 }
4626 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004627 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004628 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004629 }
4630 set vhl_done $commitidx($hlview)
4631 if {$vhl_done > 0} {
4632 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004633 }
4634}
4635
Paul Mackerras908c3582006-05-20 09:38:11 +10004636proc delvhighlight {} {
4637 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004638
4639 if {![info exists hlview]} return
4640 unset hlview
Paul Mackerras009409f2015-05-02 20:53:36 +10004641 unset -nocomplain vhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004642 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004643}
4644
Paul Mackerras908c3582006-05-20 09:38:11 +10004645proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004646 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004647
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004648 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004649 set vr [visiblerows]
4650 set r0 [lindex $vr 0]
4651 set r1 [lindex $vr 1]
4652 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004653 set id [commitonrow $i $hlview]
4654 if {[commitinview $id $curview]} {
4655 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004656 if {$r0 <= $row && $row <= $r1} {
4657 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004658 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004659 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004660 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004661 }
4662 }
4663 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004664 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004665 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004666}
4667
4668proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004669 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004670
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004671 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004672 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004673 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004674 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004675 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004676 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004677 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004678 }
4679}
4680
Paul Mackerras687c8762007-09-22 12:49:33 +10004681proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004682 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004683 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004684
4685 if {[info exists filehighlight]} {
4686 # delete previous highlights
4687 catch {close $filehighlight}
4688 unset filehighlight
Paul Mackerras009409f2015-05-02 20:53:36 +10004689 unset -nocomplain fhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004690 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004691 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004692 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004693 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004694 after cancel do_file_hl $fh_serial
4695 incr fh_serial
4696 if {$highlight_files ne {}} {
4697 after 300 do_file_hl $fh_serial
4698 }
4699}
4700
Paul Mackerras687c8762007-09-22 12:49:33 +10004701proc gdttype_change {name ix op} {
4702 global gdttype highlight_files findstring findpattern
4703
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004704 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004705 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004706 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004707 if {$highlight_files ne {}} {
4708 set highlight_files {}
4709 hfiles_change
4710 }
4711 findcom_change
4712 } else {
4713 if {$findpattern ne {}} {
4714 set findpattern {}
4715 findcom_change
4716 }
4717 set highlight_files $findstring
4718 hfiles_change
4719 }
4720 drawvisible
4721 }
4722 # enable/disable findtype/findloc menus too
4723}
4724
4725proc find_change {name ix op} {
4726 global gdttype findstring highlight_files
4727
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004728 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004729 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004730 findcom_change
4731 } else {
4732 if {$highlight_files ne $findstring} {
4733 set highlight_files $findstring
4734 hfiles_change
4735 }
4736 }
4737 drawvisible
4738}
4739
Paul Mackerras64b5f142007-10-04 22:19:24 +10004740proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004741 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004742 global findpattern findtype findstring gdttype
4743
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004744 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004745 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004746 foreach id $boldnameids {
4747 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004748 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004749 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10004750 unset -nocomplain nhighlights
Paul Mackerras687c8762007-09-22 12:49:33 +10004751 unbolden
4752 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004753 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004754 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004755 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004756 set findpattern $findstring
4757 } else {
4758 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4759 $findstring]
4760 set findpattern "*$e*"
4761 }
4762}
4763
Paul Mackerras63b79192006-05-20 21:31:52 +10004764proc makepatterns {l} {
4765 set ret {}
4766 foreach e $l {
4767 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4768 if {[string index $ee end] eq "/"} {
4769 lappend ret "$ee*"
4770 } else {
4771 lappend ret $ee
4772 lappend ret "$ee/*"
4773 }
4774 }
4775 return $ret
4776}
4777
Paul Mackerras908c3582006-05-20 09:38:11 +10004778proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004779 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004780 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004781
Christian Stimmingb007ee22007-11-07 18:44:35 +01004782 if {$gdttype eq [mc "touching paths:"]} {
Yggy Kingde665fd2011-07-13 01:30:26 -07004783 # If "exact" match then convert backslashes to forward slashes.
4784 # Most useful to support Windows-flavoured file paths.
4785 if {$findtype eq [mc "Exact"]} {
4786 set highlight_files [string map {"\\" "/"} $highlight_files]
4787 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004788 if {[catch {set paths [shellsplit $highlight_files]}]} return
4789 set highlight_paths [makepatterns $paths]
4790 highlight_filelist
Martin von Zweigbergkc332f442011-04-04 22:14:12 -04004791 set relative_paths {}
4792 foreach path $paths {
4793 lappend relative_paths [file join $cdup $path]
4794 }
4795 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004796 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004797 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004798 } elseif {$gdttype eq [mc "changing lines matching:"]} {
4799 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004800 } else {
4801 # must be "containing:", i.e. we're searching commit info
4802 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004803 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004804 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004805 set filehighlight [open $cmd r+]
4806 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004807 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004808 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004809 drawvisible
4810 flushhighlights
4811}
4812
4813proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004814 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004815
4816 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004817 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004818 puts $filehighlight ""
4819 flush $filehighlight
4820 }
4821}
4822
4823proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004824 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004825
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004826 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004827 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004828 puts $filehighlight $id
4829}
4830
4831proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004832 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004833 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004834
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004835 if {![info exists filehighlight]} {
4836 return 0
4837 }
4838 set nr 0
4839 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004840 set line [string trim $line]
4841 set i [lsearch -exact $fhl_list $line]
4842 if {$i < 0} continue
4843 for {set j 0} {$j < $i} {incr j} {
4844 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004845 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004846 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004847 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4848 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004849 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004850 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004851 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004852 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004853 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004854 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004855 if {[eof $filehighlight]} {
4856 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004857 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004858 catch {close $filehighlight}
4859 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004860 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004861 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004862 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004863 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004864 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004865 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004866}
4867
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004868proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004869 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004870
Christian Stimmingb007ee22007-11-07 18:44:35 +01004871 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004872 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004873 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004874 return [string match -nocase $findpattern $f]
4875 } else {
4876 return [string match $findpattern $f]
4877 }
4878}
4879
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004880proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004881 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004882 global findloc
4883 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004884
4885 if {![info exists commitinfo($id)]} {
4886 getcommit $id
4887 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004888 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004889 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004890 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004891 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04004892 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01004893 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004894 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004895 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004896 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004897 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004898 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004899 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004900 }
4901 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004902 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004903 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004904 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004905 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004906 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004907 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004908 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004909 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004910 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004911 }
4912 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004913 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004914}
4915
Paul Mackerras005a2f42007-07-26 22:36:39 +10004916proc markrowmatches {row id} {
4917 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004918
Paul Mackerras005a2f42007-07-26 22:36:39 +10004919 set headline [lindex $commitinfo($id) 0]
4920 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004921 $canv delete match$row
4922 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004923 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004924 set m [findmatches $headline]
4925 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004926 markmatches $canv $row $headline $linehtag($id) $m \
4927 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004928 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004929 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004930 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004931 set m [findmatches $author]
4932 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004933 markmatches $canv2 $row $author $linentag($id) $m \
4934 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004935 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004936 }
4937}
4938
Paul Mackerras164ff272006-05-29 19:50:02 +10004939proc vrel_change {name ix op} {
4940 global highlight_related
4941
4942 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004943 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004944 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004945 }
4946}
4947
4948# prepare for testing whether commits are descendents or ancestors of a
4949proc rhighlight_sel {a} {
4950 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004951 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004952
Paul Mackerras009409f2015-05-02 20:53:36 +10004953 unset -nocomplain descendent
Paul Mackerras164ff272006-05-29 19:50:02 +10004954 set desc_todo [list $a]
Paul Mackerras009409f2015-05-02 20:53:36 +10004955 unset -nocomplain ancestor
Paul Mackerras164ff272006-05-29 19:50:02 +10004956 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004957 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004958 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004959 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004960 }
4961}
4962
4963proc rhighlight_none {} {
4964 global rhighlights
4965
Paul Mackerras009409f2015-05-02 20:53:36 +10004966 unset -nocomplain rhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004967 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004968}
4969
4970proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004971 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004972
4973 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004974 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004975 set todo $desc_todo
4976 set leftover {}
4977 set done 0
4978 for {set i 0} {$i < [llength $todo]} {incr i} {
4979 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004980 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004981 lappend leftover $do
4982 continue
4983 }
4984 foreach nk $children($v,$do) {
4985 if {![info exists descendent($nk)]} {
4986 set descendent($nk) 1
4987 lappend todo $nk
4988 if {$nk eq $a} {
4989 set done 1
4990 }
4991 }
4992 }
4993 if {$done} {
4994 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4995 return
4996 }
4997 }
4998 set descendent($a) 0
4999 set desc_todo $leftover
5000}
5001
5002proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005003 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10005004
5005 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005006 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10005007 set todo $anc_todo
5008 set leftover {}
5009 set done 0
5010 for {set i 0} {$i < [llength $todo]} {incr i} {
5011 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005012 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005013 lappend leftover $do
5014 continue
5015 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005016 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10005017 if {![info exists ancestor($np)]} {
5018 set ancestor($np) 1
5019 lappend todo $np
5020 if {$np eq $a} {
5021 set done 1
5022 }
5023 }
5024 }
5025 if {$done} {
5026 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5027 return
5028 }
5029 }
5030 set ancestor($a) 0
5031 set anc_todo $leftover
5032}
5033
5034proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005035 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005036 global selectedline ancestor
5037
Paul Mackerras94b4a692008-05-20 20:51:06 +10005038 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10005039 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01005040 if {$highlight_related eq [mc "Descendant"] ||
5041 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005042 if {![info exists descendent($id)]} {
5043 is_descendent $id
5044 }
Christian Stimming55e34432008-01-09 22:23:18 +01005045 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005046 set isbold 1
5047 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005048 } elseif {$highlight_related eq [mc "Ancestor"] ||
5049 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005050 if {![info exists ancestor($id)]} {
5051 is_ancestor $id
5052 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005053 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005054 set isbold 1
5055 }
5056 }
5057 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11005058 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005059 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005060 }
5061 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005062 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005063}
5064
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005065# Graph layout functions
5066
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005067proc shortids {ids} {
5068 set res {}
5069 foreach id $ids {
5070 if {[llength $id] > 1} {
5071 lappend res [shortids $id]
5072 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
5073 lappend res [string range $id 0 7]
5074 } else {
5075 lappend res $id
5076 }
5077 }
5078 return $res
5079}
5080
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005081proc ntimes {n o} {
5082 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10005083 set o [list $o]
5084 for {set mask 1} {$mask <= $n} {incr mask $mask} {
5085 if {($n & $mask) != 0} {
5086 set ret [concat $ret $o]
5087 }
5088 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005089 }
5090 return $ret
5091}
5092
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005093proc ordertoken {id} {
5094 global ordertok curview varcid varcstart varctok curview parents children
5095 global nullid nullid2
5096
5097 if {[info exists ordertok($id)]} {
5098 return $ordertok($id)
5099 }
5100 set origid $id
5101 set todo {}
5102 while {1} {
5103 if {[info exists varcid($curview,$id)]} {
5104 set a $varcid($curview,$id)
5105 set p [lindex $varcstart($curview) $a]
5106 } else {
5107 set p [lindex $children($curview,$id) 0]
5108 }
5109 if {[info exists ordertok($p)]} {
5110 set tok $ordertok($p)
5111 break
5112 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11005113 set id [first_real_child $curview,$p]
5114 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005115 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11005116 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005117 break
5118 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005119 if {[llength $parents($curview,$id)] == 1} {
5120 lappend todo [list $p {}]
5121 } else {
5122 set j [lsearch -exact $parents($curview,$id) $p]
5123 if {$j < 0} {
5124 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
5125 }
5126 lappend todo [list $p [strrep $j]]
5127 }
5128 }
5129 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
5130 set p [lindex $todo $i 0]
5131 append tok [lindex $todo $i 1]
5132 set ordertok($p) $tok
5133 }
5134 set ordertok($origid) $tok
5135 return $tok
5136}
5137
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005138# Work out where id should go in idlist so that order-token
5139# values increase from left to right
5140proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005141 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005142 if {$i < 0} {
5143 set i 0
5144 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005145 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005146 if {$i > [llength $idlist]} {
5147 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005148 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005149 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005150 incr i
5151 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005152 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005153 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005154 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005155 }
5156 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005157 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005158}
5159
5160proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005161 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005162 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005163 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005164 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005165
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005166 set numcommits 0
5167 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005168 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005169 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005170 set rowidlist {}
5171 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005172 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005173 set canvxmax [$canv cget -width]
Paul Mackerras009409f2015-05-02 20:53:36 +10005174 unset -nocomplain colormap
5175 unset -nocomplain rowtextx
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005176 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005177}
5178
5179proc setcanvscroll {} {
5180 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005181 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005182
5183 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5184 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5185 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5186 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005187 set lastscrollset [clock clicks -milliseconds]
5188 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005189}
5190
5191proc visiblerows {} {
5192 global canv numcommits linespc
5193
5194 set ymax [lindex [$canv cget -scrollregion] 3]
5195 if {$ymax eq {} || $ymax == 0} return
5196 set f [$canv yview]
5197 set y0 [expr {int([lindex $f 0] * $ymax)}]
5198 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5199 if {$r0 < 0} {
5200 set r0 0
5201 }
5202 set y1 [expr {int([lindex $f 1] * $ymax)}]
5203 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5204 if {$r1 >= $numcommits} {
5205 set r1 [expr {$numcommits - 1}]
5206 }
5207 return [list $r0 $r1]
5208}
5209
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005210proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005211 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005212 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005213 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005214
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005215 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
5216 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005217 setcanvscroll
5218 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005219 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005220 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04005221 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005222 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005223 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005224 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005225}
5226
Paul Mackerrascdc84292008-11-18 19:54:14 +11005227# With path limiting, we mightn't get the actual HEAD commit,
5228# so ask git rev-list what is the first ancestor of HEAD that
5229# touches a file in the path limit.
5230proc get_viewmainhead {view} {
5231 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005232
Paul Mackerrascdc84292008-11-18 19:54:14 +11005233 catch {
5234 set rfd [open [concat | git rev-list -1 $mainheadid \
5235 -- $vfilelimit($view)] r]
5236 set j [reg_instance $rfd]
5237 lappend viewinstances($view) $j
5238 fconfigure $rfd -blocking 0
5239 filerun $rfd [list getviewhead $rfd $j $view]
5240 set viewmainheadid($curview) {}
5241 }
5242}
5243
5244# git rev-list should give us just 1 line to use as viewmainheadid($view)
5245proc getviewhead {fd inst view} {
5246 global viewmainheadid commfd curview viewinstances showlocalchanges
5247
5248 set id {}
5249 if {[gets $fd line] < 0} {
5250 if {![eof $fd]} {
5251 return 1
5252 }
5253 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
5254 set id $line
5255 }
5256 set viewmainheadid($view) $id
5257 close $fd
5258 unset commfd($inst)
5259 set i [lsearch -exact $viewinstances($view) $inst]
5260 if {$i >= 0} {
5261 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
5262 }
5263 if {$showlocalchanges && $id ne {} && $view == $curview} {
5264 doshowlocalchanges
5265 }
5266 return 0
5267}
5268
5269proc doshowlocalchanges {} {
5270 global curview viewmainheadid
5271
5272 if {$viewmainheadid($curview) eq {}} return
5273 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005274 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005275 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005276 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005277 }
5278}
5279
5280proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005281 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005282
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005283 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005284 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005285 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005286 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005287 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005288 }
5289 incr lserial
5290}
5291
Paul Mackerras8f489362007-07-13 19:49:37 +10005292# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005293proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005294 global lserial showlocalchanges vfilelimit curview
Jens Lehmann17f98362014-04-08 21:36:08 +02005295 global hasworktree git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005296
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005297 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005298 incr lserial
Jens Lehmann17f98362014-04-08 21:36:08 +02005299 if {[package vcompare $git_version "1.7.2"] >= 0} {
5300 set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
5301 } else {
5302 set cmd "|git diff-index --cached HEAD"
5303 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005304 if {$vfilelimit($curview) ne {}} {
5305 set cmd [concat $cmd -- $vfilelimit($curview)]
5306 }
5307 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005308 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005309 set i [reg_instance $fd]
5310 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005311}
5312
Alexander Gavrilove439e092008-07-13 16:40:47 +04005313proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005314 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5315 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005316
Paul Mackerras8f489362007-07-13 19:49:37 +10005317 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005318 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005319 if {![eof $fd]} {
5320 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005321 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005322 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005323 }
5324 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005325 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005326
Paul Mackerras24f7a662007-12-19 09:35:33 +11005327 if {$serial != $lserial} {
5328 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005329 }
5330
Paul Mackerras24f7a662007-12-19 09:35:33 +11005331 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005332 set cmd "|git diff-files"
5333 if {$vfilelimit($curview) ne {}} {
5334 set cmd [concat $cmd -- $vfilelimit($curview)]
5335 }
5336 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005337 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005338 set i [reg_instance $fd]
5339 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005340
5341 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005342 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005343 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10005344 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5345 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005346 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005347 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005348 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005349 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005350 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005351 if {[commitinview $nullid $curview]} {
5352 removefakerow $nullid
5353 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005354 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005355 }
5356 return 0
5357}
5358
Alexander Gavrilove439e092008-07-13 16:40:47 +04005359proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005360 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005361 global commitinfo commitdata lserial
5362
5363 set isdiff 1
5364 if {[gets $fd line] < 0} {
5365 if {![eof $fd]} {
5366 return 1
5367 }
5368 set isdiff 0
5369 }
5370 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005371 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005372
Paul Mackerras24f7a662007-12-19 09:35:33 +11005373 if {$serial != $lserial} {
5374 return 0
5375 }
5376
5377 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005378 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005379 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005380 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5381 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005382 if {[commitinview $nullid2 $curview]} {
5383 set p $nullid2
5384 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005385 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005386 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005387 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005388 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005389 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005390 }
5391 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005392}
5393
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005394proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005395 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005396
5397 if {[info exists children($curview,$id)]} {
5398 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005399 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005400 return -1
5401 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005402 if {[rowofcommit $kid] > $row} {
5403 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005404 }
5405 }
5406 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005407 if {[commitinview $id $curview]} {
5408 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005409 }
5410 return -1
5411}
5412
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005413proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005414 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005415
5416 set ret -1
5417 if {[info exists children($curview,$id)]} {
5418 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005419 if {![commitinview $kid $curview]} break
5420 if {[rowofcommit $kid] < $row} {
5421 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005422 }
5423 }
5424 }
5425 return $ret
5426}
5427
Paul Mackerras03800812007-08-29 21:45:21 +10005428proc make_idlist {row} {
5429 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005430 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005431
5432 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5433 if {$r < 0} {
5434 set r 0
5435 }
5436 set ra [expr {$row - $downarrowlen}]
5437 if {$ra < 0} {
5438 set ra 0
5439 }
5440 set rb [expr {$row + $uparrowlen}]
5441 if {$rb > $commitidx($curview)} {
5442 set rb $commitidx($curview)
5443 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005444 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005445 set ids {}
5446 for {} {$r < $ra} {incr r} {
5447 set nextid [lindex $displayorder [expr {$r + 1}]]
5448 foreach p [lindex $parentlist $r] {
5449 if {$p eq $nextid} continue
5450 set rn [nextuse $p $r]
5451 if {$rn >= $row &&
5452 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005453 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005454 }
5455 }
5456 }
5457 for {} {$r < $row} {incr r} {
5458 set nextid [lindex $displayorder [expr {$r + 1}]]
5459 foreach p [lindex $parentlist $r] {
5460 if {$p eq $nextid} continue
5461 set rn [nextuse $p $r]
5462 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005463 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005464 }
5465 }
5466 }
5467 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005468 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005469 while {$r < $rb} {
5470 foreach p [lindex $parentlist $r] {
5471 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005472 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005473 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005474 }
5475 }
5476 incr r
5477 set id [lindex $displayorder $r]
5478 if {$id ne {}} {
5479 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005480 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005481 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005482 }
5483 }
5484 }
5485 set idlist {}
5486 foreach idx [lsort -unique $ids] {
5487 lappend idlist [lindex $idx 1]
5488 }
5489 return $idlist
5490}
5491
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005492proc rowsequal {a b} {
5493 while {[set i [lsearch -exact $a {}]] >= 0} {
5494 set a [lreplace $a $i $i]
5495 }
5496 while {[set i [lsearch -exact $b {}]] >= 0} {
5497 set b [lreplace $b $i $i]
5498 }
5499 return [expr {$a eq $b}]
5500}
5501
5502proc makeupline {id row rend col} {
5503 global rowidlist uparrowlen downarrowlen mingaplen
5504
5505 for {set r $rend} {1} {set r $rstart} {
5506 set rstart [prevuse $id $r]
5507 if {$rstart < 0} return
5508 if {$rstart < $row} break
5509 }
5510 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5511 set rstart [expr {$rend - $uparrowlen - 1}]
5512 }
5513 for {set r $rstart} {[incr r] <= $row} {} {
5514 set idlist [lindex $rowidlist $r]
5515 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5516 set col [idcol $idlist $id $col]
5517 lset rowidlist $r [linsert $idlist $col $id]
5518 changedrow $r
5519 }
5520 }
5521}
5522
Paul Mackerras03800812007-08-29 21:45:21 +10005523proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005524 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005525 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005526 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005527 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005528
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005529 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005530 set idlist {}
5531 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005532 set rm1 [expr {$row - 1}]
5533 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005534 if {$id ne {}} {
5535 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005536 }
5537 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005538 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005539 }
Paul Mackerras03800812007-08-29 21:45:21 +10005540 for {} {$row < $endrow} {incr row} {
5541 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005542 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005543 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005544 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005545 } else {
5546 set id [lindex $displayorder $rm1]
5547 set col [lsearch -exact $idlist $id]
5548 set idlist [lreplace $idlist $col $col]
5549 foreach p [lindex $parentlist $rm1] {
5550 if {[lsearch -exact $idlist $p] < 0} {
5551 set col [idcol $idlist $p $col]
5552 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005553 # if not the first child, we have to insert a line going up
5554 if {$id ne [lindex $children($curview,$p) 0]} {
5555 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005556 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005557 }
5558 }
Paul Mackerras03800812007-08-29 21:45:21 +10005559 set id [lindex $displayorder $row]
5560 if {$row > $downarrowlen} {
5561 set termrow [expr {$row - $downarrowlen - 1}]
5562 foreach p [lindex $parentlist $termrow] {
5563 set i [lsearch -exact $idlist $p]
5564 if {$i < 0} continue
5565 set nr [nextuse $p $termrow]
5566 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5567 set idlist [lreplace $idlist $i $i]
5568 }
5569 }
5570 }
5571 set col [lsearch -exact $idlist $id]
5572 if {$col < 0} {
5573 set col [idcol $idlist $id]
5574 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005575 if {$children($curview,$id) ne {}} {
5576 makeupline $id $rm1 $row $col
5577 }
Paul Mackerras03800812007-08-29 21:45:21 +10005578 }
5579 set r [expr {$row + $uparrowlen - 1}]
5580 if {$r < $commitidx($curview)} {
5581 set x $col
5582 foreach p [lindex $parentlist $r] {
5583 if {[lsearch -exact $idlist $p] >= 0} continue
5584 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005585 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005586 set x [idcol $idlist $p $x]
5587 set idlist [linsert $idlist $x $p]
5588 }
5589 }
5590 if {[incr r] < $commitidx($curview)} {
5591 set p [lindex $displayorder $r]
5592 if {[lsearch -exact $idlist $p] < 0} {
5593 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005594 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005595 set x [idcol $idlist $p $x]
5596 set idlist [linsert $idlist $x $p]
5597 }
5598 }
5599 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005600 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005601 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005602 if {$final && !$viewcomplete($curview) &&
5603 $row + $uparrowlen + $mingaplen + $downarrowlen
5604 >= $commitidx($curview)} {
5605 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005606 }
Paul Mackerras03800812007-08-29 21:45:21 +10005607 set l [llength $rowidlist]
5608 if {$row == $l} {
5609 lappend rowidlist $idlist
5610 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005611 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005612 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005613 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005614 lset rowidlist $row $idlist
5615 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005616 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005617 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005618 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005619 set pad [ntimes [expr {$row - $l}] {}]
5620 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005621 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005622 set rowfinal [concat $rowfinal $pad]
5623 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005624 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005625 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005626 }
5627 return $row
5628}
5629
Paul Mackerras03800812007-08-29 21:45:21 +10005630proc changedrow {row} {
5631 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005632
Paul Mackerras03800812007-08-29 21:45:21 +10005633 set l [llength $rowisopt]
5634 if {$row < $l} {
5635 lset rowisopt $row 0
5636 if {$row + 1 < $l} {
5637 lset rowisopt [expr {$row + 1}] 0
5638 if {$row + 2 < $l} {
5639 lset rowisopt [expr {$row + 2}] 0
5640 }
5641 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005642 }
Paul Mackerras03800812007-08-29 21:45:21 +10005643 set id [lindex $displayorder $row]
5644 if {[info exists iddrawn($id)]} {
5645 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005646 }
5647}
5648
5649proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005650 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005651
5652 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005653 set idlist [lindex $rowidlist $row]
5654 set bef [lrange $idlist 0 [expr {$col - 1}]]
5655 set aft [lrange $idlist $col end]
5656 set i [lsearch -exact $aft {}]
5657 if {$i > 0} {
5658 set aft [lreplace $aft $i $i]
5659 }
5660 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005661 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005662}
5663
5664proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005665 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005666
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005667 if {$row < 1} {
5668 set row 1
5669 }
Paul Mackerras03800812007-08-29 21:45:21 +10005670 for {} {$row < $endrow} {incr row; set col 0} {
5671 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005672 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005673 set y0 [expr {$row - 1}]
5674 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005675 set idlist [lindex $rowidlist $row]
5676 set previdlist [lindex $rowidlist $y0]
5677 if {$idlist eq {} || $previdlist eq {}} continue
5678 if {$ym >= 0} {
5679 set pprevidlist [lindex $rowidlist $ym]
5680 if {$pprevidlist eq {}} continue
5681 } else {
5682 set pprevidlist {}
5683 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005684 set x0 -1
5685 set xm -1
5686 for {} {$col < [llength $idlist]} {incr col} {
5687 set id [lindex $idlist $col]
5688 if {[lindex $previdlist $col] eq $id} continue
5689 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005690 set haspad 1
5691 continue
5692 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005693 set x0 [lsearch -exact $previdlist $id]
5694 if {$x0 < 0} continue
5695 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005696 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005697 set z0 {}
5698 if {$ym >= 0} {
5699 set xm [lsearch -exact $pprevidlist $id]
5700 if {$xm >= 0} {
5701 set z0 [expr {$xm - $x0}]
5702 }
5703 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005704 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005705 # if row y0 is the first child of $id then it's not an arrow
5706 if {[lindex $children($curview,$id) 0] ne
5707 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005708 set isarrow 1
5709 }
5710 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005711 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5712 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5713 set isarrow 1
5714 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005715 # Looking at lines from this row to the previous row,
5716 # make them go straight up if they end in an arrow on
5717 # the previous row; otherwise make them go straight up
5718 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005719 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005720 # Line currently goes left too much;
5721 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005722 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005723 insert_pad $y0 $x0 $npad
5724 if {$y0 > 0} {
5725 optimize_rows $y0 $x0 $row
5726 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005727 set previdlist [lindex $rowidlist $y0]
5728 set x0 [lsearch -exact $previdlist $id]
5729 set z [expr {$x0 - $col}]
5730 if {$z0 ne {}} {
5731 set pprevidlist [lindex $rowidlist $ym]
5732 set xm [lsearch -exact $pprevidlist $id]
5733 set z0 [expr {$xm - $x0}]
5734 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005735 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005736 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005737 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005738 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005739 insert_pad $row $col $npad
5740 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005741 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005742 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005743 set haspad 1
5744 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005745 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005746 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005747 set id [lindex $displayorder $ym]
5748 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005749 if {$xc >= 0} {
5750 set z0 [expr {$xc - $x0}]
5751 }
5752 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005753 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005754 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5755 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005756 incr x0
5757 optimize_rows $y0 $x0 $row
5758 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005759 }
5760 }
5761 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005762 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005763 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005764 set id [lindex $idlist $col]
5765 if {$id eq {}} break
5766 set x0 [lsearch -exact $previdlist $id]
5767 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005768 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005769 set kid [lindex $displayorder $y0]
5770 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005771 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005772 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005773 }
5774 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005775 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005776 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005777 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005778 # isn't the last column
5779 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005780 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005781 lset rowidlist $row $idlist
5782 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005783 }
5784 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005785 }
5786}
5787
5788proc xc {row col} {
5789 global canvx0 linespc
5790 return [expr {$canvx0 + $col * $linespc}]
5791}
5792
5793proc yc {row} {
5794 global canvy0 linespc
5795 return [expr {$canvy0 + $row * $linespc}]
5796}
5797
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005798proc linewidth {id} {
5799 global thickerline lthickness
5800
5801 set wid $lthickness
5802 if {[info exists thickerline] && $id eq $thickerline} {
5803 set wid [expr {2 * $lthickness}]
5804 }
5805 return $wid
5806}
5807
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005808proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005809 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005810 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005811
Paul Mackerras92ed6662007-08-22 22:35:28 +10005812 set kids $children($curview,$id)
5813 if {$kids eq {}} {
5814 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005815 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005816 set ret {}
5817 lappend kids $id
5818 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005819 if {![commitinview $child $curview]} break
5820 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005821 if {![info exists prev]} {
5822 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005823 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005824 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005825 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005826 }
5827 # see if the line extends the whole way from prevrow to row
5828 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5829 [lsearch -exact [lindex $rowidlist \
5830 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5831 # it doesn't, see where it ends
5832 set r [expr {$prevrow + $downarrowlen}]
5833 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5834 while {[incr r -1] > $prevrow &&
5835 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5836 } else {
5837 while {[incr r] <= $row &&
5838 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5839 incr r -1
5840 }
5841 lappend ret $r
5842 # see where it starts up again
5843 set r [expr {$row - $uparrowlen}]
5844 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5845 while {[incr r] < $row &&
5846 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5847 } else {
5848 while {[incr r -1] >= $prevrow &&
5849 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5850 incr r
5851 }
5852 lappend ret $r
5853 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005854 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005855 if {$child eq $id} {
5856 lappend ret $row
5857 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005858 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005859 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005860 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005861 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005862}
5863
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005864proc drawlineseg {id row endrow arrowlow} {
5865 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005866 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005867
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005868 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5869 set le [expr {$row + 1}]
5870 set arrowhigh 1
5871 while {1} {
5872 set c [lsearch -exact [lindex $rowidlist $le] $id]
5873 if {$c < 0} {
5874 incr le -1
5875 break
5876 }
5877 lappend cols $c
5878 set x [lindex $displayorder $le]
5879 if {$x eq $id} {
5880 set arrowhigh 0
5881 break
5882 }
5883 if {[info exists iddrawn($x)] || $le == $endrow} {
5884 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5885 if {$c >= 0} {
5886 lappend cols $c
5887 set arrowhigh 0
5888 }
5889 break
5890 }
5891 incr le
5892 }
5893 if {$le <= $row} {
5894 return $row
5895 }
5896
5897 set lines {}
5898 set i 0
5899 set joinhigh 0
5900 if {[info exists linesegs($id)]} {
5901 set lines $linesegs($id)
5902 foreach li $lines {
5903 set r0 [lindex $li 0]
5904 if {$r0 > $row} {
5905 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5906 set joinhigh 1
5907 }
5908 break
5909 }
5910 incr i
5911 }
5912 }
5913 set joinlow 0
5914 if {$i > 0} {
5915 set li [lindex $lines [expr {$i-1}]]
5916 set r1 [lindex $li 1]
5917 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5918 set joinlow 1
5919 }
5920 }
5921
5922 set x [lindex $cols [expr {$le - $row}]]
5923 set xp [lindex $cols [expr {$le - 1 - $row}]]
5924 set dir [expr {$xp - $x}]
5925 if {$joinhigh} {
5926 set ith [lindex $lines $i 2]
5927 set coords [$canv coords $ith]
5928 set ah [$canv itemcget $ith -arrow]
5929 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5930 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5931 if {$x2 ne {} && $x - $x2 == $dir} {
5932 set coords [lrange $coords 0 end-2]
5933 }
5934 } else {
5935 set coords [list [xc $le $x] [yc $le]]
5936 }
5937 if {$joinlow} {
5938 set itl [lindex $lines [expr {$i-1}] 2]
5939 set al [$canv itemcget $itl -arrow]
5940 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005941 } elseif {$arrowlow} {
5942 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5943 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5944 set arrowlow 0
5945 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005946 }
5947 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5948 for {set y $le} {[incr y -1] > $row} {} {
5949 set x $xp
5950 set xp [lindex $cols [expr {$y - 1 - $row}]]
5951 set ndir [expr {$xp - $x}]
5952 if {$dir != $ndir || $xp < 0} {
5953 lappend coords [xc $y $x] [yc $y]
5954 }
5955 set dir $ndir
5956 }
5957 if {!$joinlow} {
5958 if {$xp < 0} {
5959 # join parent line to first child
5960 set ch [lindex $displayorder $row]
5961 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5962 if {$xc < 0} {
5963 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005964 } elseif {$xc != $x} {
5965 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5966 set d [expr {int(0.5 * $linespc)}]
5967 set x1 [xc $row $x]
5968 if {$xc < $x} {
5969 set x2 [expr {$x1 - $d}]
5970 } else {
5971 set x2 [expr {$x1 + $d}]
5972 }
5973 set y2 [yc $row]
5974 set y1 [expr {$y2 + $d}]
5975 lappend coords $x1 $y1 $x2 $y2
5976 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005977 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5978 } elseif {$xc > $x + 1} {
5979 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5980 }
5981 set x $xc
5982 }
5983 lappend coords [xc $row $x] [yc $row]
5984 } else {
5985 set xn [xc $row $xp]
5986 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005987 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005988 }
5989 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005990 assigncolor $id
5991 set t [$canv create line $coords -width [linewidth $id] \
5992 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5993 $canv lower $t
5994 bindline $t $id
5995 set lines [linsert $lines $i [list $row $le $t]]
5996 } else {
5997 $canv coords $ith $coords
5998 if {$arrow ne $ah} {
5999 $canv itemconf $ith -arrow $arrow
6000 }
6001 lset lines $i 0 $row
6002 }
6003 } else {
6004 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
6005 set ndir [expr {$xo - $xp}]
6006 set clow [$canv coords $itl]
6007 if {$dir == $ndir} {
6008 set clow [lrange $clow 2 end]
6009 }
6010 set coords [concat $coords $clow]
6011 if {!$joinhigh} {
6012 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006013 } else {
6014 # coalesce two pieces
6015 $canv delete $ith
6016 set b [lindex $lines [expr {$i-1}] 0]
6017 set e [lindex $lines $i 1]
6018 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
6019 }
6020 $canv coords $itl $coords
6021 if {$arrow ne $al} {
6022 $canv itemconf $itl -arrow $arrow
6023 }
6024 }
6025
6026 set linesegs($id) $lines
6027 return $le
6028}
6029
6030proc drawparentlinks {id row} {
6031 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10006032 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006033
6034 set rowids [lindex $rowidlist $row]
6035 set col [lsearch -exact $rowids $id]
6036 if {$col < 0} return
6037 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006038 set row2 [expr {$row + 1}]
6039 set x [xc $row $col]
6040 set y [yc $row]
6041 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10006042 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006043 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006044 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006045 # rmx = right-most X coord used
6046 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006047 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11006048 set i [lsearch -exact $ids $p]
6049 if {$i < 0} {
6050 puts "oops, parent $p of $id not in list"
6051 continue
6052 }
6053 set x2 [xc $row2 $i]
6054 if {$x2 > $rmx} {
6055 set rmx $x2
6056 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10006057 set j [lsearch -exact $rowids $p]
6058 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11006059 # drawlineseg will do this one for us
6060 continue
6061 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006062 assigncolor $p
6063 # should handle duplicated parents here...
6064 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006065 if {$i != $col} {
6066 # if attaching to a vertical segment, draw a smaller
6067 # slant for visual distinctness
6068 if {$i == $j} {
6069 if {$i < $col} {
6070 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
6071 } else {
6072 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
6073 }
6074 } elseif {$i < $col && $i < $j} {
6075 # segment slants towards us already
6076 lappend coords [xc $row $j] $y
6077 } else {
6078 if {$i < $col - 1} {
6079 lappend coords [expr {$x2 + $linespc}] $y
6080 } elseif {$i > $col + 1} {
6081 lappend coords [expr {$x2 - $linespc}] $y
6082 }
6083 lappend coords $x2 $y2
6084 }
6085 } else {
6086 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006087 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006088 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006089 -fill $colormap($p) -tags lines.$p]
6090 $canv lower $t
6091 bindline $t $p
6092 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006093 if {$rmx > [lindex $idpos($id) 1]} {
6094 lset idpos($id) 1 $rmx
6095 redrawtags $id
6096 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006097}
6098
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006099proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006100 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006101
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006102 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006103}
6104
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006105proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006106 global linespc canv canv2 canv3 fgcolor curview
6107 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006108 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10006109 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006110 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05006111 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006112 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
6113 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006114
Linus Torvalds1407ade2008-02-09 14:02:07 -08006115 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006116 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006117 if {$id eq $nullid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006118 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10006119 } elseif {$id eq $nullid2} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006120 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006121 } elseif {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006122 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006123 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006124 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006125 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006126 set x [xc $row $col]
6127 set y [yc $row]
6128 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006129 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006130 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
6131 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006132 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006133 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006134 # triangle pointing left for left-side commits
6135 set t [$canv create polygon \
6136 [expr {$x - $orad}] $y \
6137 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
6138 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006139 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006140 } else {
6141 # triangle pointing right for right-side commits
6142 set t [$canv create polygon \
6143 [expr {$x + $orad - 1}] $y \
6144 [expr {$x - $orad}] [expr {$y - $orad}] \
6145 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006146 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006147 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006148 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006149 $canv raise $t
6150 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006151 set rmx [llength [lindex $rowidlist $row]]
6152 set olds [lindex $parentlist $row]
6153 if {$olds ne {}} {
6154 set nextids [lindex $rowidlist [expr {$row + 1}]]
6155 foreach p $olds {
6156 set i [lsearch -exact $nextids $p]
6157 if {$i > $rmx} {
6158 set rmx $i
6159 }
6160 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006161 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006162 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006163 set rowtextx($row) $xt
6164 set idpos($id) [list $x $xt $y]
6165 if {[info exists idtags($id)] || [info exists idheads($id)]
6166 || [info exists idotherrefs($id)]} {
6167 set xt [drawtags $id $x $xt $y]
6168 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006169 if {[lindex $commitinfo($id) 6] > 0} {
6170 set xt [drawnotesign $xt $y]
6171 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006172 set headline [lindex $commitinfo($id) 0]
6173 set name [lindex $commitinfo($id) 1]
6174 set date [lindex $commitinfo($id) 2]
6175 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006176 set font mainfont
6177 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006178 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006179 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006180 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006181 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006182 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006183 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006184 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006185 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006186 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006187 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
6188 -text $headline -font $font -tags text]
6189 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6190 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
6191 -text $name -font $nfont -tags text]
6192 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
6193 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006194 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006195 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006196 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006197 if {[info exists markedid] && $markedid eq $id} {
6198 make_idmark $id
6199 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006200 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006201 if {$xr > $canvxmax} {
6202 set canvxmax $xr
6203 setcanvscroll
6204 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006205}
6206
6207proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006208 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006209 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006210 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006211 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006212 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006213 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006214
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006215 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006216
6217 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006218 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006219 askvhighlight $row $id
6220 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006221 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006222 askfilehighlight $row $id
6223 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006224 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006225 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006226 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006227 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10006228 askrelhighlight $row $id
6229 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006230 if {![info exists iddrawn($id)]} {
6231 set col [lsearch -exact [lindex $rowidlist $row] $id]
6232 if {$col < 0} {
6233 puts "oops, row $row id $id not in list"
6234 return
6235 }
6236 if {![info exists commitinfo($id)]} {
6237 getcommit $id
6238 }
6239 assigncolor $id
6240 drawcmittext $id $row $col
6241 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10006242 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006243 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006244 if {$markingmatches} {
6245 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006246 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006247}
6248
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006249proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006250 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006251 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006252
6253 if {$row < 0} {
6254 set row 0
6255 }
6256 if {$endrow eq {}} {
6257 set endrow $row
6258 }
6259 if {$endrow >= $numcommits} {
6260 set endrow [expr {$numcommits - 1}]
6261 }
6262
Paul Mackerras03800812007-08-29 21:45:21 +10006263 set rl1 [expr {$row - $downarrowlen - 3}]
6264 if {$rl1 < 0} {
6265 set rl1 0
6266 }
6267 set ro1 [expr {$row - 3}]
6268 if {$ro1 < 0} {
6269 set ro1 0
6270 }
6271 set r2 [expr {$endrow + $uparrowlen + 3}]
6272 if {$r2 > $numcommits} {
6273 set r2 $numcommits
6274 }
6275 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006276 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10006277 if {$rl1 < $r} {
6278 layoutrows $rl1 $r
6279 }
6280 set rl1 [expr {$r + 1}]
6281 }
6282 }
6283 if {$rl1 < $r} {
6284 layoutrows $rl1 $r
6285 }
6286 optimize_rows $ro1 0 $r2
6287 if {$need_redisplay || $nrows_drawn > 2000} {
6288 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006289 }
6290
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006291 # make the lines join to already-drawn rows either side
6292 set r [expr {$row - 1}]
6293 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
6294 set r $row
6295 }
6296 set er [expr {$endrow + 1}]
6297 if {$er >= $numcommits ||
6298 ![info exists iddrawn([lindex $displayorder $er])]} {
6299 set er $endrow
6300 }
6301 for {} {$r <= $er} {incr r} {
6302 set id [lindex $displayorder $r]
6303 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006304 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006305 if {$r == $er} break
6306 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006307 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006308 drawparentlinks $id $r
6309
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006310 set rowids [lindex $rowidlist $r]
6311 foreach lid $rowids {
6312 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006313 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006314 if {$lid eq $id} {
6315 # see if this is the first child of any of its parents
6316 foreach p [lindex $parentlist $r] {
6317 if {[lsearch -exact $rowids $p] < 0} {
6318 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006319 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006320 }
6321 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006322 } else {
6323 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006324 }
6325 }
6326 }
6327}
6328
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006329proc undolayout {row} {
6330 global uparrowlen mingaplen downarrowlen
6331 global rowidlist rowisopt rowfinal need_redisplay
6332
6333 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6334 if {$r < 0} {
6335 set r 0
6336 }
6337 if {[llength $rowidlist] > $r} {
6338 incr r -1
6339 set rowidlist [lrange $rowidlist 0 $r]
6340 set rowfinal [lrange $rowfinal 0 $r]
6341 set rowisopt [lrange $rowisopt 0 $r]
6342 set need_redisplay 1
6343 run drawvisible
6344 }
6345}
6346
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006347proc drawvisible {} {
6348 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006349 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006350
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006351 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006352 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006353 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006354 set f0 [lindex $fs 0]
6355 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006356 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006357 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006358
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006359 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11006360 if {[commitinview $targetid $curview]} {
6361 set r [rowofcommit $targetid]
6362 if {$r != $targetrow} {
6363 # Fix up the scrollregion and change the scrolling position
6364 # now that our target row has moved.
6365 set diff [expr {($r - $targetrow) * $linespc}]
6366 set targetrow $r
6367 setcanvscroll
6368 set ymax [lindex [$canv cget -scrollregion] 3]
6369 incr y0 $diff
6370 incr y1 $diff
6371 set f0 [expr {$y0 / $ymax}]
6372 set f1 [expr {$y1 / $ymax}]
6373 allcanvs yview moveto $f0
6374 $cscroll set $f0 $f1
6375 set need_redisplay 1
6376 }
6377 } else {
6378 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006379 }
6380 }
6381
6382 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6383 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6384 if {$endrow >= $vrowmod($curview)} {
6385 update_arcrows $curview
6386 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006387 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006388 $row <= $selectedline && $selectedline <= $endrow} {
6389 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006390 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006391 set targetrow [expr {int(($row + $endrow) / 2)}]
6392 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006393 if {[info exists targetrow]} {
6394 if {$targetrow >= $numcommits} {
6395 set targetrow [expr {$numcommits - 1}]
6396 }
6397 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006398 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006399 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006400}
6401
6402proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006403 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006404 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006405 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006406
6407 allcanvs delete all
Paul Mackerras009409f2015-05-02 20:53:36 +10006408 unset -nocomplain iddrawn
6409 unset -nocomplain linesegs
6410 unset -nocomplain linehtag
6411 unset -nocomplain linentag
6412 unset -nocomplain linedtag
Paul Mackerras28593d32008-11-13 23:01:46 +11006413 set boldids {}
6414 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10006415 unset -nocomplain vhighlights
6416 unset -nocomplain fhighlights
6417 unset -nocomplain nhighlights
6418 unset -nocomplain rhighlights
Paul Mackerras03800812007-08-29 21:45:21 +10006419 set need_redisplay 0
6420 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006421}
6422
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006423proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006424 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006425
6426 set cross {}
6427 set ccross {}
6428 foreach {s e} [rowranges $id] {
6429 if {$e >= $numcommits} {
6430 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006431 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006432 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006433 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006434 set x [lsearch -exact [lindex $rowidlist $row] $id]
6435 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006436 set olds [lindex $parentlist $row]
6437 set kid [lindex $displayorder $row]
6438 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6439 if {$kidx < 0} continue
6440 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6441 foreach p $olds {
6442 set px [lsearch -exact $nextrow $p]
6443 if {$px < 0} continue
6444 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6445 if {[lsearch -exact $ccross $p] >= 0} continue
6446 if {$x == $px + ($kidx < $px? -1: 1)} {
6447 lappend ccross $p
6448 } elseif {[lsearch -exact $cross $p] < 0} {
6449 lappend cross $p
6450 }
6451 }
6452 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006453 }
6454 }
6455 return [concat $ccross {{}} $cross]
6456}
6457
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006458proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006459 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006460 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006461
Paul Mackerras418c4c72006-02-07 09:10:18 +11006462 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006463 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006464 if {[info exists children($curview,$id)]} {
6465 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006466 } else {
6467 set kids {}
6468 }
6469 if {[llength $kids] == 1} {
6470 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006471 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006472 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006473 set colormap($id) $colormap($child)
6474 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006475 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006476 }
6477 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006478 set origbad {}
6479 foreach x [findcrossings $id] {
6480 if {$x eq {}} {
6481 # delimiter between corner crossings and other crossings
6482 if {[llength $badcolors] >= $ncolors - 1} break
6483 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006484 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006485 if {[info exists colormap($x)]
6486 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6487 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006488 }
6489 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006490 if {[llength $badcolors] >= $ncolors} {
6491 set badcolors $origbad
6492 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006493 set origbad $badcolors
6494 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006495 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006496 if {[info exists colormap($child)]
6497 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6498 lappend badcolors $colormap($child)
6499 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006500 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006501 if {[info exists colormap($p)]
6502 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6503 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006504 }
6505 }
6506 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006507 if {[llength $badcolors] >= $ncolors} {
6508 set badcolors $origbad
6509 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006510 }
6511 for {set i 0} {$i <= $ncolors} {incr i} {
6512 set c [lindex $colors $nextcolor]
6513 if {[incr nextcolor] >= $ncolors} {
6514 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006515 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006516 if {[lsearch -exact $badcolors $c]} break
6517 }
6518 set colormap($id) $c
6519}
6520
Paul Mackerrasa823a912005-06-21 10:01:38 +10006521proc bindline {t id} {
6522 global canv
6523
Paul Mackerrasa823a912005-06-21 10:01:38 +10006524 $canv bind $t <Enter> "lineenter %x %y $id"
6525 $canv bind $t <Motion> "linemotion %x %y $id"
6526 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006527 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006528}
6529
Paul Mackerras4399fe32013-01-03 10:10:31 +11006530proc graph_pane_width {} {
6531 global use_ttk
6532
6533 if {$use_ttk} {
6534 set g [.tf.histframe.pwclist sashpos 0]
6535 } else {
6536 set g [.tf.histframe.pwclist sash coord 0]
6537 }
6538 return [lindex $g 0]
6539}
6540
6541proc totalwidth {l font extra} {
6542 set tot 0
6543 foreach str $l {
6544 set tot [expr {$tot + [font measure $font $str] + $extra}]
6545 }
6546 return $tot
6547}
6548
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006549proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006550 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006551 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006552 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006553 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6554 global tagbgcolor tagfgcolor tagoutlinecolor
6555 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006556
6557 set marks {}
6558 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006559 set nheads 0
Paul Mackerras4399fe32013-01-03 10:10:31 +11006560 set singletag 0
6561 set maxtags 3
6562 set maxtagpct 25
6563 set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
6564 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
6565 set extra [expr {$delta + $lthickness + $linespc}]
6566
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006567 if {[info exists idtags($id)]} {
6568 set marks $idtags($id)
6569 set ntags [llength $marks]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006570 if {$ntags > $maxtags ||
6571 [totalwidth $marks mainfont $extra] > $maxwidth} {
6572 # show just a single "n tags..." tag
6573 set singletag 1
6574 if {$ntags == 1} {
6575 set marks [list "tag..."]
6576 } else {
6577 set marks [list [format "%d tags..." $ntags]]
6578 }
6579 set ntags 1
6580 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006581 }
6582 if {[info exists idheads($id)]} {
6583 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006584 set nheads [llength $idheads($id)]
6585 }
6586 if {[info exists idotherrefs($id)]} {
6587 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006588 }
6589 if {$marks eq {}} {
6590 return $xt
6591 }
6592
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006593 set yt [expr {$y1 - 0.5 * $linespc}]
6594 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006595 set xvals {}
6596 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006597 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006598 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006599 incr i
6600 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006601 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006602 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006603 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006604 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006605 lappend xvals $xt
6606 lappend wvals $wid
Paul Mackerras4399fe32013-01-03 10:10:31 +11006607 set xt [expr {$xt + $wid + $extra}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006608 }
6609 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006610 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006611 $canv lower $t
6612 foreach tag $marks x $xvals wid $wvals {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006613 set tag_quoted [string map {% %%} $tag]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006614 set xl [expr {$x + $delta}]
6615 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006616 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006617 if {[incr ntags -1] >= 0} {
6618 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006619 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6620 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006621 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6622 -tags tag.$id]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006623 if {$singletag} {
6624 set tagclick [list showtags $id 1]
6625 } else {
6626 set tagclick [list showtag $tag_quoted 1]
6627 }
6628 $canv bind $t <1> $tagclick
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006629 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006630 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006631 # draw a head or other ref
6632 if {[incr nheads -1] >= 0} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006633 set col $headbgcolor
Paul Mackerras8a485712006-07-06 10:21:23 +10006634 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006635 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006636 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006637 } else {
6638 set col "#ddddff"
6639 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006640 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006641 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006642 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006643 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006644 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006645 set xi [expr {$x + 1}]
6646 set yti [expr {$yt + 1}]
6647 set xri [expr {$x + $rwid}]
6648 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006649 -width 0 -fill $remotebgcolor -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006650 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006651 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006652 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006653 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006654 if {$ntags >= 0} {
Paul Mackerras4399fe32013-01-03 10:10:31 +11006655 $canv bind $t <1> $tagclick
Paul Mackerras10299152006-08-02 09:52:01 +10006656 } elseif {$nheads >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006657 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
Paul Mackerras106288c2005-08-19 23:11:39 +10006658 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006659 }
6660 return $xt
6661}
6662
Raphael Zimmerer36242492011-04-19 22:37:09 +02006663proc drawnotesign {xt y} {
6664 global linespc canv fgcolor
6665
6666 set orad [expr {$linespc / 3}]
6667 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
6668 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6669 -fill yellow -outline $fgcolor -width 1 -tags circle]
6670 set xt [expr {$xt + $orad * 3}]
6671 return $xt
6672}
6673
Paul Mackerras8d858d12005-08-05 09:52:16 +10006674proc xcoord {i level ln} {
6675 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006676
Paul Mackerras8d858d12005-08-05 09:52:16 +10006677 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6678 if {$i > 0 && $i == $level} {
6679 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6680 } elseif {$i > $level} {
6681 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6682 }
6683 return $x
6684}
6685
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006686proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006687 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006688
6689 clear_display
Marc Branchaud9922c5a2015-04-07 11:51:51 -04006690 set_window_title
Paul Mackerras9c311b32007-10-04 22:27:13 +10006691 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006692 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006693}
6694
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006695# Don't change the text pane cursor if it is currently the hand cursor,
6696# showing that we are over a sha1 ID link.
6697proc settextcursor {c} {
6698 global ctext curtextcursor
6699
6700 if {[$ctext cget -cursor] == $curtextcursor} {
6701 $ctext config -cursor $c
6702 }
6703 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006704}
6705
Paul Mackerrasa137a902007-10-23 21:12:49 +10006706proc nowbusy {what {name {}}} {
6707 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006708
6709 if {[array names isbusy] eq {}} {
6710 . config -cursor watch
6711 settextcursor watch
6712 }
6713 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006714 set busyname($what) $name
6715 if {$name ne {}} {
6716 $statusw conf -text $name
6717 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006718}
6719
6720proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006721 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006722
Paul Mackerrasa137a902007-10-23 21:12:49 +10006723 catch {
6724 unset isbusy($what)
6725 if {$busyname($what) ne {} &&
6726 [$statusw cget -text] eq $busyname($what)} {
6727 $statusw conf -text {}
6728 }
6729 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006730 if {[array names isbusy] eq {}} {
6731 . config -cursor $maincursor
6732 settextcursor $textcursor
6733 }
6734}
6735
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006736proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006737 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006738 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006739 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006740 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006741 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006742 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006743 set f [string tolower $f]
6744 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006745 }
6746 set matches {}
6747 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006748 set l [string length $fs]
6749 while {[set j [string first $fs $f $i]] >= 0} {
6750 lappend matches [list $j [expr {$j+$l-1}]]
6751 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006752 }
6753 }
6754 return $matches
6755}
6756
Paul Mackerrascca5d942007-10-27 21:16:56 +10006757proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006758 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006759 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006760
Paul Mackerrascca5d942007-10-27 21:16:56 +10006761 if {[info exists find_dirn]} {
6762 if {$find_dirn == $dirn} return
6763 stopfinding
6764 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006765 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006766 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006767 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006768 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006769 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006770 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006771 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006772 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006773 nowbusy finding [mc "Searching"]
6774 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006775 after cancel do_file_hl $fh_serial
6776 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006777 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006778 set find_dirn $dirn
6779 set findallowwrap $wrap
6780 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006781}
6782
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006783proc stopfinding {} {
6784 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006785
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006786 if {[info exists find_dirn]} {
6787 unset find_dirn
6788 unset findcurline
6789 notbusy finding
6790 set fprogcoord 0
6791 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006792 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006793 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006794}
6795
6796proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006797 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006798 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006799 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006800 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006801
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006802 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006803 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006804 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006805 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006806 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006807 set moretodo 0
6808 if {$find_dirn > 0} {
6809 incr l
6810 if {$l >= $numcommits} {
6811 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006812 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006813 if {$l <= $findstartline} {
6814 set lim [expr {$findstartline + 1}]
6815 } else {
6816 set lim $numcommits
6817 set moretodo $findallowwrap
6818 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006819 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006820 if {$l == 0} {
6821 set l $numcommits
6822 }
6823 incr l -1
6824 if {$l >= $findstartline} {
6825 set lim [expr {$findstartline - 1}]
6826 } else {
6827 set lim -1
6828 set moretodo $findallowwrap
6829 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006830 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006831 set n [expr {($lim - $l) * $find_dirn}]
6832 if {$n > 500} {
6833 set n 500
6834 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006835 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006836 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6837 update_arcrows $curview
6838 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006839 set found 0
6840 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006841 set ai [bsearch $vrownum($curview) $l]
6842 set a [lindex $varcorder($curview) $ai]
6843 set arow [lindex $vrownum($curview) $ai]
6844 set ids [lindex $varccommits($curview,$a)]
6845 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006846 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006847 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006848 if {$l < $arow || $l >= $arowend} {
6849 incr ai $find_dirn
6850 set a [lindex $varcorder($curview) $ai]
6851 set arow [lindex $vrownum($curview) $ai]
6852 set ids [lindex $varccommits($curview,$a)]
6853 set arowend [expr {$arow + [llength $ids]}]
6854 }
6855 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006856 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006857 if {![info exists commitdata($id)] ||
6858 ![doesmatch $commitdata($id)]} {
6859 continue
6860 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006861 if {![info exists commitinfo($id)]} {
6862 getcommit $id
6863 }
6864 set info $commitinfo($id)
6865 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04006866 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01006867 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006868 [doesmatch $f]} {
6869 set found 1
6870 break
6871 }
6872 }
6873 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006874 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006875 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006876 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006877 if {$l < $arow || $l >= $arowend} {
6878 incr ai $find_dirn
6879 set a [lindex $varcorder($curview) $ai]
6880 set arow [lindex $vrownum($curview) $ai]
6881 set ids [lindex $varccommits($curview,$a)]
6882 set arowend [expr {$arow + [llength $ids]}]
6883 }
6884 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006885 if {![info exists fhighlights($id)]} {
6886 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006887 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006888 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006889 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006890 set found $domore
6891 break
6892 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006893 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006894 if {$domore} {
6895 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006896 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006897 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006898 }
6899 }
6900 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006901 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006902 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006903 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006904 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006905 set fprogcoord 0
6906 adjustprogress
6907 if {$found} {
6908 findselectline $l
6909 } else {
6910 bell
6911 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006912 return 0
6913 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006914 if {!$domore} {
6915 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006916 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006917 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006918 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006919 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006920 if {$n < 0} {
6921 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006922 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006923 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6924 adjustprogress
6925 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006926}
6927
6928proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006929 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006930
Paul Mackerras8b39e042008-12-02 09:02:46 +11006931 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006932 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006933 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006934 if {$markingmatches &&
6935 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006936 # highlight the matches in the comments
6937 set f [$ctext get 1.0 $commentend]
6938 set matches [findmatches $f]
6939 foreach match $matches {
6940 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006941 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006942 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6943 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006944 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006945 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006946}
6947
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006948# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006949proc markmatches {canv l str tag matches font row} {
6950 global selectedline
6951
Paul Mackerras98f350e2005-05-15 05:56:51 +00006952 set bbox [$canv bbox $tag]
6953 set x0 [lindex $bbox 0]
6954 set y0 [lindex $bbox 1]
6955 set y1 [lindex $bbox 3]
6956 foreach match $matches {
6957 set start [lindex $match 0]
6958 set end [lindex $match 1]
6959 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006960 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6961 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6962 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6963 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006964 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006965 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006966 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006967 $canv raise $t secsel
6968 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006969 }
6970}
6971
6972proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006973 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006974
Paul Mackerras98f350e2005-05-15 05:56:51 +00006975 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006976 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006977 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006978}
6979
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006980proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006981 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006982 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006983 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006984 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006985 set yfrac [lindex [$canv yview] 0]
6986 set y [expr {$y + $yfrac * $ymax}]
6987 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6988 if {$l < 0} {
6989 set l 0
6990 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006991 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006992 set xmax [lindex [$canv cget -scrollregion] 2]
6993 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6994 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006995 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006996 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006997 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006998}
6999
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007000proc commit_descriptor {p} {
7001 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10007002 if {![info exists commitinfo($p)]} {
7003 getcommit $p
7004 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007005 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10007006 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007007 set l [lindex $commitinfo($p) 0]
7008 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007009 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007010}
7011
Paul Mackerras106288c2005-08-19 23:11:39 +10007012# append some text to the ctext widget, and make any SHA1 ID
7013# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007014proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007015 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10007016
7017 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007018 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007019 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10007020 foreach l $links {
7021 set s [lindex $l 0]
7022 set e [lindex $l 1]
7023 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10007024 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10007025 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007026 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10007027 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007028 incr linknum
7029 }
Paul Mackerras97645682007-08-23 22:24:38 +10007030}
7031
7032proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007033 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007034 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10007035
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007036 if {[string range $id 0 1] eq "-g"} {
7037 set id [string range $id 2 end]
7038 }
7039
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007040 set known 0
7041 if {[string length $id] < 40} {
7042 set matches [longid $id]
7043 if {[llength $matches] > 0} {
7044 if {[llength $matches] > 1} return
7045 set known 1
7046 set id [lindex $matches 0]
7047 }
7048 } else {
7049 set known [commitinview $id $curview]
7050 }
7051 if {$known} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007052 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007053 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10007054 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7055 $ctext tag bind $lk <Leave> {linkcursor %W -1}
7056 } else {
7057 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007058 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10007059 }
7060}
7061
Paul Mackerras6f63fc12009-04-21 22:22:31 +10007062proc appendshortlink {id {pre {}} {post {}}} {
7063 global ctext linknum
7064
7065 $ctext insert end $pre
7066 $ctext tag delete link$linknum
7067 $ctext insert end [string range $id 0 7] link$linknum
7068 $ctext insert end $post
7069 setlink $id link$linknum
7070 incr linknum
7071}
7072
Paul Mackerras97645682007-08-23 22:24:38 +10007073proc makelink {id} {
7074 global pendinglinks
7075
7076 if {![info exists pendinglinks($id)]} return
7077 foreach lk $pendinglinks($id) {
7078 setlink $id $lk
7079 }
7080 unset pendinglinks($id)
7081}
7082
7083proc linkcursor {w inc} {
7084 global linkentercount curtextcursor
7085
7086 if {[incr linkentercount $inc] > 0} {
7087 $w configure -cursor hand2
7088 } else {
7089 $w configure -cursor $curtextcursor
7090 if {$linkentercount < 0} {
7091 set linkentercount 0
7092 }
7093 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007094}
7095
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007096proc viewnextline {dir} {
7097 global canv linespc
7098
7099 $canv delete hover
7100 set ymax [lindex [$canv cget -scrollregion] 3]
7101 set wnow [$canv yview]
7102 set wtop [expr {[lindex $wnow 0] * $ymax}]
7103 set newtop [expr {$wtop + $dir * $linespc}]
7104 if {$newtop < 0} {
7105 set newtop 0
7106 } elseif {$newtop > $ymax} {
7107 set newtop $ymax
7108 }
7109 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7110}
7111
Paul Mackerrasef030b82006-06-04 11:50:38 +10007112# add a list of tag or branch names at position pos
7113# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10007114proc appendrefs {pos ids var} {
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007115 global ctext linknum curview $var maxrefs visiblerefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007116
Paul Mackerrasef030b82006-06-04 11:50:38 +10007117 if {[catch {$ctext index $pos}]} {
7118 return 0
7119 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007120 $ctext conf -state normal
7121 $ctext delete $pos "$pos lineend"
7122 set tags {}
7123 foreach id $ids {
7124 foreach tag [set $var\($id\)] {
7125 lappend tags [list $tag $id]
7126 }
7127 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007128
7129 set sep {}
7130 set tags [lsort -index 0 -decreasing $tags]
7131 set nutags 0
7132
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007133 if {[llength $tags] > $maxrefs} {
Paul Mackerras386befb2013-01-02 15:25:29 +11007134 # If we are displaying heads, and there are too many,
7135 # see if there are some important heads to display.
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007136 # Currently that are the current head and heads listed in $visiblerefs option
Paul Mackerras386befb2013-01-02 15:25:29 +11007137 set itags {}
7138 if {$var eq "idheads"} {
7139 set utags {}
7140 foreach ti $tags {
7141 set hname [lindex $ti 0]
7142 set id [lindex $ti 1]
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007143 if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
Paul Mackerras386befb2013-01-02 15:25:29 +11007144 [llength $itags] < $maxrefs} {
7145 lappend itags $ti
7146 } else {
7147 lappend utags $ti
7148 }
7149 }
7150 set tags $utags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007151 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007152 if {$itags ne {}} {
7153 set str [mc "and many more"]
7154 set sep " "
7155 } else {
7156 set str [mc "many"]
7157 }
7158 $ctext insert $pos "$str ([llength $tags])"
7159 set nutags [llength $tags]
7160 set tags $itags
7161 }
7162
7163 foreach ti $tags {
7164 set id [lindex $ti 1]
7165 set lk link$linknum
7166 incr linknum
7167 $ctext tag delete $lk
7168 $ctext insert $pos $sep
7169 $ctext insert $pos [lindex $ti 0] $lk
7170 setlink $id $lk
7171 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007172 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11007173 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007174 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11007175 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007176}
7177
7178# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10007179proc dispneartags {delay} {
7180 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007181
Paul Mackerras94b4a692008-05-20 20:51:06 +10007182 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007183 after cancel dispnexttag
7184 if {$delay} {
7185 after 200 dispnexttag
7186 set tagphase -1
7187 } else {
7188 after idle dispnexttag
7189 set tagphase 0
7190 }
7191}
7192
7193proc dispnexttag {} {
7194 global selectedline currentid showneartags tagphase ctext
7195
Paul Mackerras94b4a692008-05-20 20:51:06 +10007196 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007197 switch -- $tagphase {
7198 0 {
7199 set dtags [desctags $currentid]
7200 if {$dtags ne {}} {
7201 appendrefs precedes $dtags idtags
7202 }
7203 }
7204 1 {
7205 set atags [anctags $currentid]
7206 if {$atags ne {}} {
7207 appendrefs follows $atags idtags
7208 }
7209 }
7210 2 {
7211 set dheads [descheads $currentid]
7212 if {$dheads ne {}} {
7213 if {[appendrefs branch $dheads idheads] > 1
7214 && [$ctext get "branch -3c"] eq "h"} {
7215 # turn "Branch" into "Branches"
7216 $ctext conf -state normal
7217 $ctext insert "branch -2c" "es"
7218 $ctext conf -state disabled
7219 }
7220 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007221 }
7222 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007223 if {[incr tagphase] <= 2} {
7224 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007225 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007226}
7227
Paul Mackerras28593d32008-11-13 23:01:46 +11007228proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007229 global linehtag linentag linedtag canv canv2 canv3
7230
Paul Mackerras28593d32008-11-13 23:01:46 +11007231 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007232 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007233 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007234 -tags secsel -fill [$canv cget -selectbackground]]
7235 $canv lower $t
7236 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007237 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007238 -tags secsel -fill [$canv2 cget -selectbackground]]
7239 $canv2 lower $t
7240 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007241 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007242 -tags secsel -fill [$canv3 cget -selectbackground]]
7243 $canv3 lower $t
7244}
7245
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007246proc make_idmark {id} {
7247 global linehtag canv fgcolor
7248
7249 if {![info exists linehtag($id)]} return
7250 $canv delete markid
7251 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
7252 -tags markid -outline $fgcolor]
7253 $canv raise $t
7254}
7255
Max Kirillov4135d362014-04-05 23:38:50 +03007256proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007257 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007258 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007259 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007260 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007261 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007262 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007263 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007264 global autoselect autosellen jump_to_here
Thomas Rast9403bd02013-11-16 18:37:43 +01007265 global vinlinediff
Paul Mackerrasd6982062005-08-06 22:06:06 +10007266
Paul Mackerras009409f2015-05-02 20:53:36 +10007267 unset -nocomplain pending_select
Paul Mackerras84ba7342005-06-17 00:12:26 +00007268 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007269 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007270 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007271 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007272 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007273 set id [commitonrow $l]
7274 set targetid $id
7275 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007276 set selectedline $l
7277 set currentid $id
7278 if {$lastscrollrows < $numcommits} {
7279 setcanvscroll
7280 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007281
Max Kirillov4135d362014-04-05 23:38:50 +03007282 if {$cmitmode ne "patch" && $switch_to_patch} {
7283 set cmitmode "patch"
7284 }
7285
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007286 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007287 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007288 set ytop [expr {$y - $linespc - 1}]
7289 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007290 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007291 set wtop [expr {[lindex $wnow 0] * $ymax}]
7292 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007293 set wh [expr {$wbot - $wtop}]
7294 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007295 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00007296 if {$ybot < $wtop} {
7297 set newtop [expr {$y - $wh / 2.0}]
7298 } else {
7299 set newtop $ytop
7300 if {$newtop > $wtop - $linespc} {
7301 set newtop [expr {$wtop - $linespc}]
7302 }
Paul Mackerras17386062005-05-18 22:51:00 +00007303 }
Paul Mackerras58422152005-05-19 10:56:42 +00007304 } elseif {$ybot > $wbot} {
7305 if {$ytop > $wbot} {
7306 set newtop [expr {$y - $wh / 2.0}]
7307 } else {
7308 set newtop [expr {$ybot - $wh}]
7309 if {$newtop < $wtop + $linespc} {
7310 set newtop [expr {$wtop + $linespc}]
7311 }
Paul Mackerras17386062005-05-18 22:51:00 +00007312 }
Paul Mackerras58422152005-05-19 10:56:42 +00007313 }
7314 if {$newtop != $wtop} {
7315 if {$newtop < 0} {
7316 set newtop 0
7317 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007318 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007319 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007320 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007321
Paul Mackerras28593d32008-11-13 23:01:46 +11007322 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007323
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007324 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007325 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007326 }
7327
Paul Mackerras98f350e2005-05-15 05:56:51 +00007328 $sha1entry delete 0 end
7329 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007330 if {$autoselect} {
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007331 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007332 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007333 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007334
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007335 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007336 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007337 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007338 if {![info exists commitinfo($id)]} {
7339 getcommit $id
7340 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007341 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007342 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007343 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007344 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007345 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007346 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007347 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007348 foreach tag $idtags($id) {
7349 $ctext insert end " $tag"
7350 }
7351 $ctext insert end "\n"
7352 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007353
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007354 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007355 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007356 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007357 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007358 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007359 if {$np >= $mergemax} {
7360 set tag mmax
7361 } else {
7362 set tag m$np
7363 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007364 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007365 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007366 incr np
7367 }
7368 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007369 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007370 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007371 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007372 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007373
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007374 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007375 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007376 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007377
7378 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007379 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007380 if {$showneartags} {
7381 if {![info exists allcommits]} {
7382 getallcommits
7383 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007384 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10007385 $ctext mark set branch "end -1c"
7386 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007387 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007388 $ctext mark set follows "end -1c"
7389 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007390 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007391 $ctext mark set precedes "end -1c"
7392 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007393 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007394 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007395 }
7396 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007397 set comment [lindex $info 5]
7398 if {[string first "\r" $comment] >= 0} {
7399 set comment [string map {"\r" "\n "} $comment]
7400 }
7401 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007402
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007403 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007404 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007405 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007406
Paul Mackerras8a897742008-10-27 21:36:25 +11007407 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007408 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007409 if {$cmitmode eq "tree"} {
7410 gettree $id
Thomas Rast9403bd02013-11-16 18:37:43 +01007411 } elseif {$vinlinediff($curview) == 1} {
7412 showinlinediff $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007413 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11007414 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007415 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007416 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007417 }
7418}
7419
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007420proc selfirstline {} {
7421 unmarkmatches
7422 selectline 0 1
7423}
7424
7425proc sellastline {} {
7426 global numcommits
7427 unmarkmatches
7428 set l [expr {$numcommits - 1}]
7429 selectline $l 1
7430}
7431
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007432proc selnextline {dir} {
7433 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007434 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007435 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007436 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007437 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007438 selectline $l 1
7439}
7440
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007441proc selnextpage {dir} {
7442 global canv linespc selectedline numcommits
7443
7444 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7445 if {$lpp < 1} {
7446 set lpp 1
7447 }
7448 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007449 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007450 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007451 set l [expr {$selectedline + $dir * $lpp}]
7452 if {$l < 0} {
7453 set l 0
7454 } elseif {$l >= $numcommits} {
7455 set l [expr $numcommits - 1]
7456 }
7457 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007458 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007459}
7460
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007461proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007462 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007463
Paul Mackerras94b4a692008-05-20 20:51:06 +10007464 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +10007465 unset -nocomplain currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007466 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007467 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007468}
7469
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007470proc reselectline {} {
7471 global selectedline
7472
Paul Mackerras94b4a692008-05-20 20:51:06 +10007473 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007474 selectline $selectedline 0
7475 }
7476}
7477
Paul Mackerras354af6b2008-11-23 13:14:23 +11007478proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007479 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007480
Paul Mackerras354af6b2008-11-23 13:14:23 +11007481 unset_posvars
7482 save_position
7483 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007484 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10007485 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007486 return
7487 }
7488
7489 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007490 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007491 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007492 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007493 }
7494 incr historyindex
7495 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007496 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007497 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007498 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007499 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007500 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007501}
7502
Paul Mackerras354af6b2008-11-23 13:14:23 +11007503# save the scrolling position of the diff display pane
7504proc save_position {} {
7505 global historyindex history
7506
7507 if {$historyindex < 1} return
7508 set hi [expr {$historyindex - 1}]
7509 set fn [lindex $history $hi 2]
7510 if {$fn ne {}} {
7511 lset history $hi 3 [eval $fn]
7512 }
7513}
7514
7515proc unset_posvars {} {
7516 global last_posvars
7517
7518 if {[info exists last_posvars]} {
7519 foreach {var val} $last_posvars {
7520 global $var
Paul Mackerras009409f2015-05-02 20:53:36 +10007521 unset -nocomplain $var
Paul Mackerras354af6b2008-11-23 13:14:23 +11007522 }
7523 unset last_posvars
7524 }
7525}
7526
Paul Mackerras2516dae2006-04-21 10:35:31 +10007527proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007528 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007529
7530 set view [lindex $elt 0]
7531 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007532 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007533 if {$curview != $view} {
7534 showview $view
7535 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007536 unset_posvars
7537 foreach {var val} $pv {
7538 global $var
7539 set $var $val
7540 }
7541 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007542 eval $cmd
7543}
7544
Paul Mackerrasd6982062005-08-06 22:06:06 +10007545proc goback {} {
7546 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007547 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007548
7549 if {$historyindex > 1} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007550 save_position
Paul Mackerrasd6982062005-08-06 22:06:06 +10007551 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10007552 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007553 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007554 }
7555 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007556 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007557 }
7558}
7559
7560proc goforw {} {
7561 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007562 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007563
7564 if {$historyindex < [llength $history]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007565 save_position
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007566 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10007567 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10007568 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007569 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007570 }
7571 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007572 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007573 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007574}
7575
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007576proc go_to_parent {i} {
7577 global parents curview targetid
7578 set ps $parents($curview,$targetid)
7579 if {[llength $ps] >= $i} {
7580 selbyid [lindex $ps [expr $i - 1]]
7581 }
7582}
7583
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007584proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007585 global treefilelist treeidlist diffids diffmergeid treepending
7586 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007587
7588 set diffids $id
Paul Mackerras009409f2015-05-02 20:53:36 +10007589 unset -nocomplain diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007590 if {![info exists treefilelist($id)]} {
7591 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007592 if {$id eq $nullid} {
7593 set cmd [list | git ls-files]
7594 } elseif {$id eq $nullid2} {
7595 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007596 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007597 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007598 }
7599 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007600 return
7601 }
7602 set treepending $id
7603 set treefilelist($id) {}
7604 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007605 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007606 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007607 }
7608 } else {
7609 setfilelist $id
7610 }
7611}
7612
7613proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007614 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007615
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007616 set nl 0
7617 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007618 if {$diffids eq $nullid} {
7619 set fname $line
7620 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007621 set i [string first "\t" $line]
7622 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007623 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007624 set line [string range $line 0 [expr {$i-1}]]
7625 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7626 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007627 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007628 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007629 if {[string index $fname 0] eq "\""} {
7630 set fname [lindex $fname 0]
7631 }
7632 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007633 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007634 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007635 if {![eof $gtf]} {
7636 return [expr {$nl >= 1000? 2: 1}]
7637 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007638 close $gtf
7639 unset treepending
7640 if {$cmitmode ne "tree"} {
7641 if {![info exists diffmergeid]} {
7642 gettreediffs $diffids
7643 }
7644 } elseif {$id ne $diffids} {
7645 gettree $diffids
7646 } else {
7647 setfilelist $id
7648 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007649 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007650}
7651
7652proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007653 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007654 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007655 global ctext commentend
7656
7657 set i [lsearch -exact $treefilelist($diffids) $f]
7658 if {$i < 0} {
7659 puts "oops, $f not in list for id $diffids"
7660 return
7661 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007662 if {$diffids eq $nullid} {
7663 if {[catch {set bf [open $f r]} err]} {
7664 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007665 return
7666 }
7667 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007668 set blob [lindex $treeidlist($diffids) $i]
7669 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7670 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007671 return
7672 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007673 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007674 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007675 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007676 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007677 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007678 lappend ctext_file_names $f
7679 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007680 $ctext insert end "\n"
7681 $ctext insert end "$f\n" filesep
7682 $ctext config -state disabled
7683 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007684 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007685}
7686
7687proc getblobline {bf id} {
7688 global diffids cmitmode ctext
7689
7690 if {$id ne $diffids || $cmitmode ne "tree"} {
7691 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007692 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007693 }
7694 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007695 set nl 0
7696 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007697 $ctext insert end "$line\n"
7698 }
7699 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007700 global jump_to_here ctext_file_names commentend
7701
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007702 # delete last newline
7703 $ctext delete "end - 2c" "end - 1c"
7704 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007705 if {$jump_to_here ne {} &&
7706 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7707 set lnum [expr {[lindex $jump_to_here 1] +
7708 [lindex [split $commentend .] 0]}]
7709 mark_ctext_line $lnum
7710 }
Stefan Haller120ea892010-11-14 13:21:50 +01007711 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007712 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007713 }
7714 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007715 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007716}
7717
Paul Mackerras8a897742008-10-27 21:36:25 +11007718proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007719 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007720
7721 $ctext tag delete omark
7722 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007723 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007724 $ctext see $lnum.0
7725}
7726
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007727proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007728 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007729 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007730 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007731
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007732 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007733 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007734 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007735 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007736 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007737 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007738}
7739
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007740proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007741 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007742
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007743 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007744 set diffids $ids
Paul Mackerras009409f2015-05-02 20:53:36 +10007745 unset -nocomplain diffmergeid
Paul Mackerras8f489362007-07-13 19:49:37 +10007746 if {![info exists treediffs($ids)] ||
7747 [lsearch -exact $ids $nullid] >= 0 ||
7748 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007749 if {![info exists treepending]} {
7750 gettreediffs $ids
7751 }
7752 } else {
7753 addtocflist $ids
7754 }
7755}
7756
Thomas Rast9403bd02013-11-16 18:37:43 +01007757proc showinlinediff {ids} {
7758 global commitinfo commitdata ctext
7759 global treediffs
7760
7761 set info $commitinfo($ids)
7762 set diff [lindex $info 7]
7763 set difflines [split $diff "\n"]
7764
7765 initblobdiffvars
7766 set treediff {}
7767
7768 set inhdr 0
7769 foreach line $difflines {
7770 if {![string compare -length 5 "diff " $line]} {
7771 set inhdr 1
7772 } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
7773 # offset also accounts for the b/ prefix
7774 lappend treediff [string range $line 6 end]
7775 set inhdr 0
7776 }
7777 }
7778
7779 set treediffs($ids) $treediff
7780 add_flist $treediff
7781
7782 $ctext conf -state normal
7783 foreach line $difflines {
7784 parseblobdiffline $ids $line
7785 }
7786 maybe_scroll_ctext 1
7787 $ctext conf -state disabled
7788}
7789
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007790# If the filename (name) is under any of the passed filter paths
7791# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007792proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007793 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007794 foreach p $filter {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007795 set fq_p [file normalize $p]
7796 set fq_n [file normalize [file join $worktree $name]]
7797 if {[string match [file normalize $fq_p]* $fq_n]} {
7798 return 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10007799 }
7800 }
7801 return 0
7802}
7803
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007804proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007805 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007806
Paul Mackerras74a40c72007-10-24 10:16:56 +10007807 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007808 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007809}
7810
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007811proc diffcmd {ids flags} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007812 global log_showroot nullid nullid2 git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007813
7814 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007815 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007816 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007817 if {[llength $ids] > 1 && $j < 0} {
7818 # comparing working directory with some specific revision
7819 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007820 if {$i == 0} {
7821 lappend cmd -R [lindex $ids 1]
7822 } else {
7823 lappend cmd [lindex $ids 0]
7824 }
7825 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007826 # comparing working directory with index
7827 set cmd [concat | git diff-files $flags]
7828 if {$j == 1} {
7829 lappend cmd -R
7830 }
7831 }
7832 } elseif {$j >= 0} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007833 if {[package vcompare $git_version "1.7.2"] >= 0} {
7834 set flags "$flags --ignore-submodules=dirty"
7835 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007836 set cmd [concat | git diff-index --cached $flags]
7837 if {[llength $ids] > 1} {
7838 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007839 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007840 lappend cmd -R [lindex $ids 1]
7841 } else {
7842 lappend cmd [lindex $ids 0]
7843 }
7844 } else {
7845 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007846 lappend cmd HEAD
7847 }
7848 } else {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007849 if {$log_showroot} {
7850 lappend flags --root
7851 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007852 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007853 }
7854 return $cmd
7855}
7856
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007857proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007858 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007859
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007860 set cmd [diffcmd $ids {--no-commit-id}]
7861 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7862 set cmd [concat $cmd -- $vfilelimit($curview)]
7863 }
7864 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007865
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007866 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007867 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007868 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007869 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007870}
7871
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007872proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007873 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007874 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007875
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007876 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007877 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007878 set max 1000
7879 if {$perfile_attrs} {
7880 # cache_gitattr is slow, and even slower on win32 where we
7881 # have to invoke it for only about 30 paths at a time
7882 set max 500
7883 if {[tk windowingsystem] == "win32"} {
7884 set max 120
7885 }
7886 }
7887 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007888 set i [string first "\t" $line]
7889 if {$i >= 0} {
7890 set file [string range $line [expr {$i+1}] end]
7891 if {[string index $file 0] eq "\""} {
7892 set file [lindex $file 0]
7893 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007894 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007895 if {$file ne [lindex $treediff end]} {
7896 lappend treediff $file
7897 lappend sublist $file
7898 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007899 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007900 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007901 if {$perfile_attrs} {
7902 cache_gitattr encoding $sublist
7903 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007904 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007905 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007906 }
7907 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007908 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007909 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007910 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007911 gettree $diffids
7912 } elseif {$ids != $diffids} {
7913 if {![info exists diffmergeid]} {
7914 gettreediffs $diffids
7915 }
7916 } else {
7917 addtocflist $ids
7918 }
7919 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007920}
7921
Steffen Prohaska890fae72007-08-12 12:05:46 +02007922# empty string or positive integer
7923proc diffcontextvalidate {v} {
7924 return [regexp {^(|[1-9][0-9]*)$} $v]
7925}
7926
7927proc diffcontextchange {n1 n2 op} {
7928 global diffcontextstring diffcontext
7929
7930 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007931 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007932 set diffcontext $diffcontextstring
7933 reselectline
7934 }
7935 }
7936}
7937
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007938proc changeignorespace {} {
7939 reselectline
7940}
7941
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007942proc changeworddiff {name ix op} {
7943 reselectline
7944}
7945
Thomas Rast5de460a2013-11-16 18:37:41 +01007946proc initblobdiffvars {} {
7947 global diffencoding targetline diffnparents
7948 global diffinhdr currdiffsubmod diffseehere
7949 set targetline {}
7950 set diffnparents 0
7951 set diffinhdr 0
7952 set diffencoding [get_path_encoding {}]
7953 set currdiffsubmod ""
7954 set diffseehere -1
7955}
7956
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007957proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007958 global blobdifffd diffids env
Thomas Rast5de460a2013-11-16 18:37:41 +01007959 global treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007960 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007961 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007962 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007963 global limitdiffs vfilelimit curview
Thomas Rast5de460a2013-11-16 18:37:41 +01007964 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007965
Paul Mackerrasa8138732009-05-16 21:06:01 +10007966 set textconv {}
7967 if {[package vcompare $git_version "1.6.1"] >= 0} {
7968 set textconv "--textconv"
7969 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01007970 set submodule {}
7971 if {[package vcompare $git_version "1.6.6"] >= 0} {
7972 set submodule "--submodule"
7973 }
7974 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007975 if {$ignorespace} {
7976 append cmd " -w"
7977 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007978 if {$worddiff ne [mc "Line diff"]} {
7979 append cmd " --word-diff=porcelain"
7980 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007981 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7982 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007983 }
7984 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007985 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007986 return
7987 }
Pat Thoyts681c3292009-03-16 10:24:40 +00007988 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007989 set blobdifffd($ids) $bdf
Thomas Rast5de460a2013-11-16 18:37:41 +01007990 initblobdiffvars
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007991 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007992}
7993
Paul Mackerras354af6b2008-11-23 13:14:23 +11007994proc savecmitpos {} {
7995 global ctext cmitmode
7996
7997 if {$cmitmode eq "tree"} {
7998 return {}
7999 }
8000 return [list target_scrollpos [$ctext index @0,0]]
8001}
8002
8003proc savectextpos {} {
8004 global ctext
8005
8006 return [list target_scrollpos [$ctext index @0,0]]
8007}
8008
8009proc maybe_scroll_ctext {ateof} {
8010 global ctext target_scrollpos
8011
8012 if {![info exists target_scrollpos]} return
8013 if {!$ateof} {
8014 set nlines [expr {[winfo height $ctext]
8015 / [font metrics textfont -linespace]}]
8016 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
8017 }
8018 $ctext yview $target_scrollpos
8019 unset target_scrollpos
8020}
8021
Paul Mackerras89b11d32006-05-02 19:55:31 +10008022proc setinlist {var i val} {
8023 global $var
8024
8025 while {[llength [set $var]] < $i} {
8026 lappend $var {}
8027 }
8028 if {[llength [set $var]] == $i} {
8029 lappend $var $val
8030 } else {
8031 lset $var $i $val
8032 }
8033}
8034
Paul Mackerras9396cd32007-06-23 20:28:15 +10008035proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008036 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11008037 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10008038
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008039 set fname [encoding convertfrom $fname]
8040 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10008041 set i [lsearch -exact $treediffs($ids) $fname]
8042 if {$i >= 0} {
8043 setinlist difffilestart $i $curdiffstart
8044 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11008045 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10008046 set l [expr {(78 - [string length $fname]) / 2}]
8047 set pad [string range "----------------------------------------" 1 $l]
8048 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11008049 set targetline {}
8050 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
8051 set targetline [lindex $jump_to_here 1]
8052 }
8053 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10008054}
8055
Thomas Rast5de460a2013-11-16 18:37:41 +01008056proc blobdiffmaybeseehere {ateof} {
8057 global diffseehere
8058 if {$diffseehere >= 0} {
8059 mark_ctext_line [lindex [split $diffseehere .] 0]
8060 }
Max Kirillov1f3c8722014-01-18 14:58:51 +02008061 maybe_scroll_ctext $ateof
Thomas Rast5de460a2013-11-16 18:37:41 +01008062}
8063
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008064proc getblobdiffline {bdf ids} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008065 global diffids blobdifffd
8066 global ctext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008067
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008068 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008069 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008070 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
8071 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008072 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008073 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10008074 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008075 parseblobdiffline $ids $line
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008076 }
8077 $ctext conf -state disabled
Thomas Rast5de460a2013-11-16 18:37:41 +01008078 blobdiffmaybeseehere [eof $bdf]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008079 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008080 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008081 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008082 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008083 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008084}
8085
Thomas Rast5de460a2013-11-16 18:37:41 +01008086proc parseblobdiffline {ids line} {
8087 global ctext curdiffstart
8088 global diffnexthead diffnextnote difffilestart
8089 global ctext_file_names ctext_file_lines
8090 global diffinhdr treediffs mergemax diffnparents
8091 global diffencoding jump_to_here targetline diffline currdiffsubmod
8092 global worddiff diffseehere
8093
8094 if {![string compare -length 5 "diff " $line]} {
8095 if {![regexp {^diff (--cc|--git) } $line m type]} {
8096 set line [encoding convertfrom $line]
8097 $ctext insert end "$line\n" hunksep
8098 continue
8099 }
8100 # start of a new file
8101 set diffinhdr 1
8102 $ctext insert end "\n"
8103 set curdiffstart [$ctext index "end - 1c"]
8104 lappend ctext_file_names ""
8105 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8106 $ctext insert end "\n" filesep
8107
8108 if {$type eq "--cc"} {
8109 # start of a new file in a merge diff
8110 set fname [string range $line 10 end]
8111 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
8112 lappend treediffs($ids) $fname
8113 add_flist [list $fname]
8114 }
8115
8116 } else {
8117 set line [string range $line 11 end]
8118 # If the name hasn't changed the length will be odd,
8119 # the middle char will be a space, and the two bits either
8120 # side will be a/name and b/name, or "a/name" and "b/name".
8121 # If the name has changed we'll get "rename from" and
8122 # "rename to" or "copy from" and "copy to" lines following
8123 # this, and we'll use them to get the filenames.
8124 # This complexity is necessary because spaces in the
8125 # filename(s) don't get escaped.
8126 set l [string length $line]
8127 set i [expr {$l / 2}]
8128 if {!(($l & 1) && [string index $line $i] eq " " &&
8129 [string range $line 2 [expr {$i - 1}]] eq \
8130 [string range $line [expr {$i + 3}] end])} {
8131 return
8132 }
8133 # unescape if quoted and chop off the a/ from the front
8134 if {[string index $line 0] eq "\""} {
8135 set fname [string range [lindex $line 0] 2 end]
8136 } else {
8137 set fname [string range $line 2 [expr {$i - 1}]]
8138 }
8139 }
8140 makediffhdr $fname $ids
8141
8142 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
8143 set fname [encoding convertfrom [string range $line 16 end]]
8144 $ctext insert end "\n"
8145 set curdiffstart [$ctext index "end - 1c"]
8146 lappend ctext_file_names $fname
8147 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8148 $ctext insert end "$line\n" filesep
8149 set i [lsearch -exact $treediffs($ids) $fname]
8150 if {$i >= 0} {
8151 setinlist difffilestart $i $curdiffstart
8152 }
8153
8154 } elseif {![string compare -length 2 "@@" $line]} {
8155 regexp {^@@+} $line ats
8156 set line [encoding convertfrom $diffencoding $line]
8157 $ctext insert end "$line\n" hunksep
8158 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8159 set diffline $nl
8160 }
8161 set diffnparents [expr {[string length $ats] - 1}]
8162 set diffinhdr 0
8163
8164 } elseif {![string compare -length 10 "Submodule " $line]} {
8165 # start of a new submodule
8166 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
8167 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
8168 } else {
8169 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
8170 }
8171 if {$currdiffsubmod != $fname} {
8172 $ctext insert end "\n"; # Add newline after commit message
8173 }
8174 set curdiffstart [$ctext index "end - 1c"]
8175 lappend ctext_file_names ""
8176 if {$currdiffsubmod != $fname} {
8177 lappend ctext_file_lines $fname
8178 makediffhdr $fname $ids
8179 set currdiffsubmod $fname
8180 $ctext insert end "\n$line\n" filesep
8181 } else {
8182 $ctext insert end "$line\n" filesep
8183 }
8184 } elseif {![string compare -length 3 " >" $line]} {
8185 set $currdiffsubmod ""
8186 set line [encoding convertfrom $diffencoding $line]
8187 $ctext insert end "$line\n" dresult
8188 } elseif {![string compare -length 3 " <" $line]} {
8189 set $currdiffsubmod ""
8190 set line [encoding convertfrom $diffencoding $line]
8191 $ctext insert end "$line\n" d0
8192 } elseif {$diffinhdr} {
8193 if {![string compare -length 12 "rename from " $line]} {
8194 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8195 if {[string index $fname 0] eq "\""} {
8196 set fname [lindex $fname 0]
8197 }
8198 set fname [encoding convertfrom $fname]
8199 set i [lsearch -exact $treediffs($ids) $fname]
8200 if {$i >= 0} {
8201 setinlist difffilestart $i $curdiffstart
8202 }
8203 } elseif {![string compare -length 10 $line "rename to "] ||
8204 ![string compare -length 8 $line "copy to "]} {
8205 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8206 if {[string index $fname 0] eq "\""} {
8207 set fname [lindex $fname 0]
8208 }
8209 makediffhdr $fname $ids
8210 } elseif {[string compare -length 3 $line "---"] == 0} {
8211 # do nothing
8212 return
8213 } elseif {[string compare -length 3 $line "+++"] == 0} {
8214 set diffinhdr 0
8215 return
8216 }
8217 $ctext insert end "$line\n" filesep
8218
8219 } else {
8220 set line [string map {\x1A ^Z} \
8221 [encoding convertfrom $diffencoding $line]]
8222 # parse the prefix - one ' ', '-' or '+' for each parent
8223 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8224 set tag [expr {$diffnparents > 1? "m": "d"}]
8225 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8226 set words_pre_markup ""
8227 set words_post_markup ""
8228 if {[string trim $prefix " -+"] eq {}} {
8229 # prefix only has " ", "-" and "+" in it: normal diff line
8230 set num [string first "-" $prefix]
8231 if {$dowords} {
8232 set line [string range $line 1 end]
8233 }
8234 if {$num >= 0} {
8235 # removed line, first parent with line is $num
8236 if {$num >= $mergemax} {
8237 set num "max"
8238 }
8239 if {$dowords && $worddiff eq [mc "Markup words"]} {
8240 $ctext insert end "\[-$line-\]" $tag$num
8241 } else {
8242 $ctext insert end "$line" $tag$num
8243 }
8244 if {!$dowords} {
8245 $ctext insert end "\n" $tag$num
8246 }
8247 } else {
8248 set tags {}
8249 if {[string first "+" $prefix] >= 0} {
8250 # added line
8251 lappend tags ${tag}result
8252 if {$diffnparents > 1} {
8253 set num [string first " " $prefix]
8254 if {$num >= 0} {
8255 if {$num >= $mergemax} {
8256 set num "max"
8257 }
8258 lappend tags m$num
8259 }
8260 }
8261 set words_pre_markup "{+"
8262 set words_post_markup "+}"
8263 }
8264 if {$targetline ne {}} {
8265 if {$diffline == $targetline} {
8266 set diffseehere [$ctext index "end - 1 chars"]
8267 set targetline {}
8268 } else {
8269 incr diffline
8270 }
8271 }
8272 if {$dowords && $worddiff eq [mc "Markup words"]} {
8273 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8274 } else {
8275 $ctext insert end "$line" $tags
8276 }
8277 if {!$dowords} {
8278 $ctext insert end "\n" $tags
8279 }
8280 }
8281 } elseif {$dowords && $prefix eq "~"} {
8282 $ctext insert end "\n" {}
8283 } else {
8284 # "\ No newline at end of file",
8285 # or something else we don't recognize
8286 $ctext insert end "$line\n" hunksep
8287 }
8288 }
8289}
8290
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008291proc changediffdisp {} {
8292 global ctext diffelide
8293
8294 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008295 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008296}
8297
Stefan Hallerb9671352012-09-19 20:17:27 +02008298proc highlightfile {cline} {
8299 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008300
Stefan Hallerce837c92012-10-04 22:50:16 +02008301 if {![info exists cflist_top]} return
8302
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008303 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8304 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8305 $cflist see $cline.0
8306 set cflist_top $cline
8307}
8308
Stefan Hallerb9671352012-09-19 20:17:27 +02008309proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008310 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008311
Stefan Haller978904b2012-10-04 22:50:17 +02008312 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008313 if {![info exists difffilestart]} return
8314
8315 set top [lindex [split $topidx .] 0]
8316 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
8317 highlightfile 0
8318 } else {
8319 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
8320 }
8321}
8322
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008323proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008324 global difffilestart ctext cmitmode
8325
8326 if {$cmitmode eq "tree"} return
8327 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008328 set here [$ctext index @0,0]
8329 foreach loc $difffilestart {
8330 if {[$ctext compare $loc >= $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008331 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008332 return
8333 }
8334 set prev $loc
8335 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008336 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008337}
8338
Paul Mackerras39ad8572005-05-19 12:35:53 +00008339proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008340 global difffilestart ctext cmitmode
8341
8342 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008343 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008344 foreach loc $difffilestart {
8345 if {[$ctext compare $loc > $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008346 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008347 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008348 }
8349 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008350}
8351
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008352proc clear_ctext {{first 1.0}} {
8353 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008354 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008355 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008356
Paul Mackerras1902c272006-05-25 21:25:13 +10008357 set l [lindex [split $first .] 0]
8358 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
8359 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008360 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008361 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
8362 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008363 }
8364 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008365 if {$first eq "1.0"} {
Paul Mackerras009409f2015-05-02 20:53:36 +10008366 unset -nocomplain pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10008367 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008368 set ctext_file_names {}
8369 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008370}
8371
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008372proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008373 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008374
8375 if {$firstab ne {} && $have_tk85} {
8376 set firsttabstop $firstab
8377 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008378 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008379 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10008380 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8381 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008382 } elseif {$have_tk85 || $tabstop != 8} {
8383 $ctext conf -tabs [expr {$tabstop * $w}]
8384 } else {
8385 $ctext conf -tabs {}
8386 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008387}
8388
8389proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008390 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008391
Paul Mackerras1902c272006-05-25 21:25:13 +10008392 if {[catch {$ctext index anchor}]} {
8393 # no anchor set, use start of selection, or of visible area
8394 set sel [$ctext tag ranges sel]
8395 if {$sel ne {}} {
8396 $ctext mark set anchor [lindex $sel 0]
8397 } elseif {$searchdirn eq "-forwards"} {
8398 $ctext mark set anchor @0,0
8399 } else {
8400 $ctext mark set anchor @0,[winfo height $ctext]
8401 }
8402 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008403 if {$searchstring ne {}} {
Stefan Haller30441a62012-09-22 09:40:25 +02008404 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
Paul Mackerras1902c272006-05-25 21:25:13 +10008405 if {$here ne {}} {
8406 $ctext see $here
Stefan Haller30441a62012-09-22 09:40:25 +02008407 set mend "$here + $mlen c"
8408 $ctext tag remove sel 1.0 end
8409 $ctext tag add sel $here $mend
Stefan Hallerb9671352012-09-19 20:17:27 +02008410 suppress_highlighting_file_for_current_scrollpos
8411 highlightfile_for_scrollpos $here
Paul Mackerras1902c272006-05-25 21:25:13 +10008412 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008413 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008414 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008415}
8416
8417proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008418 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008419
8420 focus $sstring
8421 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008422 set searchdirn -forwards
8423 if {$searchstring ne {}} {
8424 set sel [$ctext tag ranges sel]
8425 if {$sel ne {}} {
8426 set start "[lindex $sel 0] + 1c"
8427 } elseif {[catch {set start [$ctext index anchor]}]} {
8428 set start "@0,0"
8429 }
8430 set match [$ctext search -count mlen -- $searchstring $start]
8431 $ctext tag remove sel 1.0 end
8432 if {$match eq {}} {
8433 bell
8434 return
8435 }
8436 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008437 suppress_highlighting_file_for_current_scrollpos
8438 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008439 set mend "$match + $mlen c"
8440 $ctext tag add sel $match $mend
8441 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008442 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008443 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008444}
8445
8446proc dosearchback {} {
8447 global sstring ctext searchstring searchdirn
8448
8449 focus $sstring
8450 $sstring icursor end
8451 set searchdirn -backwards
8452 if {$searchstring ne {}} {
8453 set sel [$ctext tag ranges sel]
8454 if {$sel ne {}} {
8455 set start [lindex $sel 0]
8456 } elseif {[catch {set start [$ctext index anchor]}]} {
8457 set start @0,[winfo height $ctext]
8458 }
8459 set match [$ctext search -backwards -count ml -- $searchstring $start]
8460 $ctext tag remove sel 1.0 end
8461 if {$match eq {}} {
8462 bell
8463 return
8464 }
8465 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008466 suppress_highlighting_file_for_current_scrollpos
8467 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008468 set mend "$match + $ml c"
8469 $ctext tag add sel $match $mend
8470 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008471 rehighlight_search_results
8472 }
8473}
8474
8475proc rehighlight_search_results {} {
8476 global ctext searchstring
8477
8478 $ctext tag remove found 1.0 end
8479 $ctext tag remove currentsearchhit 1.0 end
8480
8481 if {$searchstring ne {}} {
8482 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008483 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008484}
8485
8486proc searchmark {first last} {
8487 global ctext searchstring
8488
Stefan Hallerc4614992012-09-22 09:40:24 +02008489 set sel [$ctext tag ranges sel]
8490
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008491 set mend $first.0
8492 while {1} {
8493 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8494 if {$match eq {}} break
8495 set mend "$match + $mlen c"
Stefan Hallerc4614992012-09-22 09:40:24 +02008496 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8497 $ctext tag add currentsearchhit $match $mend
8498 } else {
8499 $ctext tag add found $match $mend
8500 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008501 }
8502}
8503
8504proc searchmarkvisible {doall} {
8505 global ctext smarktop smarkbot
8506
8507 set topline [lindex [split [$ctext index @0,0] .] 0]
8508 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8509 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
8510 # no overlap with previous
8511 searchmark $topline $botline
8512 set smarktop $topline
8513 set smarkbot $botline
8514 } else {
8515 if {$topline < $smarktop} {
8516 searchmark $topline [expr {$smarktop-1}]
8517 set smarktop $topline
8518 }
8519 if {$botline > $smarkbot} {
8520 searchmark [expr {$smarkbot+1}] $botline
8521 set smarkbot $botline
8522 }
8523 }
8524}
8525
Stefan Hallerb9671352012-09-19 20:17:27 +02008526proc suppress_highlighting_file_for_current_scrollpos {} {
8527 global ctext suppress_highlighting_file_for_this_scrollpos
8528
8529 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8530}
8531
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008532proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008533 global searchstring cmitmode ctext
8534 global suppress_highlighting_file_for_this_scrollpos
8535
Stefan Haller978904b2012-10-04 22:50:17 +02008536 set topidx [$ctext index @0,0]
8537 if {![info exists suppress_highlighting_file_for_this_scrollpos]
8538 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8539 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008540 }
8541
Paul Mackerras009409f2015-05-02 20:53:36 +10008542 unset -nocomplain suppress_highlighting_file_for_this_scrollpos
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008543
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008544 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008545 if {$searchstring ne {}} {
8546 searchmarkvisible 0
8547 }
8548}
8549
Paul Mackerras1d10f362005-05-15 12:55:47 +00008550proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008551 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008552 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008553
Paul Mackerras9c311b32007-10-04 22:27:13 +10008554 set linespc [font metrics mainfont -linespace]
8555 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008556 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8557 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008558 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008559 set xspc1(0) $linespc
8560 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008561}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008562
Paul Mackerras1d10f362005-05-15 12:55:47 +00008563proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008564 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008565 global selectedline
8566
8567 set ymax [lindex [$canv cget -scrollregion] 3]
8568 if {$ymax eq {} || $ymax == 0} return
8569 set span [$canv yview]
8570 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008571 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008572 allcanvs yview moveto [lindex $span 0]
8573 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008574 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008575 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008576 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008577 }
8578}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008579
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008580proc parsefont {f n} {
8581 global fontattr
8582
8583 set fontattr($f,family) [lindex $n 0]
8584 set s [lindex $n 1]
8585 if {$s eq {} || $s == 0} {
8586 set s 10
8587 } elseif {$s < 0} {
8588 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008589 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008590 set fontattr($f,size) $s
8591 set fontattr($f,weight) normal
8592 set fontattr($f,slant) roman
8593 foreach style [lrange $n 2 end] {
8594 switch -- $style {
8595 "normal" -
8596 "bold" {set fontattr($f,weight) $style}
8597 "roman" -
8598 "italic" {set fontattr($f,slant) $style}
8599 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008600 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008601}
8602
8603proc fontflags {f {isbold 0}} {
8604 global fontattr
8605
8606 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
8607 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8608 -slant $fontattr($f,slant)]
8609}
8610
8611proc fontname {f} {
8612 global fontattr
8613
8614 set n [list $fontattr($f,family) $fontattr($f,size)]
8615 if {$fontattr($f,weight) eq "bold"} {
8616 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008617 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008618 if {$fontattr($f,slant) eq "italic"} {
8619 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008620 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008621 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008622}
8623
Paul Mackerras1d10f362005-05-15 12:55:47 +00008624proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008625 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008626 global stopped entries fontattr
8627
Paul Mackerras1d10f362005-05-15 12:55:47 +00008628 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008629 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008630 incr s $inc
8631 if {$s < 1} {
8632 set s 1
8633 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008634 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008635 font config mainfont -size $s
8636 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008637 set mainfont [fontname mainfont]
8638 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008639 incr s $inc
8640 if {$s < 1} {
8641 set s 1
8642 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008643 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008644 font config textfont -size $s
8645 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008646 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008647 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008648 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008649 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008650}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008651
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008652proc clearsha1 {} {
8653 global sha1entry sha1string
8654 if {[string length $sha1string] == 40} {
8655 $sha1entry delete 0 end
8656 }
8657}
8658
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008659proc sha1change {n1 n2 op} {
8660 global sha1string currentid sha1but
8661 if {$sha1string == {}
8662 || ([info exists currentid] && $sha1string == $currentid)} {
8663 set state disabled
8664 } else {
8665 set state normal
8666 }
8667 if {[$sha1but cget -state] == $state} return
8668 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008669 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008670 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008671 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008672 }
8673}
8674
8675proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008676 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008677
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008678 if {$sha1string == {}
8679 || ([info exists currentid] && $sha1string == $currentid)} return
8680 if {[info exists tagids($sha1string)]} {
8681 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008682 } elseif {[info exists headids($sha1string)]} {
8683 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008684 } else {
8685 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008686 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008687 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008688 if {$matches ne {}} {
8689 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008690 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008691 return
8692 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008693 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008694 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008695 } else {
8696 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8697 error_popup [mc "Revision %s is not known" $sha1string]
8698 return
8699 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008700 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008701 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008702 if {[commitinview $id $curview]} {
8703 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008704 return
8705 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008706 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008707 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008708 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008709 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008710 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008711 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008712}
8713
Paul Mackerras84ba7342005-06-17 00:12:26 +00008714proc lineenter {x y id} {
8715 global hoverx hovery hoverid hovertimer
8716 global commitinfo canv
8717
Paul Mackerras8ed16482006-03-02 22:56:44 +11008718 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008719 set hoverx $x
8720 set hovery $y
8721 set hoverid $id
8722 if {[info exists hovertimer]} {
8723 after cancel $hovertimer
8724 }
8725 set hovertimer [after 500 linehover]
8726 $canv delete hover
8727}
8728
8729proc linemotion {x y id} {
8730 global hoverx hovery hoverid hovertimer
8731
8732 if {[info exists hoverid] && $id == $hoverid} {
8733 set hoverx $x
8734 set hovery $y
8735 if {[info exists hovertimer]} {
8736 after cancel $hovertimer
8737 }
8738 set hovertimer [after 500 linehover]
8739 }
8740}
8741
8742proc lineleave {id} {
8743 global hoverid hovertimer canv
8744
8745 if {[info exists hoverid] && $id == $hoverid} {
8746 $canv delete hover
8747 if {[info exists hovertimer]} {
8748 after cancel $hovertimer
8749 unset hovertimer
8750 }
8751 unset hoverid
8752 }
8753}
8754
8755proc linehover {} {
8756 global hoverx hovery hoverid hovertimer
8757 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008758 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8759
Paul Mackerras9c311b32007-10-04 22:27:13 +10008760 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008761
8762 set text [lindex $commitinfo($hoverid) 0]
8763 set ymax [lindex [$canv cget -scrollregion] 3]
8764 if {$ymax == {}} return
8765 set yfrac [lindex [$canv yview] 0]
8766 set x [expr {$hoverx + 2 * $linespc}]
8767 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8768 set x0 [expr {$x - 2 * $lthickness}]
8769 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008770 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008771 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8772 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008773 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8774 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008775 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008776 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008777 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008778 $canv raise $t
8779}
8780
Paul Mackerras9843c302005-08-30 10:57:11 +10008781proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008782 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008783
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008784 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008785 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008786 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008787 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008788 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008789 if {abs([yc $row] - $y) < $thresh} {
8790 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008791 }
8792 }
8793 return {}
8794}
8795
Paul Mackerrasf6342482006-02-28 10:02:03 +11008796proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008797 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008798
Paul Mackerrasf6342482006-02-28 10:02:03 +11008799 # 1 <-> 2, 3 <-> 4, etc...
8800 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008801 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008802 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008803 set ymax [lindex [$canv cget -scrollregion] 3]
8804 if {$ymax eq {} || $ymax <= 0} return
8805 set view [$canv yview]
8806 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8807 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8808 if {$yfrac < 0} {
8809 set yfrac 0
8810 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008811 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008812}
8813
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008814proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008815 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008816
Paul Mackerras8ed16482006-03-02 22:56:44 +11008817 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008818 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008819 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008820 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008821 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008822 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008823 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008824 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008825 if {$isnew} {
8826 set ymax [lindex [$canv cget -scrollregion] 3]
8827 if {$ymax eq {}} return
8828 set yfrac [lindex [$canv yview] 0]
8829 set y [expr {$y + $yfrac * $ymax}]
8830 }
8831 set dirn [clickisonarrow $id $y]
8832 if {$dirn ne {}} {
8833 arrowjump $id $dirn $y
8834 return
8835 }
8836
8837 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008838 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008839 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008840 # fill the details pane with info about this line
8841 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008842 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008843 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008844 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008845 $ctext insert end $id link0
8846 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008847 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008848 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008849 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008850 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008851 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008852 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008853 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008854 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008855 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008856 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008857 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008858 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008859 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008860 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008861 $ctext insert end $child link$i
8862 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008863 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008864 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008865 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008866 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008867 }
8868 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008869 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008870 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008871 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008872}
8873
Paul Mackerras9843c302005-08-30 10:57:11 +10008874proc normalline {} {
8875 global thickerline
8876 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008877 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008878 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008879 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008880 }
8881}
8882
Paul Mackerras354af6b2008-11-23 13:14:23 +11008883proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008884 global curview
8885 if {[commitinview $id $curview]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008886 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008887 }
8888}
8889
8890proc mstime {} {
8891 global startmstime
8892 if {![info exists startmstime]} {
8893 set startmstime [clock clicks -milliseconds]
8894 }
8895 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8896}
8897
8898proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008899 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008900 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008901
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008902 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008903 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008904 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008905 set state disabled
8906 } else {
8907 set state normal
8908 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008909 if {[info exists markedid] && $markedid ne $id} {
8910 set mstate normal
8911 } else {
8912 set mstate disabled
8913 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008914 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008915 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008916 if {$mainhead ne {}} {
Beat Bollib6f92a82015-09-08 01:16:37 +02008917 $menu entryconfigure 8 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008918 } else {
Beat Bollib6f92a82015-09-08 01:16:37 +02008919 $menu entryconfigure 8 -label [mc "Detached head: can't reset" $mainhead] -state disabled
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008920 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008921 $menu entryconfigure 10 -state $mstate
8922 $menu entryconfigure 11 -state $mstate
Beat Bollib6f92a82015-09-08 01:16:37 +02008923 $menu entryconfigure 12 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008924 } else {
8925 set menu $fakerowmenu
8926 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008927 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8928 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8929 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11008930 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
8931 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008932 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008933}
8934
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008935proc markhere {} {
8936 global rowmenuid markedid canv
8937
8938 set markedid $rowmenuid
8939 make_idmark $markedid
8940}
8941
8942proc gotomark {} {
8943 global markedid
8944
8945 if {[info exists markedid]} {
8946 selbyid $markedid
8947 }
8948}
8949
8950proc replace_by_kids {l r} {
8951 global curview children
8952
8953 set id [commitonrow $r]
8954 set l [lreplace $l 0 0]
8955 foreach kid $children($curview,$id) {
8956 lappend l [rowofcommit $kid]
8957 }
8958 return [lsort -integer -decreasing -unique $l]
8959}
8960
8961proc find_common_desc {} {
8962 global markedid rowmenuid curview children
8963
8964 if {![info exists markedid]} return
8965 if {![commitinview $markedid $curview] ||
8966 ![commitinview $rowmenuid $curview]} return
8967 #set t1 [clock clicks -milliseconds]
8968 set l1 [list [rowofcommit $markedid]]
8969 set l2 [list [rowofcommit $rowmenuid]]
8970 while 1 {
8971 set r1 [lindex $l1 0]
8972 set r2 [lindex $l2 0]
8973 if {$r1 eq {} || $r2 eq {}} break
8974 if {$r1 == $r2} {
8975 selectline $r1 1
8976 break
8977 }
8978 if {$r1 > $r2} {
8979 set l1 [replace_by_kids $l1 $r1]
8980 } else {
8981 set l2 [replace_by_kids $l2 $r2]
8982 }
8983 }
8984 #set t2 [clock clicks -milliseconds]
8985 #puts "took [expr {$t2-$t1}]ms"
8986}
8987
Paul Mackerras010509f2009-04-09 22:10:20 +10008988proc compare_commits {} {
8989 global markedid rowmenuid curview children
8990
8991 if {![info exists markedid]} return
8992 if {![commitinview $markedid $curview]} return
8993 addtohistory [list do_cmp_commits $markedid $rowmenuid]
8994 do_cmp_commits $markedid $rowmenuid
8995}
8996
8997proc getpatchid {id} {
8998 global patchids
8999
9000 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009001 set cmd [diffcmd [list $id] {-p --root}]
9002 # trim off the initial "|"
9003 set cmd [lrange $cmd 1 end]
9004 if {[catch {
9005 set x [eval exec $cmd | git patch-id]
9006 set patchids($id) [lindex $x 0]
9007 }]} {
9008 set patchids($id) "error"
9009 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009010 }
9011 return $patchids($id)
9012}
9013
9014proc do_cmp_commits {a b} {
9015 global ctext curview parents children patchids commitinfo
9016
9017 $ctext conf -state normal
9018 clear_ctext
9019 init_flist {}
9020 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009021 set skipa 0
9022 set skipb 0
9023 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009024 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009025 set skipa 1
9026 } else {
9027 set patcha [getpatchid $a]
9028 }
9029 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009030 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009031 set skipb 1
9032 } else {
9033 set patchb [getpatchid $b]
9034 }
9035 if {!$skipa && !$skipb} {
9036 set heada [lindex $commitinfo($a) 0]
9037 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009038 if {$patcha eq "error"} {
9039 appendshortlink $a [mc "Error getting patch ID for "] \
9040 [mc " - stopping\n"]
9041 break
9042 }
9043 if {$patchb eq "error"} {
9044 appendshortlink $b [mc "Error getting patch ID for "] \
9045 [mc " - stopping\n"]
9046 break
9047 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009048 if {$patcha eq $patchb} {
9049 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009050 appendshortlink $a [mc "Commit "]
9051 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009052 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009053 appendshortlink $a [mc "Commit "] " $heada\n"
9054 appendshortlink $b [mc " is the same patch as\n "] \
9055 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009056 }
9057 set skipa 1
9058 set skipb 1
9059 } else {
9060 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009061 appendshortlink $a [mc "Commit "] " $heada\n"
9062 appendshortlink $b [mc " differs from\n "] \
9063 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009064 $ctext insert end [mc "Diff of commits:\n\n"]
9065 $ctext conf -state disabled
9066 update
9067 diffcommits $a $b
9068 return
Paul Mackerras010509f2009-04-09 22:10:20 +10009069 }
9070 }
9071 if {$skipa} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009072 set kids [real_children $curview,$a]
9073 if {[llength $kids] != 1} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009074 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009075 appendshortlink $a [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009076 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009077 break
9078 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009079 set a [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009080 }
9081 if {$skipb} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009082 set kids [real_children $curview,$b]
9083 if {[llength $kids] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009084 appendshortlink $b [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009085 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009086 break
9087 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009088 set b [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009089 }
9090 }
9091 $ctext conf -state disabled
9092}
9093
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009094proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009095 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009096
9097 set tmpdir [gitknewtmpdir]
9098 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
9099 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
9100 if {[catch {
9101 exec git diff-tree -p --pretty $a >$fna
9102 exec git diff-tree -p --pretty $b >$fnb
9103 } err]} {
9104 error_popup [mc "Error writing commit to file: %s" $err]
9105 return
9106 }
9107 if {[catch {
9108 set fd [open "| diff -U$diffcontext $fna $fnb" r]
9109 } err]} {
9110 error_popup [mc "Error diffing commits: %s" $err]
9111 return
9112 }
9113 set diffids [list commits $a $b]
9114 set blobdifffd($diffids) $fd
9115 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009116 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009117 filerun $fd [list getblobdiffline $fd $diffids]
9118}
9119
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009120proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009121 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009122
Paul Mackerras94b4a692008-05-20 20:51:06 +10009123 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009124 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009125 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009126 set newid $rowmenuid
9127 } else {
9128 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009129 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009130 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11009131 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009132 doseldiff $oldid $newid
9133}
9134
Paul Mackerras6febded2012-03-23 22:07:27 +11009135proc diffvsmark {dirn} {
9136 global rowmenuid markedid
9137
9138 if {![info exists markedid]} return
9139 if {$dirn} {
9140 set oldid $markedid
9141 set newid $rowmenuid
9142 } else {
9143 set oldid $rowmenuid
9144 set newid $markedid
9145 }
9146 addtohistory [list doseldiff $oldid $newid] savectextpos
9147 doseldiff $oldid $newid
9148}
9149
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009150proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009151 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009152 global commitinfo
9153
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009154 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009155 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01009156 init_flist [mc "Top"]
9157 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009158 $ctext insert end $oldid link0
9159 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009160 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009161 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009162 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009163 $ctext insert end $newid link1
9164 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009165 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009166 $ctext insert end [lindex $commitinfo($newid) 0]
9167 $ctext insert end "\n"
9168 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009169 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11009170 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009171}
9172
Paul Mackerras74daedb2005-06-27 19:27:32 +10009173proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009174 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10009175
9176 if {![info exists currentid]} return
9177 set oldid $currentid
9178 set oldhead [lindex $commitinfo($oldid) 0]
9179 set newid $rowmenuid
9180 set newhead [lindex $commitinfo($newid) 0]
9181 set top .patch
9182 set patchtop $top
9183 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009184 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009185 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009186 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009187 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009188 ${NS}::label $top.from -text [mc "From:"]
9189 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009190 $top.fromsha1 insert 0 $oldid
9191 $top.fromsha1 conf -state readonly
9192 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009193 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009194 $top.fromhead insert 0 $oldhead
9195 $top.fromhead conf -state readonly
9196 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009197 ${NS}::label $top.to -text [mc "To:"]
9198 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009199 $top.tosha1 insert 0 $newid
9200 $top.tosha1 conf -state readonly
9201 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009202 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009203 $top.tohead insert 0 $newhead
9204 $top.tohead conf -state readonly
9205 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009206 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
9207 grid $top.rev x -pady 10 -padx 5
9208 ${NS}::label $top.flab -text [mc "Output file:"]
9209 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009210 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
9211 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009212 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009213 ${NS}::frame $top.buts
9214 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
9215 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009216 bind $top <Key-Return> mkpatchgo
9217 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10009218 grid $top.buts.gen $top.buts.can
9219 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9220 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9221 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009222 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10009223}
9224
9225proc mkpatchrev {} {
9226 global patchtop
9227
9228 set oldid [$patchtop.fromsha1 get]
9229 set oldhead [$patchtop.fromhead get]
9230 set newid [$patchtop.tosha1 get]
9231 set newhead [$patchtop.tohead get]
9232 foreach e [list fromsha1 fromhead tosha1 tohead] \
9233 v [list $newid $newhead $oldid $oldhead] {
9234 $patchtop.$e conf -state normal
9235 $patchtop.$e delete 0 end
9236 $patchtop.$e insert 0 $v
9237 $patchtop.$e conf -state readonly
9238 }
9239}
9240
9241proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10009242 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10009243
9244 set oldid [$patchtop.fromsha1 get]
9245 set newid [$patchtop.tosha1 get]
9246 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10009247 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10009248 # trim off the initial "|"
9249 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009250 lappend cmd >$fname &
9251 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009252 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009253 }
9254 catch {destroy $patchtop}
9255 unset patchtop
9256}
9257
9258proc mkpatchcan {} {
9259 global patchtop
9260
9261 catch {destroy $patchtop}
9262 unset patchtop
9263}
9264
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009265proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009266 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009267
9268 set top .maketag
9269 set mktagtop $top
9270 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009271 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009272 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009273 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009274 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009275 ${NS}::label $top.id -text [mc "ID:"]
9276 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009277 $top.sha1 insert 0 $rowmenuid
9278 $top.sha1 conf -state readonly
9279 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009280 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009281 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9282 $top.head conf -state readonly
9283 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009284 ${NS}::label $top.tlab -text [mc "Tag name:"]
9285 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009286 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009287 ${NS}::label $top.op -text [mc "Tag message is optional"]
9288 grid $top.op -columnspan 2 -sticky we
9289 ${NS}::label $top.mlab -text [mc "Tag message:"]
9290 ${NS}::entry $top.msg -width 60
9291 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009292 ${NS}::frame $top.buts
9293 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9294 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009295 bind $top <Key-Return> mktaggo
9296 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009297 grid $top.buts.gen $top.buts.can
9298 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9299 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9300 grid $top.buts - -pady 10 -sticky ew
9301 focus $top.tag
9302}
9303
9304proc domktag {} {
9305 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009306
9307 set id [$mktagtop.sha1 get]
9308 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009309 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009310 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009311 error_popup [mc "No tag name specified"] $mktagtop
9312 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009313 }
9314 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009315 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9316 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009317 }
9318 if {[catch {
Dave Dulsondfb891e2010-01-03 14:55:52 +00009319 if {$msg != {}} {
9320 exec git tag -a -m $msg $tag $id
9321 } else {
9322 exec git tag $tag $id
9323 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009324 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009325 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9326 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009327 }
9328
9329 set tagids($tag) $id
9330 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009331 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009332 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009333 dispneartags 0
9334 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009335 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009336}
9337
9338proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009339 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009340 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009341 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009342
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009343 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009344 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009345 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009346 if {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009347 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009348 } else {
9349 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
9350 }
9351 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009352 $canv delete tag.$id
9353 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009354 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9355 set text [$canv itemcget $linehtag($id) -text]
9356 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009357 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009358 if {$xr > $canvxmax} {
9359 set canvxmax $xr
9360 setcanvscroll
9361 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009362 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11009363 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009364 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009365 if {[info exists markedid] && $markedid eq $id} {
9366 make_idmark $id
9367 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009368}
9369
9370proc mktagcan {} {
9371 global mktagtop
9372
9373 catch {destroy $mktagtop}
9374 unset mktagtop
9375}
9376
9377proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009378 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009379 mktagcan
9380}
9381
Beat Bollid835dbb2015-07-18 13:15:39 +02009382proc copysummary {} {
9383 global rowmenuid autosellen
9384
9385 set format "%h (\"%s\", %ad)"
9386 set cmd [list git show -s --pretty=format:$format --date=short]
9387 if {$autosellen < 40} {
9388 lappend cmd --abbrev=$autosellen
9389 }
9390 set summary [eval exec $cmd $rowmenuid]
9391
9392 clipboard clear
9393 clipboard append $summary
9394}
9395
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009396proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009397 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009398
9399 set top .writecommit
9400 set wrcomtop $top
9401 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009402 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009403 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009404 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009405 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009406 ${NS}::label $top.id -text [mc "ID:"]
9407 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009408 $top.sha1 insert 0 $rowmenuid
9409 $top.sha1 conf -state readonly
9410 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009411 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009412 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9413 $top.head conf -state readonly
9414 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009415 ${NS}::label $top.clab -text [mc "Command:"]
9416 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009417 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009418 ${NS}::label $top.flab -text [mc "Output file:"]
9419 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009420 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9421 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009422 ${NS}::frame $top.buts
9423 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9424 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009425 bind $top <Key-Return> wrcomgo
9426 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009427 grid $top.buts.gen $top.buts.can
9428 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9429 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9430 grid $top.buts - -pady 10 -sticky ew
9431 focus $top.fname
9432}
9433
9434proc wrcomgo {} {
9435 global wrcomtop
9436
9437 set id [$wrcomtop.sha1 get]
9438 set cmd "echo $id | [$wrcomtop.cmd get]"
9439 set fname [$wrcomtop.fname get]
9440 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009441 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009442 }
9443 catch {destroy $wrcomtop}
9444 unset wrcomtop
9445}
9446
9447proc wrcomcan {} {
9448 global wrcomtop
9449
9450 catch {destroy $wrcomtop}
9451 unset wrcomtop
9452}
9453
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009454proc mkbranch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009455 global rowmenuid mkbrtop NS
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009456
9457 set top .makebranch
9458 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009459 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009460 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009461 ${NS}::label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009462 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009463 ${NS}::label $top.id -text [mc "ID:"]
9464 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009465 $top.sha1 insert 0 $rowmenuid
9466 $top.sha1 conf -state readonly
9467 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009468 ${NS}::label $top.nlab -text [mc "Name:"]
9469 ${NS}::entry $top.name -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009470 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009471 ${NS}::frame $top.buts
9472 ${NS}::button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
9473 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009474 bind $top <Key-Return> [list mkbrgo $top]
9475 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009476 grid $top.buts.go $top.buts.can
9477 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9478 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9479 grid $top.buts - -pady 10 -sticky ew
9480 focus $top.name
9481}
9482
9483proc mkbrgo {top} {
9484 global headids idheads
9485
9486 set name [$top.name get]
9487 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009488 set cmdargs {}
9489 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009490 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009491 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009492 return
9493 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009494 if {[info exists headids($name)]} {
9495 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009496 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009497 return
9498 }
9499 set old_id $headids($name)
9500 lappend cmdargs -f
9501 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009502 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009503 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009504 nowbusy newbranch
9505 update
9506 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009507 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009508 } err]} {
9509 notbusy newbranch
9510 error_popup $err
9511 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009512 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009513 if {$old_id ne {}} {
9514 movehead $id $name
9515 movedhead $id $name
9516 redrawtags $old_id
9517 redrawtags $id
9518 } else {
9519 set headids($name) $id
9520 lappend idheads($id) $name
9521 addedhead $id $name
9522 redrawtags $id
9523 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009524 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009525 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009526 }
9527}
9528
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009529proc exec_citool {tool_args {baseid {}}} {
9530 global commitinfo env
9531
9532 set save_env [array get env GIT_AUTHOR_*]
9533
9534 if {$baseid ne {}} {
9535 if {![info exists commitinfo($baseid)]} {
9536 getcommit $baseid
9537 }
9538 set author [lindex $commitinfo($baseid) 1]
9539 set date [lindex $commitinfo($baseid) 2]
9540 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9541 $author author name email]
9542 && $date ne {}} {
9543 set env(GIT_AUTHOR_NAME) $name
9544 set env(GIT_AUTHOR_EMAIL) $email
9545 set env(GIT_AUTHOR_DATE) $date
9546 }
9547 }
9548
9549 eval exec git citool $tool_args &
9550
9551 array unset env GIT_AUTHOR_*
9552 array set env $save_env
9553}
9554
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009555proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009556 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009557 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009558 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009559
Paul Mackerrase11f1232007-06-16 20:29:25 +10009560 set oldhead [exec git rev-parse HEAD]
9561 set dheads [descheads $rowmenuid]
9562 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009563 set ok [confirm_popup [mc "Commit %s is already\
9564 included in branch %s -- really re-apply it?" \
9565 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009566 if {!$ok} return
9567 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009568 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009569 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009570 # Unfortunately git-cherry-pick writes stuff to stderr even when
9571 # no error occurs, and exec takes that as an indication of error...
9572 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
9573 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009574 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11009575 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9576 $err msg fname]} {
9577 error_popup [mc "Cherry-pick failed because of local changes\
9578 to file '%s'.\nPlease commit, reset or stash\
9579 your changes and try again." $fname]
9580 } elseif {[regexp -line \
Anders Kaseorgb74307f2011-01-19 14:45:00 -05009581 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
Paul Mackerras887a7912008-11-08 21:37:09 +11009582 $err]} {
9583 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9584 conflict.\nDo you wish to run git citool to\
9585 resolve it?"]]} {
9586 # Force citool to read MERGE_MSG
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009587 file delete [file join $gitdir "GITGUI_MSG"]
Paul Mackerras887a7912008-11-08 21:37:09 +11009588 exec_citool {} $rowmenuid
9589 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009590 } else {
9591 error_popup $err
9592 }
Paul Mackerras887a7912008-11-08 21:37:09 +11009593 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009594 return
9595 }
9596 set newhead [exec git rev-parse HEAD]
9597 if {$newhead eq $oldhead} {
9598 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01009599 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009600 return
9601 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009602 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009603 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11009604 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009605 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009606 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009607 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009608 movedhead $newhead $mainhead
9609 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009610 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009611 redrawtags $oldhead
9612 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11009613 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009614 }
9615 notbusy cherrypick
9616}
9617
Knut Franke8f3ff932013-04-27 16:36:13 +02009618proc revert {} {
9619 global rowmenuid curview
9620 global mainhead mainheadid
9621 global gitdir
9622
9623 set oldhead [exec git rev-parse HEAD]
9624 set dheads [descheads $rowmenuid]
9625 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9626 set ok [confirm_popup [mc "Commit %s is not\
9627 included in branch %s -- really revert it?" \
9628 [string range $rowmenuid 0 7] $mainhead]]
9629 if {!$ok} return
9630 }
9631 nowbusy revert [mc "Reverting"]
9632 update
9633
9634 if [catch {exec git revert --no-edit $rowmenuid} err] {
9635 notbusy revert
9636 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9637 $err match files] {
9638 regsub {\n( |\t)+} $files "\n" files
9639 error_popup [mc "Revert failed because of local changes to\
9640 the following files:%s Please commit, reset or stash \
9641 your changes and try again." $files]
9642 } elseif [regexp {error: could not revert} $err] {
9643 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9644 Do you wish to run git citool to resolve it?"]] {
9645 # Force citool to read MERGE_MSG
9646 file delete [file join $gitdir "GITGUI_MSG"]
9647 exec_citool {} $rowmenuid
9648 }
9649 } else { error_popup $err }
9650 run updatecommits
9651 return
9652 }
9653
9654 set newhead [exec git rev-parse HEAD]
9655 if { $newhead eq $oldhead } {
9656 notbusy revert
9657 error_popup [mc "No changes committed"]
9658 return
9659 }
9660
9661 addnewchild $newhead $oldhead
9662
9663 if [commitinview $oldhead $curview] {
9664 # XXX this isn't right if we have a path limit...
9665 insertrow $newhead $oldhead $curview
9666 if {$mainhead ne {}} {
9667 movehead $newhead $mainhead
9668 movedhead $newhead $mainhead
9669 }
9670 set mainheadid $newhead
9671 redrawtags $oldhead
9672 redrawtags $newhead
9673 selbyid $newhead
9674 }
9675
9676 notbusy revert
9677}
9678
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009679proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009680 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009681
9682 set confirm_ok 0
9683 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009684 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009685 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009686 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009687 ${NS}::label $w.m -text \
9688 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009689 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009690 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009691 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009692 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009693 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009694 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009695 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009696 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009697 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009698 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009699 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009700 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009701 pack $w.f -side top -fill x -padx 4
9702 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009703 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009704 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009705 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009706 pack $w.cancel -side right -fill x -padx 20 -pady 20
9707 bind $w <Visibility> "grab $w; focus $w"
9708 tkwait window $w
9709 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009710 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10009711 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009712 error_popup $err
9713 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009714 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10009715 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009716 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11009717 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009718 }
9719}
9720
Paul Mackerrasa137a902007-10-23 21:12:49 +10009721proc readresetstat {fd} {
9722 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009723
9724 if {[gets $fd line] >= 0} {
9725 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10009726 set rprogcoord [expr {1.0 * $m / $n}]
9727 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009728 }
9729 return 1
9730 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009731 set rprogcoord 0
9732 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009733 notbusy reset
9734 if {[catch {close $fd} err]} {
9735 error_popup $err
9736 }
9737 set oldhead $mainheadid
9738 set newhead [exec git rev-parse HEAD]
9739 if {$newhead ne $oldhead} {
9740 movehead $newhead $mainhead
9741 movedhead $newhead $mainhead
9742 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009743 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10009744 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009745 }
9746 if {$showlocalchanges} {
9747 doshowlocalchanges
9748 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009749 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009750}
9751
Paul Mackerras10299152006-08-02 09:52:01 +10009752# context menu for a head
9753proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10009754 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10009755
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009756 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009757 set headmenuid $id
9758 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10009759 set state normal
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309760 if {[string match "remotes/*" $head]} {
9761 set state disabled
9762 }
Paul Mackerras00609462007-06-17 17:08:35 +10009763 if {$head eq $mainhead} {
9764 set state disabled
9765 }
9766 $headctxmenu entryconfigure 0 -state $state
9767 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10009768 tk_popup $headctxmenu $x $y
9769}
9770
9771proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009772 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009773 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009774
9775 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01009776 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009777 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009778 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009779 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10009780 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10009781 } err]} {
9782 notbusy checkout
9783 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10009784 if {$showlocalchanges} {
9785 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009786 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009787 } else {
9788 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009789 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009790}
9791
9792proc readcheckoutstat {fd newhead newheadid} {
9793 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009794 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009795
9796 if {[gets $fd line] >= 0} {
9797 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9798 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9799 adjustprogress
9800 }
9801 return 1
9802 }
9803 set progresscoords {0 0}
9804 adjustprogress
9805 notbusy checkout
9806 if {[catch {close $fd} err]} {
9807 error_popup $err
9808 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009809 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009810 set mainhead $newhead
9811 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11009812 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009813 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009814 redrawtags $newheadid
9815 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009816 if {$showlocalchanges} {
9817 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009818 }
9819}
9820
9821proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009822 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10009823 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10009824
9825 set head $headmenuhead
9826 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10009827 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10009828 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009829 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10009830 return
9831 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009832 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10009833 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10009834 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01009835 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
9836 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10009837 }
9838 nowbusy rmbranch
9839 update
9840 if {[catch {exec git branch -D $head} err]} {
9841 notbusy rmbranch
9842 error_popup $err
9843 return
9844 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009845 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009846 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10009847 redrawtags $id
9848 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10009849 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009850 run refill_reflist
9851}
9852
9853# Display a list of tags and heads
9854proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009855 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +10009856 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10009857
9858 set top .showrefs
9859 set showrefstop $top
9860 if {[winfo exists $top]} {
9861 raise $top
9862 refill_reflist
9863 return
9864 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009865 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009866 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009867 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10009868 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10009869 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10009870 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
9871 -width 30 -height 20 -cursor $maincursor \
9872 -spacing1 1 -spacing3 1 -state disabled
9873 $top.list tag configure highlight -background $selectbgcolor
Paul Mackerraseb859df2015-05-03 15:11:29 +10009874 if {![lsearch -exact $bglist $top.list]} {
9875 lappend bglist $top.list
9876 lappend fglist $top.list
9877 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009878 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
9879 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +10009880 grid $top.list $top.ysb -sticky nsew
9881 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +01009882 ${NS}::frame $top.f
9883 ${NS}::label $top.f.l -text "[mc "Filter"]: "
9884 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009885 set reflistfilter "*"
9886 trace add variable reflistfilter write reflistfilter_change
9887 pack $top.f.e -side right -fill x -expand 1
9888 pack $top.f.l -side left
9889 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01009890 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009891 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10009892 grid $top.close -
9893 grid columnconfigure $top 0 -weight 1
9894 grid rowconfigure $top 0 -weight 1
9895 bind $top.list <1> {break}
9896 bind $top.list <B1-Motion> {break}
9897 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
9898 set reflist {}
9899 refill_reflist
9900}
9901
9902proc sel_reflist {w x y} {
9903 global showrefstop reflist headids tagids otherrefids
9904
9905 if {![winfo exists $showrefstop]} return
9906 set l [lindex [split [$w index "@$x,$y"] "."] 0]
9907 set ref [lindex $reflist [expr {$l-1}]]
9908 set n [lindex $ref 0]
9909 switch -- [lindex $ref 1] {
9910 "H" {selbyid $headids($n)}
9911 "T" {selbyid $tagids($n)}
9912 "o" {selbyid $otherrefids($n)}
9913 }
9914 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
9915}
9916
9917proc unsel_reflist {} {
9918 global showrefstop
9919
9920 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9921 $showrefstop.list tag remove highlight 0.0 end
9922}
9923
9924proc reflistfilter_change {n1 n2 op} {
9925 global reflistfilter
9926
9927 after cancel refill_reflist
9928 after 200 refill_reflist
9929}
9930
9931proc refill_reflist {} {
9932 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009933 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10009934
9935 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9936 set refs {}
9937 foreach n [array names headids] {
9938 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009939 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009940 lappend refs [list $n H]
9941 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009942 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009943 }
9944 }
9945 }
9946 foreach n [array names tagids] {
9947 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009948 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009949 lappend refs [list $n T]
9950 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009951 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009952 }
9953 }
9954 }
9955 foreach n [array names otherrefids] {
9956 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009957 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009958 lappend refs [list $n o]
9959 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009960 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009961 }
9962 }
9963 }
9964 set refs [lsort -index 0 $refs]
9965 if {$refs eq $reflist} return
9966
9967 # Update the contents of $showrefstop.list according to the
9968 # differences between $reflist (old) and $refs (new)
9969 $showrefstop.list conf -state normal
9970 $showrefstop.list insert end "\n"
9971 set i 0
9972 set j 0
9973 while {$i < [llength $reflist] || $j < [llength $refs]} {
9974 if {$i < [llength $reflist]} {
9975 if {$j < [llength $refs]} {
9976 set cmp [string compare [lindex $reflist $i 0] \
9977 [lindex $refs $j 0]]
9978 if {$cmp == 0} {
9979 set cmp [string compare [lindex $reflist $i 1] \
9980 [lindex $refs $j 1]]
9981 }
9982 } else {
9983 set cmp -1
9984 }
9985 } else {
9986 set cmp 1
9987 }
9988 switch -- $cmp {
9989 -1 {
9990 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
9991 incr i
9992 }
9993 0 {
9994 incr i
9995 incr j
9996 }
9997 1 {
9998 set l [expr {$j + 1}]
9999 $showrefstop.list image create $l.0 -align baseline \
10000 -image reficon-[lindex $refs $j 1] -padx 2
10001 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
10002 incr j
10003 }
10004 }
10005 }
10006 set reflist $refs
10007 # delete last newline
10008 $showrefstop.list delete end-2c end-1c
10009 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +100010010}
10011
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010012# Stuff for finding nearby tags
10013proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010014 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
10015 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010016 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010017
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010018 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010019 set nextarc 0
10020 set allcommits 0
10021 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010022 set allcwait 0
10023 set cachedarcs 0
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010024 set allccache [file join $gitdir "gitk.cache"]
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010025 if {![catch {
10026 set f [open $allccache r]
10027 set allcwait 1
10028 getcache $f
10029 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010030 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010031
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010032 if {$allcwait} {
10033 return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010034 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010035 set cmd [list | git rev-list --parents]
10036 set allcupdate [expr {$seeds ne {}}]
10037 if {!$allcupdate} {
10038 set ids "--all"
10039 } else {
10040 set refs [concat [array names idheads] [array names idtags] \
10041 [array names idotherrefs]]
10042 set ids {}
10043 set tagobjs {}
10044 foreach name [array names tagobjid] {
10045 lappend tagobjs $tagobjid($name)
10046 }
10047 foreach id [lsort -unique $refs] {
10048 if {![info exists allparents($id)] &&
10049 [lsearch -exact $tagobjs $id] < 0} {
10050 lappend ids $id
10051 }
10052 }
10053 if {$ids ne {}} {
10054 foreach id $seeds {
10055 lappend ids "^$id"
10056 }
10057 }
10058 }
10059 if {$ids ne {}} {
10060 set fd [open [concat $cmd $ids] r]
10061 fconfigure $fd -blocking 0
10062 incr allcommits
10063 nowbusy allcommits
10064 filerun $fd [list getallclines $fd]
10065 } else {
10066 dispneartags 0
10067 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010068}
10069
Paul Mackerrase11f1232007-06-16 20:29:25 +100010070# Since most commits have 1 parent and 1 child, we group strings of
10071# such commits into "arcs" joining branch/merge points (BMPs), which
10072# are commits that either don't have 1 parent or don't have 1 child.
10073#
10074# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
10075# arcout(id) - outgoing arcs for BMP
10076# arcids(a) - list of IDs on arc including end but not start
10077# arcstart(a) - BMP ID at start of arc
10078# arcend(a) - BMP ID at end of arc
10079# growing(a) - arc a is still growing
10080# arctags(a) - IDs out of arcids (excluding end) that have tags
10081# archeads(a) - IDs out of arcids (excluding end) that have heads
10082# The start of an arc is at the descendent end, so "incoming" means
10083# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010084
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010085proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010086 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010087 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010088 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +010010089
Paul Mackerrase11f1232007-06-16 20:29:25 +100010090 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010091 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010092 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010093 if {[info exists allparents($id)]} {
10094 # seen it already
10095 continue
10096 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010097 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010098 set olds [lrange $line 1 end]
10099 set allparents($id) $olds
10100 if {![info exists allchildren($id)]} {
10101 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010102 set arcnos($id) {}
10103 lappend seeds $id
10104 } else {
10105 set a $arcnos($id)
10106 if {[llength $olds] == 1 && [llength $a] == 1} {
10107 lappend arcids($a) $id
10108 if {[info exists idtags($id)]} {
10109 lappend arctags($a) $id
10110 }
10111 if {[info exists idheads($id)]} {
10112 lappend archeads($a) $id
10113 }
10114 if {[info exists allparents($olds)]} {
10115 # seen parent already
10116 if {![info exists arcout($olds)]} {
10117 splitarc $olds
10118 }
10119 lappend arcids($a) $olds
10120 set arcend($a) $olds
10121 unset growing($a)
10122 }
10123 lappend allchildren($olds) $id
10124 lappend arcnos($olds) $a
10125 continue
10126 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010127 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010128 foreach a $arcnos($id) {
10129 lappend arcids($a) $id
10130 set arcend($a) $id
10131 unset growing($a)
10132 }
10133
10134 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010135 foreach p $olds {
10136 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010137 set a [incr nextarc]
10138 set arcstart($a) $id
10139 set archeads($a) {}
10140 set arctags($a) {}
10141 set archeads($a) {}
10142 set arcids($a) {}
10143 lappend ao $a
10144 set growing($a) 1
10145 if {[info exists allparents($p)]} {
10146 # seen it already, may need to make a new branch
10147 if {![info exists arcout($p)]} {
10148 splitarc $p
10149 }
10150 lappend arcids($a) $p
10151 set arcend($a) $p
10152 unset growing($a)
10153 }
10154 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010155 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010156 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010157 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010158 if {$nid > 0} {
10159 global cached_dheads cached_dtags cached_atags
Paul Mackerras009409f2015-05-02 20:53:36 +100010160 unset -nocomplain cached_dheads
10161 unset -nocomplain cached_dtags
10162 unset -nocomplain cached_atags
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010163 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010164 if {![eof $fd]} {
10165 return [expr {$nid >= 1000? 2: 1}]
10166 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010167 set cacheok 1
10168 if {[catch {
10169 fconfigure $fd -blocking 1
10170 close $fd
10171 } err]} {
10172 # got an error reading the list of commits
10173 # if we were updating, try rereading the whole thing again
10174 if {$allcupdate} {
10175 incr allcommits -1
10176 dropcache $err
10177 return
10178 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010010179 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010180 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +010010181 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010182 set cacheok 0
10183 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010184 if {[incr allcommits -1] == 0} {
10185 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010186 if {$cacheok} {
10187 run savecache
10188 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010189 }
10190 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010191 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010192}
10193
10194proc recalcarc {a} {
10195 global arctags archeads arcids idtags idheads
10196
10197 set at {}
10198 set ah {}
10199 foreach id [lrange $arcids($a) 0 end-1] {
10200 if {[info exists idtags($id)]} {
10201 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010202 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010203 if {[info exists idheads($id)]} {
10204 lappend ah $id
10205 }
10206 }
10207 set arctags($a) $at
10208 set archeads($a) $ah
10209}
10210
10211proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010212 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +100010213 global arcstart arcend arcout allparents growing
10214
10215 set a $arcnos($p)
10216 if {[llength $a] != 1} {
10217 puts "oops splitarc called but [llength $a] arcs already"
10218 return
10219 }
10220 set a [lindex $a 0]
10221 set i [lsearch -exact $arcids($a) $p]
10222 if {$i < 0} {
10223 puts "oops splitarc $p not in arc $a"
10224 return
10225 }
10226 set na [incr nextarc]
10227 if {[info exists arcend($a)]} {
10228 set arcend($na) $arcend($a)
10229 } else {
10230 set l [lindex $allparents([lindex $arcids($a) end]) 0]
10231 set j [lsearch -exact $arcnos($l) $a]
10232 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
10233 }
10234 set tail [lrange $arcids($a) [expr {$i+1}] end]
10235 set arcids($a) [lrange $arcids($a) 0 $i]
10236 set arcend($a) $p
10237 set arcstart($na) $p
10238 set arcout($p) $na
10239 set arcids($na) $tail
10240 if {[info exists growing($a)]} {
10241 set growing($na) 1
10242 unset growing($a)
10243 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010244
10245 foreach id $tail {
10246 if {[llength $arcnos($id)] == 1} {
10247 set arcnos($id) $na
10248 } else {
10249 set j [lsearch -exact $arcnos($id) $a]
10250 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
10251 }
10252 }
10253
10254 # reconstruct tags and heads lists
10255 if {$arctags($a) ne {} || $archeads($a) ne {}} {
10256 recalcarc $a
10257 recalcarc $na
10258 } else {
10259 set arctags($na) {}
10260 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010261 }
10262}
10263
Paul Mackerrase11f1232007-06-16 20:29:25 +100010264# Update things for a new commit added that is a child of one
10265# existing commit. Used when cherry-picking.
10266proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010267 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010268 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010269 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010270
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010271 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010272 set allparents($id) [list $p]
10273 set allchildren($id) {}
10274 set arcnos($id) {}
10275 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010276 lappend allchildren($p) $id
10277 set a [incr nextarc]
10278 set arcstart($a) $id
10279 set archeads($a) {}
10280 set arctags($a) {}
10281 set arcids($a) [list $p]
10282 set arcend($a) $p
10283 if {![info exists arcout($p)]} {
10284 splitarc $p
10285 }
10286 lappend arcnos($p) $a
10287 set arcout($id) [list $a]
10288}
10289
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010290# This implements a cache for the topology information.
10291# The cache saves, for each arc, the start and end of the arc,
10292# the ids on the arc, and the outgoing arcs from the end.
10293proc readcache {f} {
10294 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10295 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10296 global allcwait
10297
10298 set a $nextarc
10299 set lim $cachedarcs
10300 if {$lim - $a > 500} {
10301 set lim [expr {$a + 500}]
10302 }
10303 if {[catch {
10304 if {$a == $lim} {
10305 # finish reading the cache and setting up arctags, etc.
10306 set line [gets $f]
10307 if {$line ne "1"} {error "bad final version"}
10308 close $f
10309 foreach id [array names idtags] {
10310 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10311 [llength $allparents($id)] == 1} {
10312 set a [lindex $arcnos($id) 0]
10313 if {$arctags($a) eq {}} {
10314 recalcarc $a
10315 }
10316 }
10317 }
10318 foreach id [array names idheads] {
10319 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10320 [llength $allparents($id)] == 1} {
10321 set a [lindex $arcnos($id) 0]
10322 if {$archeads($a) eq {}} {
10323 recalcarc $a
10324 }
10325 }
10326 }
10327 foreach id [lsort -unique $possible_seeds] {
10328 if {$arcnos($id) eq {}} {
10329 lappend seeds $id
10330 }
10331 }
10332 set allcwait 0
10333 } else {
10334 while {[incr a] <= $lim} {
10335 set line [gets $f]
10336 if {[llength $line] != 3} {error "bad line"}
10337 set s [lindex $line 0]
10338 set arcstart($a) $s
10339 lappend arcout($s) $a
10340 if {![info exists arcnos($s)]} {
10341 lappend possible_seeds $s
10342 set arcnos($s) {}
10343 }
10344 set e [lindex $line 1]
10345 if {$e eq {}} {
10346 set growing($a) 1
10347 } else {
10348 set arcend($a) $e
10349 if {![info exists arcout($e)]} {
10350 set arcout($e) {}
10351 }
10352 }
10353 set arcids($a) [lindex $line 2]
10354 foreach id $arcids($a) {
10355 lappend allparents($s) $id
10356 set s $id
10357 lappend arcnos($id) $a
10358 }
10359 if {![info exists allparents($s)]} {
10360 set allparents($s) {}
10361 }
10362 set arctags($a) {}
10363 set archeads($a) {}
10364 }
10365 set nextarc [expr {$a - 1}]
10366 }
10367 } err]} {
10368 dropcache $err
10369 return 0
10370 }
10371 if {!$allcwait} {
10372 getallcommits
10373 }
10374 return $allcwait
10375}
10376
10377proc getcache {f} {
10378 global nextarc cachedarcs possible_seeds
10379
10380 if {[catch {
10381 set line [gets $f]
10382 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10383 # make sure it's an integer
10384 set cachedarcs [expr {int([lindex $line 1])}]
10385 if {$cachedarcs < 0} {error "bad number of arcs"}
10386 set nextarc 0
10387 set possible_seeds {}
10388 run readcache $f
10389 } err]} {
10390 dropcache $err
10391 }
10392 return 0
10393}
10394
10395proc dropcache {err} {
10396 global allcwait nextarc cachedarcs seeds
10397
10398 #puts "dropping cache ($err)"
10399 foreach v {arcnos arcout arcids arcstart arcend growing \
10400 arctags archeads allparents allchildren} {
10401 global $v
Paul Mackerras009409f2015-05-02 20:53:36 +100010402 unset -nocomplain $v
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010403 }
10404 set allcwait 0
10405 set nextarc 0
10406 set cachedarcs 0
10407 set seeds {}
10408 getallcommits
10409}
10410
10411proc writecache {f} {
10412 global cachearc cachedarcs allccache
10413 global arcstart arcend arcnos arcids arcout
10414
10415 set a $cachearc
10416 set lim $cachedarcs
10417 if {$lim - $a > 1000} {
10418 set lim [expr {$a + 1000}]
10419 }
10420 if {[catch {
10421 while {[incr a] <= $lim} {
10422 if {[info exists arcend($a)]} {
10423 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10424 } else {
10425 puts $f [list $arcstart($a) {} $arcids($a)]
10426 }
10427 }
10428 } err]} {
10429 catch {close $f}
10430 catch {file delete $allccache}
10431 #puts "writing cache failed ($err)"
10432 return 0
10433 }
10434 set cachearc [expr {$a - 1}]
10435 if {$a > $cachedarcs} {
10436 puts $f "1"
10437 close $f
10438 return 0
10439 }
10440 return 1
10441}
10442
10443proc savecache {} {
10444 global nextarc cachedarcs cachearc allccache
10445
10446 if {$nextarc == $cachedarcs} return
10447 set cachearc 0
10448 set cachedarcs $nextarc
10449 catch {
10450 set f [open $allccache w]
10451 puts $f [list 1 $cachedarcs]
10452 run writecache $f
10453 }
10454}
10455
Paul Mackerrase11f1232007-06-16 20:29:25 +100010456# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10457# or 0 if neither is true.
10458proc anc_or_desc {a b} {
10459 global arcout arcstart arcend arcnos cached_isanc
10460
10461 if {$arcnos($a) eq $arcnos($b)} {
10462 # Both are on the same arc(s); either both are the same BMP,
10463 # or if one is not a BMP, the other is also not a BMP or is
10464 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +100010465 # Or both can be BMPs with no incoming arcs.
10466 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010467 return 0
10468 }
10469 # assert {[llength $arcnos($a)] == 1}
10470 set arc [lindex $arcnos($a) 0]
10471 set i [lsearch -exact $arcids($arc) $a]
10472 set j [lsearch -exact $arcids($arc) $b]
10473 if {$i < 0 || $i > $j} {
10474 return 1
10475 } else {
10476 return -1
10477 }
10478 }
10479
10480 if {![info exists arcout($a)]} {
10481 set arc [lindex $arcnos($a) 0]
10482 if {[info exists arcend($arc)]} {
10483 set aend $arcend($arc)
10484 } else {
10485 set aend {}
10486 }
10487 set a $arcstart($arc)
10488 } else {
10489 set aend $a
10490 }
10491 if {![info exists arcout($b)]} {
10492 set arc [lindex $arcnos($b) 0]
10493 if {[info exists arcend($arc)]} {
10494 set bend $arcend($arc)
10495 } else {
10496 set bend {}
10497 }
10498 set b $arcstart($arc)
10499 } else {
10500 set bend $b
10501 }
10502 if {$a eq $bend} {
10503 return 1
10504 }
10505 if {$b eq $aend} {
10506 return -1
10507 }
10508 if {[info exists cached_isanc($a,$bend)]} {
10509 if {$cached_isanc($a,$bend)} {
10510 return 1
10511 }
10512 }
10513 if {[info exists cached_isanc($b,$aend)]} {
10514 if {$cached_isanc($b,$aend)} {
10515 return -1
10516 }
10517 if {[info exists cached_isanc($a,$bend)]} {
10518 return 0
10519 }
10520 }
10521
10522 set todo [list $a $b]
10523 set anc($a) a
10524 set anc($b) b
10525 for {set i 0} {$i < [llength $todo]} {incr i} {
10526 set x [lindex $todo $i]
10527 if {$anc($x) eq {}} {
10528 continue
10529 }
10530 foreach arc $arcnos($x) {
10531 set xd $arcstart($arc)
10532 if {$xd eq $bend} {
10533 set cached_isanc($a,$bend) 1
10534 set cached_isanc($b,$aend) 0
10535 return 1
10536 } elseif {$xd eq $aend} {
10537 set cached_isanc($b,$aend) 1
10538 set cached_isanc($a,$bend) 0
10539 return -1
10540 }
10541 if {![info exists anc($xd)]} {
10542 set anc($xd) $anc($x)
10543 lappend todo $xd
10544 } elseif {$anc($xd) ne $anc($x)} {
10545 set anc($xd) {}
10546 }
10547 }
10548 }
10549 set cached_isanc($a,$bend) 0
10550 set cached_isanc($b,$aend) 0
10551 return 0
10552}
10553
10554# This identifies whether $desc has an ancestor that is
10555# a growing tip of the graph and which is not an ancestor of $anc
10556# and returns 0 if so and 1 if not.
10557# If we subsequently discover a tag on such a growing tip, and that
10558# turns out to be a descendent of $anc (which it could, since we
10559# don't necessarily see children before parents), then $desc
10560# isn't a good choice to display as a descendent tag of
10561# $anc (since it is the descendent of another tag which is
10562# a descendent of $anc). Similarly, $anc isn't a good choice to
10563# display as a ancestor tag of $desc.
10564#
10565proc is_certain {desc anc} {
10566 global arcnos arcout arcstart arcend growing problems
10567
10568 set certain {}
10569 if {[llength $arcnos($anc)] == 1} {
10570 # tags on the same arc are certain
10571 if {$arcnos($desc) eq $arcnos($anc)} {
10572 return 1
10573 }
10574 if {![info exists arcout($anc)]} {
10575 # if $anc is partway along an arc, use the start of the arc instead
10576 set a [lindex $arcnos($anc) 0]
10577 set anc $arcstart($a)
10578 }
10579 }
10580 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
10581 set x $desc
10582 } else {
10583 set a [lindex $arcnos($desc) 0]
10584 set x $arcend($a)
10585 }
10586 if {$x == $anc} {
10587 return 1
10588 }
10589 set anclist [list $x]
10590 set dl($x) 1
10591 set nnh 1
10592 set ngrowanc 0
10593 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
10594 set x [lindex $anclist $i]
10595 if {$dl($x)} {
10596 incr nnh -1
10597 }
10598 set done($x) 1
10599 foreach a $arcout($x) {
10600 if {[info exists growing($a)]} {
10601 if {![info exists growanc($x)] && $dl($x)} {
10602 set growanc($x) 1
10603 incr ngrowanc
10604 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010605 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010606 set y $arcend($a)
10607 if {[info exists dl($y)]} {
10608 if {$dl($y)} {
10609 if {!$dl($x)} {
10610 set dl($y) 0
10611 if {![info exists done($y)]} {
10612 incr nnh -1
10613 }
10614 if {[info exists growanc($x)]} {
10615 incr ngrowanc -1
10616 }
10617 set xl [list $y]
10618 for {set k 0} {$k < [llength $xl]} {incr k} {
10619 set z [lindex $xl $k]
10620 foreach c $arcout($z) {
10621 if {[info exists arcend($c)]} {
10622 set v $arcend($c)
10623 if {[info exists dl($v)] && $dl($v)} {
10624 set dl($v) 0
10625 if {![info exists done($v)]} {
10626 incr nnh -1
10627 }
10628 if {[info exists growanc($v)]} {
10629 incr ngrowanc -1
10630 }
10631 lappend xl $v
10632 }
10633 }
10634 }
10635 }
10636 }
10637 }
10638 } elseif {$y eq $anc || !$dl($x)} {
10639 set dl($y) 0
10640 lappend anclist $y
10641 } else {
10642 set dl($y) 1
10643 lappend anclist $y
10644 incr nnh
10645 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010646 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010647 }
10648 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010649 foreach x [array names growanc] {
10650 if {$dl($x)} {
10651 return 0
10652 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010653 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010654 }
10655 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010656}
10657
Paul Mackerrase11f1232007-06-16 20:29:25 +100010658proc validate_arctags {a} {
10659 global arctags idtags
10660
10661 set i -1
10662 set na $arctags($a)
10663 foreach id $arctags($a) {
10664 incr i
10665 if {![info exists idtags($id)]} {
10666 set na [lreplace $na $i $i]
10667 incr i -1
10668 }
10669 }
10670 set arctags($a) $na
10671}
10672
10673proc validate_archeads {a} {
10674 global archeads idheads
10675
10676 set i -1
10677 set na $archeads($a)
10678 foreach id $archeads($a) {
10679 incr i
10680 if {![info exists idheads($id)]} {
10681 set na [lreplace $na $i $i]
10682 incr i -1
10683 }
10684 }
10685 set archeads($a) $na
10686}
10687
10688# Return the list of IDs that have tags that are descendents of id,
10689# ignoring IDs that are descendents of IDs already reported.
10690proc desctags {id} {
10691 global arcnos arcstart arcids arctags idtags allparents
10692 global growing cached_dtags
10693
10694 if {![info exists allparents($id)]} {
10695 return {}
10696 }
10697 set t1 [clock clicks -milliseconds]
10698 set argid $id
10699 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10700 # part-way along an arc; check that arc first
10701 set a [lindex $arcnos($id) 0]
10702 if {$arctags($a) ne {}} {
10703 validate_arctags $a
10704 set i [lsearch -exact $arcids($a) $id]
10705 set tid {}
10706 foreach t $arctags($a) {
10707 set j [lsearch -exact $arcids($a) $t]
10708 if {$j >= $i} break
10709 set tid $t
10710 }
10711 if {$tid ne {}} {
10712 return $tid
10713 }
10714 }
10715 set id $arcstart($a)
10716 if {[info exists idtags($id)]} {
10717 return $id
10718 }
10719 }
10720 if {[info exists cached_dtags($id)]} {
10721 return $cached_dtags($id)
10722 }
10723
10724 set origid $id
10725 set todo [list $id]
10726 set queued($id) 1
10727 set nc 1
10728 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10729 set id [lindex $todo $i]
10730 set done($id) 1
10731 set ta [info exists hastaggedancestor($id)]
10732 if {!$ta} {
10733 incr nc -1
10734 }
10735 # ignore tags on starting node
10736 if {!$ta && $i > 0} {
10737 if {[info exists idtags($id)]} {
10738 set tagloc($id) $id
10739 set ta 1
10740 } elseif {[info exists cached_dtags($id)]} {
10741 set tagloc($id) $cached_dtags($id)
10742 set ta 1
10743 }
10744 }
10745 foreach a $arcnos($id) {
10746 set d $arcstart($a)
10747 if {!$ta && $arctags($a) ne {}} {
10748 validate_arctags $a
10749 if {$arctags($a) ne {}} {
10750 lappend tagloc($id) [lindex $arctags($a) end]
10751 }
10752 }
10753 if {$ta || $arctags($a) ne {}} {
10754 set tomark [list $d]
10755 for {set j 0} {$j < [llength $tomark]} {incr j} {
10756 set dd [lindex $tomark $j]
10757 if {![info exists hastaggedancestor($dd)]} {
10758 if {[info exists done($dd)]} {
10759 foreach b $arcnos($dd) {
10760 lappend tomark $arcstart($b)
10761 }
10762 if {[info exists tagloc($dd)]} {
10763 unset tagloc($dd)
10764 }
10765 } elseif {[info exists queued($dd)]} {
10766 incr nc -1
10767 }
10768 set hastaggedancestor($dd) 1
10769 }
10770 }
10771 }
10772 if {![info exists queued($d)]} {
10773 lappend todo $d
10774 set queued($d) 1
10775 if {![info exists hastaggedancestor($d)]} {
10776 incr nc
10777 }
10778 }
10779 }
10780 }
10781 set tags {}
10782 foreach id [array names tagloc] {
10783 if {![info exists hastaggedancestor($id)]} {
10784 foreach t $tagloc($id) {
10785 if {[lsearch -exact $tags $t] < 0} {
10786 lappend tags $t
10787 }
10788 }
10789 }
10790 }
10791 set t2 [clock clicks -milliseconds]
10792 set loopix $i
10793
10794 # remove tags that are descendents of other tags
10795 for {set i 0} {$i < [llength $tags]} {incr i} {
10796 set a [lindex $tags $i]
10797 for {set j 0} {$j < $i} {incr j} {
10798 set b [lindex $tags $j]
10799 set r [anc_or_desc $a $b]
10800 if {$r == 1} {
10801 set tags [lreplace $tags $j $j]
10802 incr j -1
10803 incr i -1
10804 } elseif {$r == -1} {
10805 set tags [lreplace $tags $i $i]
10806 incr i -1
10807 break
10808 }
10809 }
10810 }
10811
10812 if {[array names growing] ne {}} {
10813 # graph isn't finished, need to check if any tag could get
10814 # eclipsed by another tag coming later. Simply ignore any
10815 # tags that could later get eclipsed.
10816 set ctags {}
10817 foreach t $tags {
10818 if {[is_certain $t $origid]} {
10819 lappend ctags $t
10820 }
10821 }
10822 if {$tags eq $ctags} {
10823 set cached_dtags($origid) $tags
10824 } else {
10825 set tags $ctags
10826 }
10827 } else {
10828 set cached_dtags($origid) $tags
10829 }
10830 set t3 [clock clicks -milliseconds]
10831 if {0 && $t3 - $t1 >= 100} {
10832 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
10833 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10834 }
10835 return $tags
10836}
10837
10838proc anctags {id} {
10839 global arcnos arcids arcout arcend arctags idtags allparents
10840 global growing cached_atags
10841
10842 if {![info exists allparents($id)]} {
10843 return {}
10844 }
10845 set t1 [clock clicks -milliseconds]
10846 set argid $id
10847 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10848 # part-way along an arc; check that arc first
10849 set a [lindex $arcnos($id) 0]
10850 if {$arctags($a) ne {}} {
10851 validate_arctags $a
10852 set i [lsearch -exact $arcids($a) $id]
10853 foreach t $arctags($a) {
10854 set j [lsearch -exact $arcids($a) $t]
10855 if {$j > $i} {
10856 return $t
10857 }
10858 }
10859 }
10860 if {![info exists arcend($a)]} {
10861 return {}
10862 }
10863 set id $arcend($a)
10864 if {[info exists idtags($id)]} {
10865 return $id
10866 }
10867 }
10868 if {[info exists cached_atags($id)]} {
10869 return $cached_atags($id)
10870 }
10871
10872 set origid $id
10873 set todo [list $id]
10874 set queued($id) 1
10875 set taglist {}
10876 set nc 1
10877 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10878 set id [lindex $todo $i]
10879 set done($id) 1
10880 set td [info exists hastaggeddescendent($id)]
10881 if {!$td} {
10882 incr nc -1
10883 }
10884 # ignore tags on starting node
10885 if {!$td && $i > 0} {
10886 if {[info exists idtags($id)]} {
10887 set tagloc($id) $id
10888 set td 1
10889 } elseif {[info exists cached_atags($id)]} {
10890 set tagloc($id) $cached_atags($id)
10891 set td 1
10892 }
10893 }
10894 foreach a $arcout($id) {
10895 if {!$td && $arctags($a) ne {}} {
10896 validate_arctags $a
10897 if {$arctags($a) ne {}} {
10898 lappend tagloc($id) [lindex $arctags($a) 0]
10899 }
10900 }
10901 if {![info exists arcend($a)]} continue
10902 set d $arcend($a)
10903 if {$td || $arctags($a) ne {}} {
10904 set tomark [list $d]
10905 for {set j 0} {$j < [llength $tomark]} {incr j} {
10906 set dd [lindex $tomark $j]
10907 if {![info exists hastaggeddescendent($dd)]} {
10908 if {[info exists done($dd)]} {
10909 foreach b $arcout($dd) {
10910 if {[info exists arcend($b)]} {
10911 lappend tomark $arcend($b)
10912 }
10913 }
10914 if {[info exists tagloc($dd)]} {
10915 unset tagloc($dd)
10916 }
10917 } elseif {[info exists queued($dd)]} {
10918 incr nc -1
10919 }
10920 set hastaggeddescendent($dd) 1
10921 }
10922 }
10923 }
10924 if {![info exists queued($d)]} {
10925 lappend todo $d
10926 set queued($d) 1
10927 if {![info exists hastaggeddescendent($d)]} {
10928 incr nc
10929 }
10930 }
10931 }
10932 }
10933 set t2 [clock clicks -milliseconds]
10934 set loopix $i
10935 set tags {}
10936 foreach id [array names tagloc] {
10937 if {![info exists hastaggeddescendent($id)]} {
10938 foreach t $tagloc($id) {
10939 if {[lsearch -exact $tags $t] < 0} {
10940 lappend tags $t
10941 }
10942 }
10943 }
10944 }
10945
10946 # remove tags that are ancestors of other tags
10947 for {set i 0} {$i < [llength $tags]} {incr i} {
10948 set a [lindex $tags $i]
10949 for {set j 0} {$j < $i} {incr j} {
10950 set b [lindex $tags $j]
10951 set r [anc_or_desc $a $b]
10952 if {$r == -1} {
10953 set tags [lreplace $tags $j $j]
10954 incr j -1
10955 incr i -1
10956 } elseif {$r == 1} {
10957 set tags [lreplace $tags $i $i]
10958 incr i -1
10959 break
10960 }
10961 }
10962 }
10963
10964 if {[array names growing] ne {}} {
10965 # graph isn't finished, need to check if any tag could get
10966 # eclipsed by another tag coming later. Simply ignore any
10967 # tags that could later get eclipsed.
10968 set ctags {}
10969 foreach t $tags {
10970 if {[is_certain $origid $t]} {
10971 lappend ctags $t
10972 }
10973 }
10974 if {$tags eq $ctags} {
10975 set cached_atags($origid) $tags
10976 } else {
10977 set tags $ctags
10978 }
10979 } else {
10980 set cached_atags($origid) $tags
10981 }
10982 set t3 [clock clicks -milliseconds]
10983 if {0 && $t3 - $t1 >= 100} {
10984 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
10985 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10986 }
10987 return $tags
10988}
10989
10990# Return the list of IDs that have heads that are descendents of id,
10991# including id itself if it has a head.
10992proc descheads {id} {
10993 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010994 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100010995
10996 if {![info exists allparents($id)]} {
10997 return {}
10998 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010999 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011000 if {![info exists arcout($id)]} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011001 # part-way along an arc; check it first
11002 set a [lindex $arcnos($id) 0]
11003 if {$archeads($a) ne {}} {
11004 validate_archeads $a
11005 set i [lsearch -exact $arcids($a) $id]
11006 foreach t $archeads($a) {
11007 set j [lsearch -exact $arcids($a) $t]
11008 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011009 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100011010 }
11011 }
11012 set id $arcstart($a)
11013 }
11014 set origid $id
11015 set todo [list $id]
11016 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011017 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011018 for {set i 0} {$i < [llength $todo]} {incr i} {
11019 set id [lindex $todo $i]
11020 if {[info exists cached_dheads($id)]} {
11021 set ret [concat $ret $cached_dheads($id)]
11022 } else {
11023 if {[info exists idheads($id)]} {
11024 lappend ret $id
11025 }
11026 foreach a $arcnos($id) {
11027 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100011028 validate_archeads $a
11029 if {$archeads($a) ne {}} {
11030 set ret [concat $ret $archeads($a)]
11031 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011032 }
11033 set d $arcstart($a)
11034 if {![info exists seen($d)]} {
11035 lappend todo $d
11036 set seen($d) 1
11037 }
11038 }
11039 }
11040 }
11041 set ret [lsort -unique $ret]
11042 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011043 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100011044}
11045
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011046proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011047 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011048
Paul Mackerrase11f1232007-06-16 20:29:25 +100011049 if {![info exists arcnos($id)]} return
11050 if {![info exists arcout($id)]} {
11051 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011052 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011053 unset -nocomplain cached_dtags
11054 unset -nocomplain cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011055}
11056
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011057proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011058 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011059
Paul Mackerrase11f1232007-06-16 20:29:25 +100011060 if {![info exists arcnos($hid)]} return
11061 if {![info exists arcout($hid)]} {
11062 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011063 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011064 unset -nocomplain cached_dheads
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011065}
11066
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011067proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011068 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011069
Paul Mackerras009409f2015-05-02 20:53:36 +100011070 unset -nocomplain cached_dheads
Paul Mackerras10299152006-08-02 09:52:01 +100011071}
11072
Paul Mackerrase11f1232007-06-16 20:29:25 +100011073proc movedhead {hid head} {
11074 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011075
Paul Mackerrase11f1232007-06-16 20:29:25 +100011076 if {![info exists arcnos($hid)]} return
11077 if {![info exists arcout($hid)]} {
11078 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011079 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011080 unset -nocomplain cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011081}
11082
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011083proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070011084 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100011085 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011086
Paul Mackerrase11f1232007-06-16 20:29:25 +100011087 foreach id [concat [array names idheads] [array names idtags]] {
11088 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
11089 set a [lindex $arcnos($id) 0]
11090 if {![info exists donearc($a)]} {
11091 recalcarc $a
11092 set donearc($a) 1
11093 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011094 }
11095 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011096 unset -nocomplain cached_tagcontent
11097 unset -nocomplain cached_dtags
11098 unset -nocomplain cached_atags
11099 unset -nocomplain cached_dheads
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011100}
11101
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011102proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011103 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011104
11105 set refids [concat [array names idtags] \
11106 [array names idheads] [array names idotherrefs]]
11107 foreach id $refids {
11108 if {![info exists ref($id)]} {
11109 set ref($id) [listrefs $id]
11110 }
11111 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011112 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011113 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011114 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011115 set refids [lsort -unique [concat $refids [array names idtags] \
11116 [array names idheads] [array names idotherrefs]]]
11117 foreach id $refids {
11118 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011119 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011120 redrawtags $id
11121 }
11122 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011123 if {$oldmainhead ne $mainheadid} {
11124 redrawtags $oldmainhead
11125 redrawtags $mainheadid
11126 }
Paul Mackerras887c9962007-08-20 19:36:20 +100011127 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011128}
11129
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011130proc listrefs {id} {
11131 global idtags idheads idotherrefs
11132
11133 set x {}
11134 if {[info exists idtags($id)]} {
11135 set x $idtags($id)
11136 }
11137 set y {}
11138 if {[info exists idheads($id)]} {
11139 set y $idheads($id)
11140 }
11141 set z {}
11142 if {[info exists idotherrefs($id)]} {
11143 set z $idotherrefs($id)
11144 }
11145 return [list $x $y $z]
11146}
11147
Paul Mackerras4399fe32013-01-03 10:10:31 +110011148proc add_tag_ctext {tag} {
11149 global ctext cached_tagcontent tagids
11150
11151 if {![info exists cached_tagcontent($tag)]} {
11152 catch {
11153 set cached_tagcontent($tag) [exec git cat-file -p $tag]
11154 }
11155 }
11156 $ctext insert end "[mc "Tag"]: $tag\n" bold
11157 if {[info exists cached_tagcontent($tag)]} {
11158 set text $cached_tagcontent($tag)
11159 } else {
11160 set text "[mc "Id"]: $tagids($tag)"
11161 }
11162 appendwithlinks $text {}
11163}
11164
Paul Mackerras106288c2005-08-19 23:11:39 +100011165proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070011166 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100011167
11168 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +110011169 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100011170 }
11171 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100011172 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011173 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100011174 set linknum 0
Paul Mackerras4399fe32013-01-03 10:10:31 +110011175 add_tag_ctext $tag
11176 maybe_scroll_ctext 1
11177 $ctext conf -state disabled
11178 init_flist {}
11179}
11180
11181proc showtags {id isnew} {
11182 global idtags ctext linknum
11183
11184 if {$isnew} {
11185 addtohistory [list showtags $id 0] savectextpos
Paul Mackerras62d3ea62006-09-11 10:36:53 +100011186 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011187 $ctext conf -state normal
11188 clear_ctext
11189 settabs 0
11190 set linknum 0
11191 set sep {}
11192 foreach tag $idtags($id) {
11193 $ctext insert end $sep
11194 add_tag_ctext $tag
11195 set sep "\n\n"
Paul Mackerras106288c2005-08-19 23:11:39 +100011196 }
Pat Thoytsa80e82f2009-11-14 13:21:09 +000011197 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100011198 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100011199 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100011200}
11201
Paul Mackerras1d10f362005-05-15 12:55:47 +000011202proc doquit {} {
11203 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010011204 global gitktmpdir
11205
Paul Mackerras1d10f362005-05-15 12:55:47 +000011206 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050011207 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000011208 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010011209
11210 if {[info exists gitktmpdir]} {
11211 catch {file delete -force $gitktmpdir}
11212 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000011213}
11214
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011215proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011216 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011217
11218 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011219 ${NS}::button $top.${font}but -text $which \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011220 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011221 ${NS}::label $top.$font -relief flat -font $font \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011222 -text $fontattr($font,family) -justify left
11223 grid x $top.${font}but $top.$font -sticky w
11224}
11225
11226proc choosefont {font which} {
11227 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010011228 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011229
11230 set fontparam(which) $which
11231 set fontparam(font) $font
11232 set fontparam(family) [font actual $font -family]
11233 set fontparam(size) $fontattr($font,size)
11234 set fontparam(weight) $fontattr($font,weight)
11235 set fontparam(slant) $fontattr($font,slant)
11236 set top .gitkfont
11237 set fonttop $top
11238 if {![winfo exists $top]} {
11239 font create sample
11240 eval font config sample [font actual $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011241 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011242 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010011243 wm title $top [mc "Gitk font chooser"]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011244 ${NS}::label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011245 pack $top.l -side top
11246 set fontlist [lsort [font families]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011247 ${NS}::frame $top.f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011248 listbox $top.f.fam -listvariable fontlist \
11249 -yscrollcommand [list $top.f.sb set]
11250 bind $top.f.fam <<ListboxSelect>> selfontfam
Pat Thoytsd93f1712009-04-17 01:24:35 +010011251 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011252 pack $top.f.sb -side right -fill y
11253 pack $top.f.fam -side left -fill both -expand 1
11254 pack $top.f -side top -fill both -expand 1
Pat Thoytsd93f1712009-04-17 01:24:35 +010011255 ${NS}::frame $top.g
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011256 spinbox $top.g.size -from 4 -to 40 -width 4 \
11257 -textvariable fontparam(size) \
11258 -validatecommand {string is integer -strict %s}
11259 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011260 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011261 -variable fontparam(weight) -onvalue bold -offvalue normal
11262 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011263 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011264 -variable fontparam(slant) -onvalue italic -offvalue roman
11265 pack $top.g.size $top.g.bold $top.g.ital -side left
11266 pack $top.g -side top
11267 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
11268 -background white
11269 $top.c create text 100 25 -anchor center -text $which -font sample \
11270 -fill black -tags text
11271 bind $top.c <Configure> [list centertext $top.c]
11272 pack $top.c -side top -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +010011273 ${NS}::frame $top.buts
11274 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
11275 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011276 bind $top <Key-Return> fontok
11277 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011278 grid $top.buts.ok $top.buts.can
11279 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11280 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11281 pack $top.buts -side bottom -fill x
11282 trace add variable fontparam write chg_fontparam
11283 } else {
11284 raise $top
11285 $top.c itemconf text -text $which
11286 }
11287 set i [lsearch -exact $fontlist $fontparam(family)]
11288 if {$i >= 0} {
11289 $top.f.fam selection set $i
11290 $top.f.fam see $i
11291 }
11292}
11293
11294proc centertext {w} {
11295 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11296}
11297
11298proc fontok {} {
11299 global fontparam fontpref prefstop
11300
11301 set f $fontparam(font)
11302 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11303 if {$fontparam(weight) eq "bold"} {
11304 lappend fontpref($f) "bold"
11305 }
11306 if {$fontparam(slant) eq "italic"} {
11307 lappend fontpref($f) "italic"
11308 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011309 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011310 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011311
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011312 fontcan
11313}
11314
11315proc fontcan {} {
11316 global fonttop fontparam
11317
11318 if {[info exists fonttop]} {
11319 catch {destroy $fonttop}
11320 catch {font delete sample}
11321 unset fonttop
11322 unset fontparam
11323 }
11324}
11325
Pat Thoytsd93f1712009-04-17 01:24:35 +010011326if {[package vsatisfies [package provide Tk] 8.6]} {
11327 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11328 # function to make use of it.
11329 proc choosefont {font which} {
11330 tk fontchooser configure -title $which -font $font \
11331 -command [list on_choosefont $font $which]
11332 tk fontchooser show
11333 }
11334 proc on_choosefont {font which newfont} {
11335 global fontparam
11336 puts stderr "$font $newfont"
11337 array set f [font actual $newfont]
11338 set fontparam(which) $which
11339 set fontparam(font) $font
11340 set fontparam(family) $f(-family)
11341 set fontparam(size) $f(-size)
11342 set fontparam(weight) $f(-weight)
11343 set fontparam(slant) $f(-slant)
11344 fontok
11345 }
11346}
11347
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011348proc selfontfam {} {
11349 global fonttop fontparam
11350
11351 set i [$fonttop.f.fam curselection]
11352 if {$i ne {}} {
11353 set fontparam(family) [$fonttop.f.fam get $i]
11354 }
11355}
11356
11357proc chg_fontparam {v sub op} {
11358 global fontparam
11359
11360 font config sample -$sub $fontparam($sub)
11361}
11362
Pat Thoyts44acce02011-12-13 14:56:49 +000011363# Create a property sheet tab page
11364proc create_prefs_page {w} {
11365 global NS
11366 set parent [join [lrange [split $w .] 0 end-1] .]
11367 if {[winfo class $parent] eq "TNotebook"} {
11368 ${NS}::frame $w
11369 } else {
11370 ${NS}::labelframe $w
11371 }
11372}
11373
11374proc prefspage_general {notebook} {
11375 global NS maxwidth maxgraphpct showneartags showlocalchanges
11376 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011377 global hideremotes want_ttk have_ttk maxrefs
Pat Thoyts44acce02011-12-13 14:56:49 +000011378
11379 set page [create_prefs_page $notebook.general]
11380
11381 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11382 grid $page.ldisp - -sticky w -pady 10
11383 ${NS}::label $page.spacer -text " "
11384 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11385 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11386 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
Alex Henrie8a1692f2015-01-22 01:19:39 -070011387 #xgettext:no-tcl-format
Pat Thoyts44acce02011-12-13 14:56:49 +000011388 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11389 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11390 grid x $page.maxpctl $page.maxpct -sticky w
11391 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
11392 -variable showlocalchanges
11393 grid x $page.showlocal -sticky w
11394 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
11395 -variable autoselect
11396 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11397 grid x $page.autoselect $page.autosellen -sticky w
11398 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
11399 -variable hideremotes
11400 grid x $page.hideremotes -sticky w
11401
11402 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11403 grid $page.ddisp - -sticky w -pady 10
11404 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11405 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11406 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011407 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Pat Thoyts44acce02011-12-13 14:56:49 +000011408 -variable showneartags
11409 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011410 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11411 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11412 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011413 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
11414 -variable limitdiffs
11415 grid x $page.ldiff -sticky w
11416 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
11417 -variable perfile_attrs
11418 grid x $page.lattr -sticky w
11419
11420 ${NS}::entry $page.extdifft -textvariable extdifftool
11421 ${NS}::frame $page.extdifff
11422 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11423 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11424 pack $page.extdifff.l $page.extdifff.b -side left
11425 pack configure $page.extdifff.l -padx 10
11426 grid x $page.extdifff $page.extdifft -sticky ew
11427
11428 ${NS}::label $page.lgen -text [mc "General options"]
11429 grid $page.lgen - -sticky w -pady 10
11430 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
11431 -text [mc "Use themed widgets"]
11432 if {$have_ttk} {
11433 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
11434 } else {
11435 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
11436 }
11437 grid x $page.want_ttk $page.ttk_note -sticky w
11438 return $page
11439}
11440
11441proc prefspage_colors {notebook} {
11442 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
11443
11444 set page [create_prefs_page $notebook.colors]
11445
11446 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11447 grid $page.cdisp - -sticky w -pady 10
11448 label $page.ui -padx 40 -relief sunk -background $uicolor
11449 ${NS}::button $page.uibut -text [mc "Interface"] \
11450 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11451 grid x $page.uibut $page.ui -sticky w
11452 label $page.bg -padx 40 -relief sunk -background $bgcolor
11453 ${NS}::button $page.bgbut -text [mc "Background"] \
11454 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
11455 grid x $page.bgbut $page.bg -sticky w
11456 label $page.fg -padx 40 -relief sunk -background $fgcolor
11457 ${NS}::button $page.fgbut -text [mc "Foreground"] \
11458 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
11459 grid x $page.fgbut $page.fg -sticky w
11460 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11461 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
11462 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11463 [list $ctext tag conf d0 -foreground]]
11464 grid x $page.diffoldbut $page.diffold -sticky w
11465 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11466 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
11467 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11468 [list $ctext tag conf dresult -foreground]]
11469 grid x $page.diffnewbut $page.diffnew -sticky w
11470 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11471 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
11472 -command [list choosecolor diffcolors 2 $page.hunksep \
11473 [mc "diff hunk header"] \
11474 [list $ctext tag conf hunksep -foreground]]
11475 grid x $page.hunksepbut $page.hunksep -sticky w
11476 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11477 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
11478 -command [list choosecolor markbgcolor {} $page.markbgsep \
11479 [mc "marked line background"] \
11480 [list $ctext tag conf omark -background]]
11481 grid x $page.markbgbut $page.markbgsep -sticky w
11482 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11483 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
11484 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
11485 grid x $page.selbgbut $page.selbgsep -sticky w
11486 return $page
11487}
11488
11489proc prefspage_fonts {notebook} {
11490 global NS
11491 set page [create_prefs_page $notebook.fonts]
11492 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11493 grid $page.cfont - -sticky w -pady 10
11494 mkfontdisp mainfont $page [mc "Main font"]
11495 mkfontdisp textfont $page [mc "Diff display font"]
11496 mkfontdisp uifont $page [mc "User interface font"]
11497 return $page
11498}
11499
Paul Mackerras712fcc02005-11-30 09:28:16 +110011500proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011501 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011502 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011503 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011504 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011505 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011506
Paul Mackerras712fcc02005-11-30 09:28:16 +110011507 set top .gitkprefs
11508 set prefstop $top
11509 if {[winfo exists $top]} {
11510 raise $top
11511 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011512 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011513 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011514 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110011515 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011516 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011517 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011518 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011519 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011520
Pat Thoyts44acce02011-12-13 14:56:49 +000011521 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
11522 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011523 } else {
Pat Thoyts44acce02011-12-13 14:56:49 +000011524 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011525 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011526
Pat Thoyts44acce02011-12-13 14:56:49 +000011527 lappend pages [prefspage_general $notebook] [mc "General"]
11528 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11529 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011530 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011531 foreach {page title} $pages {
11532 if {$use_notebook} {
11533 $notebook add $page -text $title
11534 } else {
11535 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11536 -text $title -command [list raise $page]]
11537 $page configure -text $title
11538 grid $btn -row 0 -column [incr col] -sticky w
11539 grid $page -row 1 -column 0 -sticky news -columnspan 100
11540 }
11541 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011542
Pat Thoyts44acce02011-12-13 14:56:49 +000011543 if {!$use_notebook} {
11544 grid columnconfigure $notebook 0 -weight 1
11545 grid rowconfigure $notebook 1 -weight 1
11546 raise [lindex $pages 0]
11547 }
11548
11549 grid $notebook -sticky news -padx 2 -pady 2
11550 grid rowconfigure $top 0 -weight 1
11551 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011552
Pat Thoytsd93f1712009-04-17 01:24:35 +010011553 ${NS}::frame $top.buts
11554 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11555 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011556 bind $top <Key-Return> prefsok
11557 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011558 grid $top.buts.ok $top.buts.can
11559 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11560 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11561 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011562 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011563 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011564}
11565
Thomas Arcila314f5de2008-03-24 12:55:36 +010011566proc choose_extdiff {} {
11567 global extdifftool
11568
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011569 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011570 if {$prog ne {}} {
11571 set extdifftool $prog
11572 }
11573}
11574
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011575proc choosecolor {v vi w x cmd} {
11576 global $v
11577
11578 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011579 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011580 if {$c eq {}} return
11581 $w conf -background $c
11582 lset $v $vi $c
11583 eval $cmd $c
11584}
11585
Mark Levedahl60378c02007-05-20 12:12:48 -040011586proc setselbg {c} {
11587 global bglist cflist
11588 foreach w $bglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011589 if {[winfo exists $w]} {
11590 $w configure -selectbackground $c
11591 }
Mark Levedahl60378c02007-05-20 12:12:48 -040011592 }
11593 $cflist tag configure highlight \
11594 -background [$cflist cget -selectbackground]
11595 allcanvs itemconf secsel -fill $c
11596}
11597
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011598# This sets the background color and the color scheme for the whole UI.
11599# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11600# if we don't specify one ourselves, which makes the checkbuttons and
11601# radiobuttons look bad. This chooses white for selectColor if the
11602# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011603proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011604 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011605 set bg [winfo rgb . $c]
11606 set selc black
11607 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
11608 set selc white
11609 }
11610 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011611}
11612
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011613proc setbg {c} {
11614 global bglist
11615
11616 foreach w $bglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011617 if {[winfo exists $w]} {
11618 $w conf -background $c
11619 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011620 }
11621}
11622
11623proc setfg {c} {
11624 global fglist canv
11625
11626 foreach w $fglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011627 if {[winfo exists $w]} {
11628 $w conf -foreground $c
11629 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011630 }
11631 allcanvs itemconf text -fill $c
11632 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011633 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011634}
11635
Paul Mackerras712fcc02005-11-30 09:28:16 +110011636proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011637 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011638
Paul Mackerras3de07112007-10-23 22:40:50 +100011639 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011640 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras94503912007-10-23 10:33:38 +100011641 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110011642 set $v $oldprefs($v)
11643 }
11644 catch {destroy $prefstop}
11645 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011646 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011647}
11648
11649proc prefsok {} {
11650 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011651 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011652 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011653 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011654 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011655
11656 catch {destroy $prefstop}
11657 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011658 fontcan
11659 set fontchanged 0
11660 if {$mainfont ne $fontpref(mainfont)} {
11661 set mainfont $fontpref(mainfont)
11662 parsefont mainfont $mainfont
11663 eval font configure mainfont [fontflags mainfont]
11664 eval font configure mainfontbold [fontflags mainfont 1]
11665 setcoords
11666 set fontchanged 1
11667 }
11668 if {$textfont ne $fontpref(textfont)} {
11669 set textfont $fontpref(textfont)
11670 parsefont textfont $textfont
11671 eval font configure textfont [fontflags textfont]
11672 eval font configure textfontbold [fontflags textfont 1]
11673 }
11674 if {$uifont ne $fontpref(uifont)} {
11675 set uifont $fontpref(uifont)
11676 parsefont uifont $uifont
11677 eval font configure uifont [fontflags uifont]
11678 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011679 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011680 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
11681 if {$showlocalchanges} {
11682 doshowlocalchanges
11683 } else {
11684 dohidelocalchanges
11685 }
11686 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011687 if {$limitdiffs != $oldprefs(limitdiffs) ||
11688 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11689 # treediffs elements are limited by path;
11690 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras009409f2015-05-02 20:53:36 +100011691 unset -nocomplain treediffs
Paul Mackerras74a40c72007-10-24 10:16:56 +100011692 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011693 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011694 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11695 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011696 } elseif {$showneartags != $oldprefs(showneartags) ||
11697 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011698 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011699 }
Thomas Rastffe15292009-08-03 23:53:36 +020011700 if {$hideremotes != $oldprefs(hideremotes)} {
11701 rereadrefs
11702 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011703}
11704
11705proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011706 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011707 if {$d ne {}} {
Anders Kaseorg019e1632014-05-12 07:25:58 -040011708 # If $datetimeformat includes a timezone, display in the
11709 # timezone of the argument. Otherwise, display in local time.
11710 if {[string match {*%[zZ]*} $datetimeformat]} {
11711 if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
11712 # Tcl < 8.5 does not support -timezone. Emulate it by
11713 # setting TZ (e.g. TZ=<-0430>+04:30).
11714 global env
11715 if {[info exists env(TZ)]} {
11716 set savedTZ $env(TZ)
11717 }
11718 set zone [lindex $d 1]
11719 set sign [string map {+ - - +} [string index $zone 0]]
11720 set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
11721 set d [clock format [lindex $d 0] -format $datetimeformat]
11722 if {[info exists savedTZ]} {
11723 set env(TZ) $savedTZ
11724 } else {
11725 unset env(TZ)
11726 }
11727 }
11728 } else {
11729 set d [clock format [lindex $d 0] -format $datetimeformat]
11730 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011731 }
11732 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011733}
11734
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011735# This list of encoding names and aliases is distilled from
11736# http://www.iana.org/assignments/character-sets.
11737# Not all of them are supported by Tcl.
11738set encoding_aliases {
11739 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11740 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11741 { ISO-10646-UTF-1 csISO10646UTF1 }
11742 { ISO_646.basic:1983 ref csISO646basic1983 }
11743 { INVARIANT csINVARIANT }
11744 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11745 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11746 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11747 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11748 { NATS-DANO iso-ir-9-1 csNATSDANO }
11749 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11750 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11751 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11752 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11753 { ISO-2022-KR csISO2022KR }
11754 { EUC-KR csEUCKR }
11755 { ISO-2022-JP csISO2022JP }
11756 { ISO-2022-JP-2 csISO2022JP2 }
11757 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11758 csISO13JISC6220jp }
11759 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11760 { IT iso-ir-15 ISO646-IT csISO15Italian }
11761 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11762 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11763 { greek7-old iso-ir-18 csISO18Greek7Old }
11764 { latin-greek iso-ir-19 csISO19LatinGreek }
11765 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11766 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11767 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11768 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11769 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11770 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11771 { INIS iso-ir-49 csISO49INIS }
11772 { INIS-8 iso-ir-50 csISO50INIS8 }
11773 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11774 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11775 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11776 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
11777 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
11778 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
11779 csISO60Norwegian1 }
11780 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
11781 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
11782 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
11783 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
11784 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
11785 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
11786 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
11787 { greek7 iso-ir-88 csISO88Greek7 }
11788 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
11789 { iso-ir-90 csISO90 }
11790 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
11791 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
11792 csISO92JISC62991984b }
11793 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
11794 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
11795 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
11796 csISO95JIS62291984handadd }
11797 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
11798 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
11799 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
11800 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
11801 CP819 csISOLatin1 }
11802 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
11803 { T.61-7bit iso-ir-102 csISO102T617bit }
11804 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
11805 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
11806 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
11807 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
11808 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
11809 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
11810 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
11811 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
11812 arabic csISOLatinArabic }
11813 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
11814 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
11815 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
11816 greek greek8 csISOLatinGreek }
11817 { T.101-G2 iso-ir-128 csISO128T101G2 }
11818 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
11819 csISOLatinHebrew }
11820 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
11821 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
11822 { CSN_369103 iso-ir-139 csISO139CSN369103 }
11823 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
11824 { ISO_6937-2-add iso-ir-142 csISOTextComm }
11825 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
11826 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
11827 csISOLatinCyrillic }
11828 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
11829 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
11830 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
11831 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
11832 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
11833 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
11834 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
11835 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
11836 { ISO_10367-box iso-ir-155 csISO10367Box }
11837 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
11838 { latin-lap lap iso-ir-158 csISO158Lap }
11839 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
11840 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
11841 { us-dk csUSDK }
11842 { dk-us csDKUS }
11843 { JIS_X0201 X0201 csHalfWidthKatakana }
11844 { KSC5636 ISO646-KR csKSC5636 }
11845 { ISO-10646-UCS-2 csUnicode }
11846 { ISO-10646-UCS-4 csUCS4 }
11847 { DEC-MCS dec csDECMCS }
11848 { hp-roman8 roman8 r8 csHPRoman8 }
11849 { macintosh mac csMacintosh }
11850 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
11851 csIBM037 }
11852 { IBM038 EBCDIC-INT cp038 csIBM038 }
11853 { IBM273 CP273 csIBM273 }
11854 { IBM274 EBCDIC-BE CP274 csIBM274 }
11855 { IBM275 EBCDIC-BR cp275 csIBM275 }
11856 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
11857 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
11858 { IBM280 CP280 ebcdic-cp-it csIBM280 }
11859 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
11860 { IBM284 CP284 ebcdic-cp-es csIBM284 }
11861 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
11862 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
11863 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
11864 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
11865 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
11866 { IBM424 cp424 ebcdic-cp-he csIBM424 }
11867 { IBM437 cp437 437 csPC8CodePage437 }
11868 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
11869 { IBM775 cp775 csPC775Baltic }
11870 { IBM850 cp850 850 csPC850Multilingual }
11871 { IBM851 cp851 851 csIBM851 }
11872 { IBM852 cp852 852 csPCp852 }
11873 { IBM855 cp855 855 csIBM855 }
11874 { IBM857 cp857 857 csIBM857 }
11875 { IBM860 cp860 860 csIBM860 }
11876 { IBM861 cp861 861 cp-is csIBM861 }
11877 { IBM862 cp862 862 csPC862LatinHebrew }
11878 { IBM863 cp863 863 csIBM863 }
11879 { IBM864 cp864 csIBM864 }
11880 { IBM865 cp865 865 csIBM865 }
11881 { IBM866 cp866 866 csIBM866 }
11882 { IBM868 CP868 cp-ar csIBM868 }
11883 { IBM869 cp869 869 cp-gr csIBM869 }
11884 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
11885 { IBM871 CP871 ebcdic-cp-is csIBM871 }
11886 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
11887 { IBM891 cp891 csIBM891 }
11888 { IBM903 cp903 csIBM903 }
11889 { IBM904 cp904 904 csIBBM904 }
11890 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
11891 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
11892 { IBM1026 CP1026 csIBM1026 }
11893 { EBCDIC-AT-DE csIBMEBCDICATDE }
11894 { EBCDIC-AT-DE-A csEBCDICATDEA }
11895 { EBCDIC-CA-FR csEBCDICCAFR }
11896 { EBCDIC-DK-NO csEBCDICDKNO }
11897 { EBCDIC-DK-NO-A csEBCDICDKNOA }
11898 { EBCDIC-FI-SE csEBCDICFISE }
11899 { EBCDIC-FI-SE-A csEBCDICFISEA }
11900 { EBCDIC-FR csEBCDICFR }
11901 { EBCDIC-IT csEBCDICIT }
11902 { EBCDIC-PT csEBCDICPT }
11903 { EBCDIC-ES csEBCDICES }
11904 { EBCDIC-ES-A csEBCDICESA }
11905 { EBCDIC-ES-S csEBCDICESS }
11906 { EBCDIC-UK csEBCDICUK }
11907 { EBCDIC-US csEBCDICUS }
11908 { UNKNOWN-8BIT csUnknown8BiT }
11909 { MNEMONIC csMnemonic }
11910 { MNEM csMnem }
11911 { VISCII csVISCII }
11912 { VIQR csVIQR }
11913 { KOI8-R csKOI8R }
11914 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
11915 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
11916 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
11917 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
11918 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
11919 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
11920 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
11921 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
11922 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
11923 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
11924 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
11925 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
11926 { IBM1047 IBM-1047 }
11927 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
11928 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
11929 { UNICODE-1-1 csUnicode11 }
11930 { CESU-8 csCESU-8 }
11931 { BOCU-1 csBOCU-1 }
11932 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
11933 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
11934 l8 }
11935 { ISO-8859-15 ISO_8859-15 Latin-9 }
11936 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
11937 { GBK CP936 MS936 windows-936 }
11938 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011939 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011940 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
11941 EUC-JP }
11942 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
11943 { ISO-10646-UCS-Basic csUnicodeASCII }
11944 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
11945 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
11946 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
11947 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
11948 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
11949 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
11950 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
11951 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
11952 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
11953 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
11954 { Adobe-Standard-Encoding csAdobeStandardEncoding }
11955 { Ventura-US csVenturaUS }
11956 { Ventura-International csVenturaInternational }
11957 { PC8-Danish-Norwegian csPC8DanishNorwegian }
11958 { PC8-Turkish csPC8Turkish }
11959 { IBM-Symbols csIBMSymbols }
11960 { IBM-Thai csIBMThai }
11961 { HP-Legal csHPLegal }
11962 { HP-Pi-font csHPPiFont }
11963 { HP-Math8 csHPMath8 }
11964 { Adobe-Symbol-Encoding csHPPSMath }
11965 { HP-DeskTop csHPDesktop }
11966 { Ventura-Math csVenturaMath }
11967 { Microsoft-Publishing csMicrosoftPublishing }
11968 { Windows-31J csWindows31J }
11969 { GB2312 csGB2312 }
11970 { Big5 csBig5 }
11971}
11972
11973proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011974 global encoding_aliases tcl_encoding_cache
11975 if {[info exists tcl_encoding_cache($enc)]} {
11976 return $tcl_encoding_cache($enc)
11977 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011978 set names [encoding names]
11979 set lcnames [string tolower $names]
11980 set enc [string tolower $enc]
11981 set i [lsearch -exact $lcnames $enc]
11982 if {$i < 0} {
11983 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011984 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011985 set i [lsearch -exact $lcnames $encx]
11986 }
11987 }
11988 if {$i < 0} {
11989 foreach l $encoding_aliases {
11990 set ll [string tolower $l]
11991 if {[lsearch -exact $ll $enc] < 0} continue
11992 # look through the aliases for one that tcl knows about
11993 foreach e $ll {
11994 set i [lsearch -exact $lcnames $e]
11995 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011996 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011997 set i [lsearch -exact $lcnames $ex]
11998 }
11999 }
12000 if {$i >= 0} break
12001 }
12002 break
12003 }
12004 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012005 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012006 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012007 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012008 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012009 set tcl_encoding_cache($enc) $tclenc
12010 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012011}
12012
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012013proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012014 global path_attr_cache
12015 if {[info exists path_attr_cache($attr,$path)]} {
12016 set r $path_attr_cache($attr,$path)
12017 } else {
12018 set r "unspecified"
12019 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020012020 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012021 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012022 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012023 }
12024 if {$r eq "unspecified"} {
12025 return $default
12026 }
12027 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012028}
12029
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012030proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012031 global path_attr_cache
12032 set newlist {}
12033 foreach path $pathlist {
12034 if {![info exists path_attr_cache($attr,$path)]} {
12035 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012036 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012037 }
12038 set lim 1000
12039 if {[tk windowingsystem] == "win32"} {
12040 # windows has a 32k limit on the arguments to a command...
12041 set lim 30
12042 }
12043 while {$newlist ne {}} {
12044 set head [lrange $newlist 0 [expr {$lim - 1}]]
12045 set newlist [lrange $newlist $lim end]
12046 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
12047 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020012048 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012049 if {[string index $path 0] eq "\""} {
12050 set path [encoding convertfrom [lindex $path 0]]
12051 }
12052 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012053 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012054 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012055 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012056 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012057}
12058
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012059proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012060 global gui_encoding perfile_attrs
12061 set tcl_enc $gui_encoding
12062 if {$path ne {} && $perfile_attrs} {
12063 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
12064 if {$enc2 ne {}} {
12065 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012066 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012067 }
12068 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012069}
12070
Alex Henrieef87a482015-05-11 13:26:41 -060012071## For msgcat loading, first locate the installation location.
12072if { [info exists ::env(GITK_MSGSDIR)] } {
12073 ## Msgsdir was manually set in the environment.
12074 set gitk_msgsdir $::env(GITK_MSGSDIR)
12075} else {
12076 ## Let's guess the prefix from argv0.
12077 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
12078 set gitk_libdir [file join $gitk_prefix share gitk lib]
12079 set gitk_msgsdir [file join $gitk_libdir msgs]
12080 unset gitk_prefix
12081}
12082
12083## Internationalization (i18n) through msgcat and gettext. See
12084## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
12085package require msgcat
12086namespace import ::msgcat::mc
12087## And eventually load the actual message catalog
12088::msgcat::mcload $gitk_msgsdir
12089
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012090# First check that Tcl/Tk is recent enough
12091if {[catch {package require Tk 8.4} err]} {
Alex Henrieef87a482015-05-11 13:26:41 -060012092 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
12093 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012094 exit 1
12095}
12096
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060012097# on OSX bring the current Wish process window to front
12098if {[tk windowingsystem] eq "aqua"} {
12099 exec osascript -e [format {
12100 tell application "System Events"
12101 set frontmost of processes whose unix id is %d to true
12102 end tell
12103 } [pid] ]
12104}
12105
Aske Olsson0ae10352012-05-10 12:13:43 +020012106# Unset GIT_TRACE var if set
12107if { [info exists ::env(GIT_TRACE)] } {
12108 unset ::env(GIT_TRACE)
12109}
12110
Paul Mackerras1d10f362005-05-15 12:55:47 +000012111# defaults...
Chris Packhame203d1d2014-11-02 21:37:50 +130012112set wrcomcmd "git diff-tree --stdin -p --pretty=email"
Junio C Hamano671bc152005-11-27 16:12:51 -080012113
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012114set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080012115catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110012116 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080012117}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030012118catch {
12119 set gitencoding [exec git config --get i18n.logoutputencoding]
12120}
Junio C Hamano671bc152005-11-27 16:12:51 -080012121if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012122 set gitencoding "utf-8"
12123}
12124set tclencoding [tcl_encoding $gitencoding]
12125if {$tclencoding == {}} {
12126 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080012127}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012128
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012129set gui_encoding [encoding system]
12130catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012131 set enc [exec git config --get gui.encoding]
12132 if {$enc ne {}} {
12133 set tclenc [tcl_encoding $enc]
12134 if {$tclenc ne {}} {
12135 set gui_encoding $tclenc
12136 } else {
12137 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
12138 }
12139 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012140}
12141
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020012142set log_showroot true
12143catch {
12144 set log_showroot [exec git config --bool --get log.showroot]
12145}
12146
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012147if {[tk windowingsystem] eq "aqua"} {
12148 set mainfont {{Lucida Grande} 9}
12149 set textfont {Monaco 9}
12150 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060012151} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
12152 # fontconfig!
12153 set mainfont {sans 9}
12154 set textfont {monospace 9}
12155 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012156} else {
12157 set mainfont {Helvetica 9}
12158 set textfont {Courier 9}
12159 set uifont {Helvetica 9 bold}
12160}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040012161set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040012162set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100012163set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100012164set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110012165set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110012166set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100012167set uparrowlen 5
12168set downarrowlen 5
12169set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100012170set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040012171set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100012172set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020012173set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100012174set maxrefs 20
Max Kirillovbde4a0f2014-06-24 08:19:44 +030012175set visiblerefs {"master"}
Paul Mackerras322a8cc2006-10-15 18:03:46 +100012176set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012177set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100012178set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020012179set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050012180set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110012181set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012182set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012183set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000012184
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012185if {[tk windowingsystem] eq "aqua"} {
12186 set extdifftool "opendiff"
12187} else {
12188 set extdifftool "meld"
12189}
Thomas Arcila314f5de2008-03-24 12:55:36 +010012190
YOKOTA Hiroshi66db14c2015-10-25 01:58:41 +090012191set colors {lime red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012192if {[tk windowingsystem] eq "win32"} {
12193 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012194 set uifgcolor SystemButtonText
12195 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012196 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012197 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012198 set selectbgcolor SystemHighlight
12199} else {
12200 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012201 set uifgcolor black
12202 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012203 set bgcolor white
12204 set fgcolor black
12205 set selectbgcolor gray85
12206}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100012207set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020012208set diffcontext 3
YOKOTA Hiroshi66db14c2015-10-25 01:58:41 +090012209set mergecolors {red blue lime purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010012210set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020012211set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110012212set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000012213
YOKOTA Hiroshi66db14c2015-10-25 01:58:41 +090012214set headbgcolor lime
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012215set headfgcolor black
12216set headoutlinecolor black
12217set remotebgcolor #ffddaa
12218set tagbgcolor yellow
12219set tagfgcolor black
12220set tagoutlinecolor black
12221set reflinecolor black
12222set filesepbgcolor #aaaaaa
12223set filesepfgcolor black
12224set linehoverbgcolor #ffff80
12225set linehoverfgcolor black
12226set linehoveroutlinecolor black
12227set mainheadcirclecolor yellow
12228set workingfilescirclecolor red
YOKOTA Hiroshi66db14c2015-10-25 01:58:41 +090012229set indexcirclecolor lime
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012230set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012231set linkfgcolor blue
12232set circleoutlinecolor $fgcolor
12233set foundbgcolor yellow
12234set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012235
Paul Mackerrasd277e892008-09-21 18:11:37 -050012236# button for popping up context menus
12237if {[tk windowingsystem] eq "aqua"} {
12238 set ctxbut <Button-2>
12239} else {
12240 set ctxbut <Button-3>
12241}
12242
Astril Hayato8f863392014-01-21 19:10:16 +000012243catch {
12244 # follow the XDG base directory specification by default. See
12245 # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
12246 if {[info exists env(XDG_CONFIG_HOME)] && $env(XDG_CONFIG_HOME) ne ""} {
12247 # XDG_CONFIG_HOME environment variable is set
12248 set config_file [file join $env(XDG_CONFIG_HOME) git gitk]
12249 set config_file_tmp [file join $env(XDG_CONFIG_HOME) git gitk-tmp]
12250 } else {
12251 # default XDG_CONFIG_HOME
12252 set config_file "~/.config/git/gitk"
12253 set config_file_tmp "~/.config/git/gitk-tmp"
12254 }
12255 if {![file exists $config_file]} {
12256 # for backward compatibility use the old config file if it exists
12257 if {[file exists "~/.gitk"]} {
12258 set config_file "~/.gitk"
12259 set config_file_tmp "~/.gitk-tmp"
12260 } elseif {![file exists [file dirname $config_file]]} {
12261 file mkdir [file dirname $config_file]
12262 }
12263 }
12264 source $config_file
12265}
Max Kirilloveaf7e832015-03-04 05:58:18 +020012266config_check_tmp_exists 50
Paul Mackerras1d10f362005-05-15 12:55:47 +000012267
Max Kirillov9fabefb2014-09-14 23:35:57 +030012268set config_variables {
12269 mainfont textfont uifont tabstop findmergefiles maxgraphpct maxwidth
12270 cmitmode wrapcomment autoselect autosellen showneartags maxrefs visiblerefs
12271 hideremotes showlocalchanges datetimeformat limitdiffs uicolor want_ttk
12272 bgcolor fgcolor uifgcolor uifgdisabledcolor colors diffcolors mergecolors
12273 markbgcolor diffcontext selectbgcolor foundbgcolor currentsearchhitbgcolor
12274 extdifftool perfile_attrs headbgcolor headfgcolor headoutlinecolor
12275 remotebgcolor tagbgcolor tagfgcolor tagoutlinecolor reflinecolor
12276 filesepbgcolor filesepfgcolor linehoverbgcolor linehoverfgcolor
12277 linehoveroutlinecolor mainheadcirclecolor workingfilescirclecolor
12278 indexcirclecolor circlecolors linkfgcolor circleoutlinecolor
12279}
Max Kirillov995f7922015-03-04 05:58:16 +020012280foreach var $config_variables {
12281 config_init_trace $var
12282 trace add variable $var write config_variable_change_cb
12283}
Max Kirillov9fabefb2014-09-14 23:35:57 +030012284
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100012285parsefont mainfont $mainfont
12286eval font create mainfont [fontflags mainfont]
12287eval font create mainfontbold [fontflags mainfont 1]
12288
12289parsefont textfont $textfont
12290eval font create textfont [fontflags textfont]
12291eval font create textfontbold [fontflags textfont 1]
12292
12293parsefont uifont $uifont
12294eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000012295
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110012296setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020012297
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110012298setoptions
12299
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012300# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040012301if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012302 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020012303 exit 1
12304}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012305
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012306set selecthead {}
12307set selectheadid {}
12308
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012309set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012310set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012311set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010012312set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012313foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010012314 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100012315 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012316 "--" {
12317 set cmdline_files [lrange $argv [expr {$i + 1}] end]
12318 break
12319 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012320 "--select-commit=*" {
12321 set selecthead [string range $arg 16 end]
12322 }
Yann Dirson2d480852008-02-21 21:23:31 +010012323 "--argscmd=*" {
12324 set revtreeargscmd [string range $arg 10 end]
12325 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012326 default {
12327 lappend revtreeargs $arg
12328 }
12329 }
12330 incr i
12331}
12332
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012333if {$selecthead eq "HEAD"} {
12334 set selecthead {}
12335}
12336
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012337if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012338 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012339 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030012340 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012341 set cmdline_files [split $f "\n"]
12342 set n [llength $cmdline_files]
12343 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012344 # Unfortunately git rev-parse doesn't produce an error when
12345 # something is both a revision and a filename. To be consistent
12346 # with git log and git rev-list, check revtreeargs for filenames.
12347 foreach arg $revtreeargs {
12348 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012349 show_error {} . [mc "Ambiguous argument '%s': both revision\
12350 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012351 exit 1
12352 }
12353 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012354 } err]} {
12355 # unfortunately we get both stdout and stderr in $err,
12356 # so look for "fatal:".
12357 set i [string first "fatal:" $err]
12358 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070012359 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012360 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010012361 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012362 exit 1
12363 }
12364}
12365
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012366set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012367set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012368set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012369
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012370set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012371if {![info exists have_ttk]} {
12372 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012373}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012374set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012375set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012376
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +010012377if {$use_ttk} {
12378 setttkstyle
12379}
12380
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012381regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012382
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012383set show_notes {}
12384if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12385 set show_notes "--show-notes"
12386}
12387
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012388set appname "gitk"
12389
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012390set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012391set history {}
12392set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012393set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012394set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012395set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012396set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012397set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012398set boldids {}
12399set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012400set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012401set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012402set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012403set need_redisplay 0
12404set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012405set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012406
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012407set nextviewnum 1
12408set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012409set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012410set selectedhlview [mc "None"]
12411set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012412set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012413set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012414set viewperm(0) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012415set viewchanged(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012416set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012417set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012418
Paul Mackerras94b4a692008-05-20 20:51:06 +100012419set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012420set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012421set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012422set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012423set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012424set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012425set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012426set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012427set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012428set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012429if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012430 set cdup [exec git rev-parse --show-cdup]
12431}
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -040012432set worktree [exec git rev-parse --show-toplevel]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012433setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012434makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012435catch {
12436 image create photo gitlogo -width 16 -height 16
12437
12438 image create photo gitlogominus -width 4 -height 2
12439 gitlogominus put #C00000 -to 0 0 4 2
12440 gitlogo copy gitlogominus -to 1 5
12441 gitlogo copy gitlogominus -to 6 5
12442 gitlogo copy gitlogominus -to 11 5
12443 image delete gitlogominus
12444
12445 image create photo gitlogoplus -width 4 -height 4
12446 gitlogoplus put #008000 -to 1 0 3 4
12447 gitlogoplus put #008000 -to 0 1 4 3
12448 gitlogo copy gitlogoplus -to 1 9
12449 gitlogo copy gitlogoplus -to 6 9
12450 gitlogo copy gitlogoplus -to 11 9
12451 image delete gitlogoplus
12452
Stephen Boydd38d7d42009-03-19 01:54:18 -070012453 image create photo gitlogo32 -width 32 -height 32
12454 gitlogo32 copy gitlogo -zoom 2 2
12455
12456 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012457}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012458# wait for the window to become visible
12459tkwait visibility .
Marc Branchaud9922c5a2015-04-07 11:51:51 -040012460set_window_title
Pat Thoyts478afad2009-04-15 17:14:03 +010012461update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012462readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012463
Yann Dirson2d480852008-02-21 21:23:31 +010012464if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012465 # create a view for the files/dirs specified on the command line
12466 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012467 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012468 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012469 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012470 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012471 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012472 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012473 set viewperm(1) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012474 set viewchanged(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012475 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012476 addviewmenu 1
Beat Bolli28de5682015-09-30 21:50:11 +020012477 .bar.view entryconf [mca "&Edit view..."] -state normal
12478 .bar.view entryconf [mca "&Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012479}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012480
12481if {[info exists permviews]} {
12482 foreach v $permviews {
12483 set n $nextviewnum
12484 incr nextviewnum
12485 set viewname($n) [lindex $v 0]
12486 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012487 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010012488 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012489 set viewperm($n) 1
Max Kirillov995f7922015-03-04 05:58:16 +020012490 set viewchanged($n) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012491 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012492 }
12493}
Johannes Sixte4df5192008-12-18 08:30:49 +010012494
12495if {[tk windowingsystem] eq "win32"} {
12496 focus -force .
12497}
12498
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012499getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012500
12501# Local variables:
12502# mode: tcl
12503# indent-tabs-mode: t
12504# tab-width: 8
12505# End: