blob: df3ba2ea99b310c3cdcd5c7a8938eef498b3e92e [file] [log] [blame]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
Paul Mackerras9e026d32005-09-27 10:29:41 +10003exec wish "$0" -- "$@"
Paul Mackerras1db95b02005-05-09 04:08:39 +00004
Paul Mackerrasfbf42642016-12-12 20:46:42 +11005# Copyright © 2005-2016 Paul Mackerras. All rights reserved.
Paul Mackerras1db95b02005-05-09 04:08:39 +00006# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
Pat Thoytsd93f1712009-04-17 01:24:35 +010010package require Tk
11
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012proc hasworktree {} {
13 return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
Denton Liue2445882020-09-10 21:36:33 -070014 [exec git rev-parse --is-inside-git-dir] == "false"}]
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040015}
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]} {
Denton Liue2445882020-09-10 21:36:33 -070021 set n [string range $n 0 end-5]
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010022 }
23 return [file tail $n]
24}
25
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000026proc gitworktree {} {
27 variable _gitworktree
28 if {[info exists _gitworktree]} {
Denton Liue2445882020-09-10 21:36:33 -070029 return $_gitworktree
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000030 }
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) }]} {
Denton Liue2445882020-09-10 21:36:33 -070037 if {[catch {set _gitworktree [exec git config --get core.worktree]}]} {
38 set _gitworktree [file normalize ./[exec git rev-parse --show-cdup]]
39 }
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000040 }
41 }
42 return $_gitworktree
43}
44
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100045# A simple scheduler for compute-intensive stuff.
46# The aim is to make sure that event handlers for GUI actions can
47# run at least every 50-100 ms. Unfortunately fileevent handlers are
48# run before X event handlers, so reading from a fast source can
49# make the GUI completely unresponsive.
50proc run args {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040051 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100052
53 set script $args
54 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040055 if {$runq eq {} && ![info exists currunq]} {
Denton Liue2445882020-09-10 21:36:33 -070056 after idle dorunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100057 }
58 lappend runq [list {} $script]
59 set isonrunq($script) 1
60}
61
62proc filerun {fd script} {
63 fileevent $fd readable [list filereadable $fd $script]
64}
65
66proc filereadable {fd script} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040067 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100068
69 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040070 if {$runq eq {} && ![info exists currunq]} {
Denton Liue2445882020-09-10 21:36:33 -070071 after idle dorunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 }
73 lappend runq [list $fd $script]
74}
75
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110076proc nukefile {fd} {
77 global runq
78
79 for {set i 0} {$i < [llength $runq]} {} {
Denton Liue2445882020-09-10 21:36:33 -070080 if {[lindex $runq $i 0] eq $fd} {
81 set runq [lreplace $runq $i $i]
82 } else {
83 incr i
84 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110085 }
86}
87
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100088proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040089 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100090
91 set tstart [clock clicks -milliseconds]
92 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110093 while {[llength $runq] > 0} {
Denton Liue2445882020-09-10 21:36:33 -070094 set fd [lindex $runq 0 0]
95 set script [lindex $runq 0 1]
96 set currunq [lindex $runq 0]
97 set runq [lrange $runq 1 end]
98 set repeat [eval $script]
99 unset currunq
100 set t1 [clock clicks -milliseconds]
101 set t [expr {$t1 - $t0}]
102 if {$repeat ne {} && $repeat} {
103 if {$fd eq {} || $repeat == 2} {
104 # script returns 1 if it wants to be readded
105 # file readers return 2 if they could do more straight away
106 lappend runq [list $fd $script]
107 } else {
108 fileevent $fd readable [list filereadable $fd $script]
109 }
110 } elseif {$fd eq {}} {
111 unset isonrunq($script)
112 }
113 set t0 $t1
114 if {$t1 - $tstart >= 80} break
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000115 }
116 if {$runq ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700117 after idle dorunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000118 }
119}
120
Alexander Gavrilove439e092008-07-13 16:40:47 +0400121proc reg_instance {fd} {
122 global commfd leftover loginstance
123
124 set i [incr loginstance]
125 set commfd($i) $fd
126 set leftover($i) {}
127 return $i
128}
129
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000130proc unmerged_files {files} {
131 global nr_unmerged
132
133 # find the list of unmerged files
134 set mlist {}
135 set nr_unmerged 0
136 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -0700137 set fd [open "| git ls-files -u" r]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000138 } err]} {
Denton Liue2445882020-09-10 21:36:33 -0700139 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
140 exit 1
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000141 }
142 while {[gets $fd line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -0700143 set i [string first "\t" $line]
144 if {$i < 0} continue
145 set fname [string range $line [expr {$i+1}] end]
146 if {[lsearch -exact $mlist $fname] >= 0} continue
147 incr nr_unmerged
148 if {$files eq {} || [path_filter $files $fname]} {
149 lappend mlist $fname
150 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000151 }
152 catch {close $fd}
153 return $mlist
154}
155
156proc parseviewargs {n arglist} {
Christian Couderc2f2dab2009-12-12 05:52:39 +0100157 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
Thomas Rast9403bd02013-11-16 18:37:43 +0100158 global vinlinediff
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200159 global worddiff git_version
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000160
161 set vdatemode($n) 0
162 set vmergeonly($n) 0
Thomas Rast9403bd02013-11-16 18:37:43 +0100163 set vinlinediff($n) 0
Paul Mackerrasee66e082008-05-09 10:14:07 +1000164 set glflags {}
165 set diffargs {}
166 set nextisval 0
167 set revargs {}
168 set origargs $arglist
169 set allknown 1
170 set filtered 0
171 set i -1
172 foreach arg $arglist {
Denton Liue2445882020-09-10 21:36:33 -0700173 incr i
174 if {$nextisval} {
175 lappend glflags $arg
176 set nextisval 0
177 continue
178 }
179 switch -glob -- $arg {
180 "-d" -
181 "--date-order" {
182 set vdatemode($n) 1
183 # remove from origargs in case we hit an unknown option
184 set origargs [lreplace $origargs $i $i]
185 incr i -1
186 }
187 "-[puabwcrRBMC]" -
188 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
189 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
190 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
191 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
192 "--ignore-space-change" - "-U*" - "--unified=*" {
193 # These request or affect diff output, which we don't want.
194 # Some could be used to set our defaults for diff display.
195 lappend diffargs $arg
196 }
197 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
198 "--name-only" - "--name-status" - "--color" -
199 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
200 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
201 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
202 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
203 "--objects" - "--objects-edge" - "--reverse" {
204 # These cause our parsing of git log's output to fail, or else
205 # they're options we want to set ourselves, so ignore them.
206 }
207 "--color-words*" - "--word-diff=color" {
208 # These trigger a word diff in the console interface,
209 # so help the user by enabling our own support
210 if {[package vcompare $git_version "1.7.2"] >= 0} {
211 set worddiff [mc "Color words"]
212 }
213 }
214 "--word-diff*" {
215 if {[package vcompare $git_version "1.7.2"] >= 0} {
216 set worddiff [mc "Markup words"]
217 }
218 }
219 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
220 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
221 "--full-history" - "--dense" - "--sparse" -
222 "--follow" - "--left-right" - "--encoding=*" {
223 # These are harmless, and some are even useful
224 lappend glflags $arg
225 }
226 "--diff-filter=*" - "--no-merges" - "--unpacked" -
227 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
228 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
229 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
230 "--remove-empty" - "--first-parent" - "--cherry-pick" -
231 "-S*" - "-G*" - "--pickaxe-all" - "--pickaxe-regex" -
232 "--simplify-by-decoration" {
233 # These mean that we get a subset of the commits
234 set filtered 1
235 lappend glflags $arg
236 }
237 "-L*" {
238 # Line-log with 'stuck' argument (unstuck form is
239 # not supported)
240 set filtered 1
241 set vinlinediff($n) 1
242 set allknown 0
243 lappend glflags $arg
244 }
245 "-n" {
246 # This appears to be the only one that has a value as a
247 # separate word following it
248 set filtered 1
249 set nextisval 1
250 lappend glflags $arg
251 }
252 "--not" - "--all" {
253 lappend revargs $arg
254 }
255 "--merge" {
256 set vmergeonly($n) 1
257 # git rev-parse doesn't understand --merge
258 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
259 }
260 "--no-replace-objects" {
261 set env(GIT_NO_REPLACE_OBJECTS) "1"
262 }
263 "-*" {
264 # Other flag arguments including -<n>
265 if {[string is digit -strict [string range $arg 1 end]]} {
266 set filtered 1
267 } else {
268 # a flag argument that we don't recognize;
269 # that means we can't optimize
270 set allknown 0
271 }
272 lappend glflags $arg
273 }
274 default {
275 # Non-flag arguments specify commits or ranges of commits
276 if {[string match "*...*" $arg]} {
277 lappend revargs --gitk-symmetric-diff-marker
278 }
279 lappend revargs $arg
280 }
281 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000282 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000283 set vdflags($n) $diffargs
284 set vflags($n) $glflags
285 set vrevs($n) $revargs
286 set vfiltered($n) $filtered
287 set vorigargs($n) $origargs
288 return $allknown
289}
290
291proc parseviewrevs {view revs} {
292 global vposids vnegids
293
294 if {$revs eq {}} {
Denton Liue2445882020-09-10 21:36:33 -0700295 set revs HEAD
Max Kirillov4d5e1b12014-09-09 10:29:16 +0300296 } elseif {[lsearch -exact $revs --all] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -0700297 lappend revs HEAD
Paul Mackerrasee66e082008-05-09 10:14:07 +1000298 }
299 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
Denton Liue2445882020-09-10 21:36:33 -0700300 # we get stdout followed by stderr in $err
301 # for an unknown rev, git rev-parse echoes it and then errors out
302 set errlines [split $err "\n"]
303 set badrev {}
304 for {set l 0} {$l < [llength $errlines]} {incr l} {
305 set line [lindex $errlines $l]
306 if {!([string length $line] == 40 && [string is xdigit $line])} {
307 if {[string match "fatal:*" $line]} {
308 if {[string match "fatal: ambiguous argument*" $line]
309 && $badrev ne {}} {
310 if {[llength $badrev] == 1} {
311 set err "unknown revision $badrev"
312 } else {
313 set err "unknown revisions: [join $badrev ", "]"
314 }
315 } else {
316 set err [join [lrange $errlines $l end] "\n"]
317 }
318 break
319 }
320 lappend badrev $line
321 }
322 }
323 error_popup "[mc "Error parsing revisions:"] $err"
324 return {}
Paul Mackerrasee66e082008-05-09 10:14:07 +1000325 }
326 set ret {}
327 set pos {}
328 set neg {}
329 set sdm 0
330 foreach id [split $ids "\n"] {
Denton Liue2445882020-09-10 21:36:33 -0700331 if {$id eq "--gitk-symmetric-diff-marker"} {
332 set sdm 4
333 } elseif {[string match "^*" $id]} {
334 if {$sdm != 1} {
335 lappend ret $id
336 if {$sdm == 3} {
337 set sdm 0
338 }
339 }
340 lappend neg [string range $id 1 end]
341 } else {
342 if {$sdm != 2} {
343 lappend ret $id
344 } else {
345 lset ret end $id...[lindex $ret end]
346 }
347 lappend pos $id
348 }
349 incr sdm -1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000350 }
351 set vposids($view) $pos
352 set vnegids($view) $neg
353 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000354}
355
Nico Rieck7dd272e2023-01-24 11:23:17 +0000356# Escapes a list of filter paths to be passed to git log via stdin. Note that
357# paths must not be quoted.
358proc escape_filter_paths {paths} {
359 set escaped [list]
360 foreach path $paths {
361 lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path]
362 }
363 return $escaped
364}
365
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100366# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000367proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000368 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400369 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000370 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100371 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400372 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100373 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000374 global vcanopt vflags vrevs vorigargs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400375 global show_notes
Paul Mackerras38ad0912005-12-01 22:42:46 +1100376
377 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000378 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000379 # these are set this way for the error exits
380 set viewcomplete($view) 1
381 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100382 varcinit $view
383
Yann Dirson2d480852008-02-21 21:23:31 +0100384 set args $viewargs($view)
385 if {$viewargscmd($view) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700386 if {[catch {
387 set str [exec sh -c $viewargscmd($view)]
388 } err]} {
389 error_popup "[mc "Error executing --argscmd command:"] $err"
390 return 0
391 }
392 set args [concat $args [split $str "\n"]]
Yann Dirson2d480852008-02-21 21:23:31 +0100393 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000394 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000395
396 set files $viewfiles($view)
397 if {$vmergeonly($view)} {
Denton Liue2445882020-09-10 21:36:33 -0700398 set files [unmerged_files $files]
399 if {$files eq {}} {
400 global nr_unmerged
401 if {$nr_unmerged == 0} {
402 error_popup [mc "No files selected: --merge specified but\
403 no files are unmerged."]
404 } else {
405 error_popup [mc "No files selected: --merge specified but\
406 no unmerged files are within file limit."]
407 }
408 return 0
409 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000410 }
411 set vfilelimit($view) $files
412
Paul Mackerrasee66e082008-05-09 10:14:07 +1000413 if {$vcanopt($view)} {
Denton Liue2445882020-09-10 21:36:33 -0700414 set revs [parseviewrevs $view $vrevs($view)]
415 if {$revs eq {}} {
416 return 0
417 }
Johannes Schindelinbb5cb232023-01-24 11:23:16 +0000418 set args $vflags($view)
Paul Mackerrasee66e082008-05-09 10:14:07 +1000419 } else {
Johannes Schindelinbb5cb232023-01-24 11:23:16 +0000420 set revs {}
Denton Liue2445882020-09-10 21:36:33 -0700421 set args $vorigargs($view)
Paul Mackerrasee66e082008-05-09 10:14:07 +1000422 }
423
Paul Mackerras418c4c72006-02-07 09:10:18 +1100424 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -0700425 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
Johannes Schindelinbb5cb232023-01-24 11:23:16 +0000426 --parents --boundary $args --stdin \
Nico Rieck7dd272e2023-01-24 11:23:17 +0000427 "<<[join [concat $revs "--" \
428 [escape_filter_paths $files]] "\\n"]"] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100429 } err]} {
Denton Liue2445882020-09-10 21:36:33 -0700430 error_popup "[mc "Error executing git log:"] $err"
431 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100432 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400433 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100434 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100435 set viewmainheadid($view) $mainheadid
436 set viewmainheadid_orig($view) $mainheadid
437 if {$files ne {} && $mainheadid ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700438 get_viewmainhead $view
Paul Mackerrascdc84292008-11-18 19:54:14 +1100439 }
440 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700441 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000442 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400443 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100444 if {$tclencoding != {}} {
Denton Liue2445882020-09-10 21:36:33 -0700445 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100446 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100447 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100448 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000449 set viewcomplete($view) 0
450 set viewactive($view) 1
451 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100452}
453
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400454proc stop_instance {inst} {
455 global commfd leftover
456
457 set fd $commfd($inst)
458 catch {
Denton Liue2445882020-09-10 21:36:33 -0700459 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400460
Denton Liue2445882020-09-10 21:36:33 -0700461 if {$::tcl_platform(platform) eq {windows}} {
462 exec taskkill /pid $pid
463 } else {
464 exec kill $pid
465 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400466 }
467 catch {close $fd}
468 nukefile $fd
469 unset commfd($inst)
470 unset leftover($inst)
471}
472
473proc stop_backends {} {
474 global commfd
475
476 foreach inst [array names commfd] {
Denton Liue2445882020-09-10 21:36:33 -0700477 stop_instance $inst
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400478 }
479}
480
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100481proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400482 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000483
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100484 foreach inst $viewinstances($view) {
Denton Liue2445882020-09-10 21:36:33 -0700485 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000486 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100487 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000488}
489
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400490proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400491 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400492
493 if {$selid ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700494 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400495 } elseif {$selectheadid ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700496 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400497 } else {
Denton Liue2445882020-09-10 21:36:33 -0700498 set pending_select $mainheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400499 }
500}
501
502proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000503 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100504
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000505 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000506 if {[start_rev_list $curview]} {
Denton Liue2445882020-09-10 21:36:33 -0700507 reset_pending_select $selid
508 show_status [mc "Reading commits..."]
509 set need_redisplay 1
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000510 } else {
Denton Liue2445882020-09-10 21:36:33 -0700511 show_status [mc "No commits selected"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000512 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000513}
514
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100515proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000516 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400517 global viewactive viewcomplete tclencoding
518 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100519 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400520 global hasworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000521 global varcid vposids vnegids vflags vrevs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400522 global show_notes
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100523
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400524 set hasworktree [hasworktree]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100525 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100526 set view $curview
527 if {$mainheadid ne $viewmainheadid_orig($view)} {
Denton Liue2445882020-09-10 21:36:33 -0700528 if {$showlocalchanges} {
529 dohidelocalchanges
530 }
531 set viewmainheadid($view) $mainheadid
532 set viewmainheadid_orig($view) $mainheadid
533 if {$vfilelimit($view) ne {}} {
534 get_viewmainhead $view
535 }
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100536 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100537 if {$showlocalchanges} {
Denton Liue2445882020-09-10 21:36:33 -0700538 doshowlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100539 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000540 if {$vcanopt($view)} {
Denton Liue2445882020-09-10 21:36:33 -0700541 set oldpos $vposids($view)
542 set oldneg $vnegids($view)
543 set revs [parseviewrevs $view $vrevs($view)]
544 if {$revs eq {}} {
545 return
546 }
547 # note: getting the delta when negative refs change is hard,
548 # and could require multiple git log invocations, so in that
549 # case we ask git log for all the commits (not just the delta)
550 if {$oldneg eq $vnegids($view)} {
551 set newrevs {}
552 set npos 0
553 # take out positive refs that we asked for before or
554 # that we have already seen
555 foreach rev $revs {
556 if {[string length $rev] == 40} {
557 if {[lsearch -exact $oldpos $rev] < 0
558 && ![info exists varcid($view,$rev)]} {
559 lappend newrevs $rev
560 incr npos
561 }
562 } else {
563 lappend $newrevs $rev
564 }
565 }
566 if {$npos == 0} return
567 set revs $newrevs
568 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
569 }
Johannes Schindelinbb5cb232023-01-24 11:23:16 +0000570 set args $vflags($view)
571 foreach r $oldpos {
572 lappend revs "^$r"
573 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000574 } else {
Johannes Schindelinbb5cb232023-01-24 11:23:16 +0000575 set revs {}
Denton Liue2445882020-09-10 21:36:33 -0700576 set args $vorigargs($view)
Paul Mackerrasee66e082008-05-09 10:14:07 +1000577 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100578 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -0700579 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
Johannes Schindelinbb5cb232023-01-24 11:23:16 +0000580 --parents --boundary $args --stdin \
581 "<<[join [concat $revs "--" \
Nico Rieck7dd272e2023-01-24 11:23:17 +0000582 [escape_filter_paths \
583 $vfilelimit($view)]] "\\n"]"] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100584 } err]} {
Denton Liue2445882020-09-10 21:36:33 -0700585 error_popup "[mc "Error executing git log:"] $err"
586 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100587 }
588 if {$viewactive($view) == 0} {
Denton Liue2445882020-09-10 21:36:33 -0700589 set startmsecs [clock clicks -milliseconds]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100590 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400591 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100592 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100593 fconfigure $fd -blocking 0 -translation lf -eofchar {}
594 if {$tclencoding != {}} {
Denton Liue2445882020-09-10 21:36:33 -0700595 fconfigure $fd -encoding $tclencoding
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100596 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100597 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100598 incr viewactive($view)
599 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400600 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200601 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100602 if {$showneartags} {
Denton Liue2445882020-09-10 21:36:33 -0700603 getallcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100604 }
605}
606
607proc reloadcommits {} {
608 global curview viewcomplete selectedline currentid thickerline
609 global showneartags treediffs commitinterest cached_commitrow
Markus Hitter18ae9122016-11-07 19:02:51 +0100610 global targetid commitinfo
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100611
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400612 set selid {}
613 if {$selectedline ne {}} {
Denton Liue2445882020-09-10 21:36:33 -0700614 set selid $currentid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400615 }
616
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100617 if {!$viewcomplete($curview)} {
Denton Liue2445882020-09-10 21:36:33 -0700618 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100619 }
620 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000621 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +1000622 unset -nocomplain currentid
623 unset -nocomplain thickerline
624 unset -nocomplain treediffs
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100625 readrefs
626 changedrefs
627 if {$showneartags} {
Denton Liue2445882020-09-10 21:36:33 -0700628 getallcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100629 }
630 clear_display
Markus Hitter18ae9122016-11-07 19:02:51 +0100631 unset -nocomplain commitinfo
Paul Mackerras009409f2015-05-02 20:53:36 +1000632 unset -nocomplain commitinterest
633 unset -nocomplain cached_commitrow
634 unset -nocomplain targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100635 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400636 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100637 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100638}
639
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000640# This makes a string representation of a positive integer which
641# sorts as a string in numerical order
642proc strrep {n} {
643 if {$n < 16} {
Denton Liue2445882020-09-10 21:36:33 -0700644 return [format "%x" $n]
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000645 } elseif {$n < 256} {
Denton Liue2445882020-09-10 21:36:33 -0700646 return [format "x%.2x" $n]
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000647 } elseif {$n < 65536} {
Denton Liue2445882020-09-10 21:36:33 -0700648 return [format "y%.4x" $n]
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000649 }
650 return [format "z%.8x" $n]
651}
652
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100653# Procedures used in reordering commits from git log (without
654# --topo-order) into the order for display.
655
656proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100657 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
658 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100659
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100660 set varcstart($view) {{}}
661 set vupptr($view) {0}
662 set vdownptr($view) {0}
663 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100664 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100665 set varctok($view) {{}}
666 set varcrow($view) {{}}
667 set vtokmod($view) {}
668 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100669 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100670 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100671 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100672}
673
674proc resetvarcs {view} {
675 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100676 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100677
678 foreach vid [array names varcid $view,*] {
Denton Liue2445882020-09-10 21:36:33 -0700679 unset varcid($vid)
680 unset children($vid)
681 unset parents($vid)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100682 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100683 foreach vid [array names vshortids $view,*] {
Denton Liue2445882020-09-10 21:36:33 -0700684 unset vshortids($vid)
Paul Mackerras22387f22012-03-19 11:21:08 +1100685 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100686 # some commits might have children but haven't been seen yet
687 foreach vid [array names children $view,*] {
Denton Liue2445882020-09-10 21:36:33 -0700688 unset children($vid)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100689 }
690 foreach va [array names varccommits $view,*] {
Denton Liue2445882020-09-10 21:36:33 -0700691 unset varccommits($va)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100692 }
693 foreach vd [array names vseedcount $view,*] {
Denton Liue2445882020-09-10 21:36:33 -0700694 unset vseedcount($vd)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100695 }
Paul Mackerras009409f2015-05-02 20:53:36 +1000696 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100697}
698
Paul Mackerras468bcae2008-03-03 10:19:35 +1100699# returns a list of the commits with no children
700proc seeds {v} {
701 global vdownptr vleftptr varcstart
702
703 set ret {}
704 set a [lindex $vdownptr($v) 0]
705 while {$a != 0} {
Denton Liue2445882020-09-10 21:36:33 -0700706 lappend ret [lindex $varcstart($v) $a]
707 set a [lindex $vleftptr($v) $a]
Paul Mackerras468bcae2008-03-03 10:19:35 +1100708 }
709 return $ret
710}
711
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100712proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000713 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100714 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
715 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100716
717 set a [llength $varctok($view)]
718 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000719 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Denton Liue2445882020-09-10 21:36:33 -0700720 if {![info exists commitinfo($id)]} {
721 parsecommit $id $commitdata($id) 1
722 }
723 set cdate [lindex [lindex $commitinfo($id) 4] 0]
724 if {![string is integer -strict $cdate]} {
725 set cdate 0
726 }
727 if {![info exists vseedcount($view,$cdate)]} {
728 set vseedcount($view,$cdate) -1
729 }
730 set c [incr vseedcount($view,$cdate)]
731 set cdate [expr {$cdate ^ 0xffffffff}]
732 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100733 } else {
Denton Liue2445882020-09-10 21:36:33 -0700734 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100735 }
736 set ka 0
737 if {[llength $children($vid)] > 0} {
Denton Liue2445882020-09-10 21:36:33 -0700738 set kid [lindex $children($vid) end]
739 set k $varcid($view,$kid)
740 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
741 set ki $kid
742 set ka $k
743 set tok [lindex $varctok($view) $k]
744 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100745 }
746 if {$ka != 0} {
Denton Liue2445882020-09-10 21:36:33 -0700747 set i [lsearch -exact $parents($view,$ki) $id]
748 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
749 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100750 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100751 set c [lindex $vlastins($view) $ka]
752 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
Denton Liue2445882020-09-10 21:36:33 -0700753 set c $ka
754 set b [lindex $vdownptr($view) $ka]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100755 } else {
Denton Liue2445882020-09-10 21:36:33 -0700756 set b [lindex $vleftptr($view) $c]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100757 }
758 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -0700759 set c $b
760 set b [lindex $vleftptr($view) $c]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100761 }
762 if {$c == $ka} {
Denton Liue2445882020-09-10 21:36:33 -0700763 lset vdownptr($view) $ka $a
764 lappend vbackptr($view) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100765 } else {
Denton Liue2445882020-09-10 21:36:33 -0700766 lset vleftptr($view) $c $a
767 lappend vbackptr($view) $c
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100768 }
769 lset vlastins($view) $ka $a
770 lappend vupptr($view) $ka
771 lappend vleftptr($view) $b
772 if {$b != 0} {
Denton Liue2445882020-09-10 21:36:33 -0700773 lset vbackptr($view) $b $a
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100774 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100775 lappend varctok($view) $tok
776 lappend varcstart($view) $id
777 lappend vdownptr($view) 0
778 lappend varcrow($view) {}
779 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100780 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100781 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100782 return $a
783}
784
785proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100786 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100787 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100788
789 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100790 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100791 set ac $varccommits($v,$oa)
792 set i [lsearch -exact $varccommits($v,$oa) $p]
793 if {$i <= 0} return
794 set na [llength $varctok($v)]
795 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100796 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100797 lappend varctok($v) $tok
798 lappend varcrow($v) {}
799 lappend varcix($v) {}
800 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
801 set varccommits($v,$na) [lrange $ac $i end]
802 lappend varcstart($v) $p
803 foreach id $varccommits($v,$na) {
Denton Liue2445882020-09-10 21:36:33 -0700804 set varcid($v,$id) $na
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100805 }
806 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100807 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100808 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100809 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100810 lappend vupptr($v) $oa
811 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100812 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100813 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
Denton Liue2445882020-09-10 21:36:33 -0700814 lset vupptr($v) $b $na
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100815 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100816 if {[string compare $otok $vtokmod($v)] <= 0} {
Denton Liue2445882020-09-10 21:36:33 -0700817 modify_arc $v $oa
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100818 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100819}
820
821proc renumbervarc {a v} {
822 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000823 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100824
825 set t1 [clock clicks -milliseconds]
826 set todo {}
827 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100828 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100829 set ntot 0
830 while {$a != 0} {
Denton Liue2445882020-09-10 21:36:33 -0700831 if {[info exists isrelated($a)]} {
832 lappend todo $a
833 set id [lindex $varccommits($v,$a) end]
834 foreach p $parents($v,$id) {
835 if {[info exists varcid($v,$p)]} {
836 set isrelated($varcid($v,$p)) 1
837 }
838 }
839 }
840 incr ntot
841 set b [lindex $vdownptr($v) $a]
842 if {$b == 0} {
843 while {$a != 0} {
844 set b [lindex $vleftptr($v) $a]
845 if {$b != 0} break
846 set a [lindex $vupptr($v) $a]
847 }
848 }
849 set a $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100850 }
851 foreach a $todo {
Denton Liue2445882020-09-10 21:36:33 -0700852 if {![info exists kidchanged($a)]} continue
853 set id [lindex $varcstart($v) $a]
854 if {[llength $children($v,$id)] > 1} {
855 set children($v,$id) [lsort -command [list vtokcmp $v] \
856 $children($v,$id)]
857 }
858 set oldtok [lindex $varctok($v) $a]
859 if {!$vdatemode($v)} {
860 set tok {}
861 } else {
862 set tok $oldtok
863 }
864 set ka 0
865 set kid [last_real_child $v,$id]
866 if {$kid ne {}} {
867 set k $varcid($v,$kid)
868 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
869 set ki $kid
870 set ka $k
871 set tok [lindex $varctok($v) $k]
872 }
873 }
874 if {$ka != 0} {
875 set i [lsearch -exact $parents($v,$ki) $id]
876 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
877 append tok [strrep $j]
878 }
879 if {$tok eq $oldtok} {
880 continue
881 }
882 set id [lindex $varccommits($v,$a) end]
883 foreach p $parents($v,$id) {
884 if {[info exists varcid($v,$p)]} {
885 set kidchanged($varcid($v,$p)) 1
886 } else {
887 set sortkids($p) 1
888 }
889 }
890 lset varctok($v) $a $tok
891 set b [lindex $vupptr($v) $a]
892 if {$b != $ka} {
893 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
894 modify_arc $v $ka
895 }
896 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
897 modify_arc $v $b
898 }
899 set c [lindex $vbackptr($v) $a]
900 set d [lindex $vleftptr($v) $a]
901 if {$c == 0} {
902 lset vdownptr($v) $b $d
903 } else {
904 lset vleftptr($v) $c $d
905 }
906 if {$d != 0} {
907 lset vbackptr($v) $d $c
908 }
909 if {[lindex $vlastins($v) $b] == $a} {
910 lset vlastins($v) $b $c
911 }
912 lset vupptr($v) $a $ka
913 set c [lindex $vlastins($v) $ka]
914 if {$c == 0 || \
915 [string compare $tok [lindex $varctok($v) $c]] < 0} {
916 set c $ka
917 set b [lindex $vdownptr($v) $ka]
918 } else {
919 set b [lindex $vleftptr($v) $c]
920 }
921 while {$b != 0 && \
922 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
923 set c $b
924 set b [lindex $vleftptr($v) $c]
925 }
926 if {$c == $ka} {
927 lset vdownptr($v) $ka $a
928 lset vbackptr($v) $a 0
929 } else {
930 lset vleftptr($v) $c $a
931 lset vbackptr($v) $a $c
932 }
933 lset vleftptr($v) $a $b
934 if {$b != 0} {
935 lset vbackptr($v) $b $a
936 }
937 lset vlastins($v) $ka $a
938 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100939 }
940 foreach id [array names sortkids] {
Denton Liue2445882020-09-10 21:36:33 -0700941 if {[llength $children($v,$id)] > 1} {
942 set children($v,$id) [lsort -command [list vtokcmp $v] \
943 $children($v,$id)]
944 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100945 }
946 set t2 [clock clicks -milliseconds]
947 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
948}
949
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100950# Fix up the graph after we have found out that in view $v,
951# $p (a commit that we have already seen) is actually the parent
952# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100953proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100954 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100955
956 set pa $varcid($v,$p)
957 if {$p ne [lindex $varcstart($v) $pa]} {
Denton Liue2445882020-09-10 21:36:33 -0700958 splitvarc $p $v
959 set pa $varcid($v,$p)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100960 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100961 # seeds always need to be renumbered
962 if {[lindex $vupptr($v) $pa] == 0 ||
Denton Liue2445882020-09-10 21:36:33 -0700963 [string compare [lindex $varctok($v) $a] \
964 [lindex $varctok($v) $pa]] > 0} {
965 renumbervarc $pa $v
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100966 }
967}
968
969proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100970 global cmitlisted children parents varcid varctok vtokmod
971 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100972 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100973
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100974 readcommit $id
975 set vid $v,$id
976 set cmitlisted($vid) 1
977 set children($vid) {}
978 set parents($vid) [list $p]
979 set a [newvarc $v $id]
980 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100981 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100982 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
Denton Liue2445882020-09-10 21:36:33 -0700983 modify_arc $v $a
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100984 }
985 lappend varccommits($v,$a) $id
986 set vp $v,$p
987 if {[llength [lappend children($vp) $id]] > 1} {
Denton Liue2445882020-09-10 21:36:33 -0700988 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
989 unset -nocomplain ordertok
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100990 }
991 fix_reversal $p $a $v
992 incr commitidx($v)
993 if {$v == $curview} {
Denton Liue2445882020-09-10 21:36:33 -0700994 set numcommits $commitidx($v)
995 setcanvscroll
996 if {[info exists targetid]} {
997 if {![comes_before $targetid $p]} {
998 incr targetrow
999 }
1000 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001001 }
1002}
1003
1004proc insertfakerow {id p} {
1005 global varcid varccommits parents children cmitlisted
1006 global commitidx varctok vtokmod targetid targetrow curview numcommits
1007
1008 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001009 set a $varcid($v,$p)
1010 set i [lsearch -exact $varccommits($v,$a) $p]
1011 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -07001012 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
1013 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001014 }
1015 set children($v,$id) {}
1016 set parents($v,$id) [list $p]
1017 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001018 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001019 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001020 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001021 # note we deliberately don't update varcstart($v) even if $i == 0
1022 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001023 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +11001024 if {[info exists targetid]} {
Denton Liue2445882020-09-10 21:36:33 -07001025 if {![comes_before $targetid $p]} {
1026 incr targetrow
1027 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001028 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001029 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001030 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001031}
1032
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001033proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001034 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001035 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001036 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001037
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001038 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001039 if {[llength $parents($v,$id)] != 1} {
Denton Liue2445882020-09-10 21:36:33 -07001040 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
1041 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001042 }
1043 set p [lindex $parents($v,$id) 0]
1044 set a $varcid($v,$id)
1045 set i [lsearch -exact $varccommits($v,$a) $id]
1046 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -07001047 puts "oops: removefakerow can't find [shortids $id] on arc $a"
1048 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001049 }
1050 unset varcid($v,$id)
1051 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1052 unset parents($v,$id)
1053 unset children($v,$id)
1054 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001055 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001056 set j [lsearch -exact $children($v,$p) $id]
1057 if {$j >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07001058 set children($v,$p) [lreplace $children($v,$p) $j $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001059 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001060 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001061 if {[info exist currentid] && $id eq $currentid} {
Denton Liue2445882020-09-10 21:36:33 -07001062 unset currentid
1063 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001064 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001065 if {[info exists targetid] && $targetid eq $id} {
Denton Liue2445882020-09-10 21:36:33 -07001066 set targetid $p
Paul Mackerras42a671f2008-01-02 09:59:39 +11001067 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001068 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001069 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001070}
1071
Paul Mackerrasaa435612009-09-10 21:58:40 +10001072proc real_children {vp} {
1073 global children nullid nullid2
1074
1075 set kids {}
1076 foreach id $children($vp) {
Denton Liue2445882020-09-10 21:36:33 -07001077 if {$id ne $nullid && $id ne $nullid2} {
1078 lappend kids $id
1079 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10001080 }
1081 return $kids
1082}
1083
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001084proc first_real_child {vp} {
1085 global children nullid nullid2
1086
1087 foreach id $children($vp) {
Denton Liue2445882020-09-10 21:36:33 -07001088 if {$id ne $nullid && $id ne $nullid2} {
1089 return $id
1090 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001091 }
1092 return {}
1093}
1094
1095proc last_real_child {vp} {
1096 global children nullid nullid2
1097
1098 set kids $children($vp)
1099 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
Denton Liue2445882020-09-10 21:36:33 -07001100 set id [lindex $kids $i]
1101 if {$id ne $nullid && $id ne $nullid2} {
1102 return $id
1103 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001104 }
1105 return {}
1106}
1107
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001108proc vtokcmp {v a b} {
1109 global varctok varcid
1110
1111 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
Denton Liue2445882020-09-10 21:36:33 -07001112 [lindex $varctok($v) $varcid($v,$b)]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001113}
1114
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001115# This assumes that if lim is not given, the caller has checked that
1116# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001117proc modify_arc {v a {lim {}}} {
1118 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001119
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001120 if {$lim ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07001121 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1122 if {$c > 0} return
1123 if {$c == 0} {
1124 set r [lindex $varcrow($v) $a]
1125 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1126 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001127 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001128 set vtokmod($v) [lindex $varctok($v) $a]
1129 set varcmod($v) $a
1130 if {$v == $curview} {
Denton Liue2445882020-09-10 21:36:33 -07001131 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1132 set a [lindex $vupptr($v) $a]
1133 set lim {}
1134 }
1135 set r 0
1136 if {$a != 0} {
1137 if {$lim eq {}} {
1138 set lim [llength $varccommits($v,$a)]
1139 }
1140 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1141 }
1142 set vrowmod($v) $r
1143 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001144 }
1145}
1146
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001147proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001148 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001149 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001150 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001151 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001152
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001153 if {$vrowmod($v) == $commitidx($v)} return
1154 if {$v == $curview} {
Denton Liue2445882020-09-10 21:36:33 -07001155 if {[llength $displayorder] > $vrowmod($v)} {
1156 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1157 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1158 }
1159 unset -nocomplain cached_commitrow
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001160 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001161 set narctot [expr {[llength $varctok($v)] - 1}]
1162 set a $varcmod($v)
1163 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07001164 # go up the tree until we find something that has a row number,
1165 # or we get to a seed
1166 set a [lindex $vupptr($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001167 }
1168 if {$a == 0} {
Denton Liue2445882020-09-10 21:36:33 -07001169 set a [lindex $vdownptr($v) 0]
1170 if {$a == 0} return
1171 set vrownum($v) {0}
1172 set varcorder($v) [list $a]
1173 lset varcix($v) $a 0
1174 lset varcrow($v) $a 0
1175 set arcn 0
1176 set row 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001177 } else {
Denton Liue2445882020-09-10 21:36:33 -07001178 set arcn [lindex $varcix($v) $a]
1179 if {[llength $vrownum($v)] > $arcn + 1} {
1180 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1181 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1182 }
1183 set row [lindex $varcrow($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001184 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001185 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07001186 set p $a
1187 incr row [llength $varccommits($v,$a)]
1188 # go down if possible
1189 set b [lindex $vdownptr($v) $a]
1190 if {$b == 0} {
1191 # if not, go left, or go up until we can go left
1192 while {$a != 0} {
1193 set b [lindex $vleftptr($v) $a]
1194 if {$b != 0} break
1195 set a [lindex $vupptr($v) $a]
1196 }
1197 if {$a == 0} break
1198 }
1199 set a $b
1200 incr arcn
1201 lappend vrownum($v) $row
1202 lappend varcorder($v) $a
1203 lset varcix($v) $a $arcn
1204 lset varcrow($v) $a $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001205 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001206 set vtokmod($v) [lindex $varctok($v) $p]
1207 set varcmod($v) $p
1208 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001209 if {[info exists currentid]} {
Denton Liue2445882020-09-10 21:36:33 -07001210 set selectedline [rowofcommit $currentid]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001211 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001212}
1213
1214# Test whether view $v contains commit $id
1215proc commitinview {id v} {
1216 global varcid
1217
1218 return [info exists varcid($v,$id)]
1219}
1220
1221# Return the row number for commit $id in the current view
1222proc rowofcommit {id} {
1223 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001224 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001225
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001226 set v $curview
1227 if {![info exists varcid($v,$id)]} {
Denton Liue2445882020-09-10 21:36:33 -07001228 puts "oops rowofcommit no arc for [shortids $id]"
1229 return {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001230 }
1231 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001232 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07001233 update_arcrows $v
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001234 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001235 if {[info exists cached_commitrow($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07001236 return $cached_commitrow($id)
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001237 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001238 set i [lsearch -exact $varccommits($v,$a) $id]
1239 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -07001240 puts "oops didn't find commit [shortids $id] in arc $a"
1241 return {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001242 }
1243 incr i [lindex $varcrow($v) $a]
1244 set cached_commitrow($id) $i
1245 return $i
1246}
1247
Paul Mackerras42a671f2008-01-02 09:59:39 +11001248# Returns 1 if a is on an earlier row than b, otherwise 0
1249proc comes_before {a b} {
1250 global varcid varctok curview
1251
1252 set v $curview
1253 if {$a eq $b || ![info exists varcid($v,$a)] || \
Denton Liue2445882020-09-10 21:36:33 -07001254 ![info exists varcid($v,$b)]} {
1255 return 0
Paul Mackerras42a671f2008-01-02 09:59:39 +11001256 }
1257 if {$varcid($v,$a) != $varcid($v,$b)} {
Denton Liue2445882020-09-10 21:36:33 -07001258 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1259 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
Paul Mackerras42a671f2008-01-02 09:59:39 +11001260 }
1261 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1262}
1263
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001264proc bsearch {l elt} {
1265 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
Denton Liue2445882020-09-10 21:36:33 -07001266 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001267 }
1268 set lo 0
1269 set hi [llength $l]
1270 while {$hi - $lo > 1} {
Denton Liue2445882020-09-10 21:36:33 -07001271 set mid [expr {int(($lo + $hi) / 2)}]
1272 set t [lindex $l $mid]
1273 if {$elt < $t} {
1274 set hi $mid
1275 } elseif {$elt > $t} {
1276 set lo $mid
1277 } else {
1278 return $mid
1279 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001280 }
1281 return $lo
1282}
1283
1284# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1285proc make_disporder {start end} {
1286 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001287 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001288 global d_valid_start d_valid_end
1289
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001290 if {$end > $vrowmod($curview)} {
Denton Liue2445882020-09-10 21:36:33 -07001291 update_arcrows $curview
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001292 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001293 set ai [bsearch $vrownum($curview) $start]
1294 set start [lindex $vrownum($curview) $ai]
1295 set narc [llength $vrownum($curview)]
1296 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
Denton Liue2445882020-09-10 21:36:33 -07001297 set a [lindex $varcorder($curview) $ai]
1298 set l [llength $displayorder]
1299 set al [llength $varccommits($curview,$a)]
1300 if {$l < $r + $al} {
1301 if {$l < $r} {
1302 set pad [ntimes [expr {$r - $l}] {}]
1303 set displayorder [concat $displayorder $pad]
1304 set parentlist [concat $parentlist $pad]
1305 } elseif {$l > $r} {
1306 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1307 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1308 }
1309 foreach id $varccommits($curview,$a) {
1310 lappend displayorder $id
1311 lappend parentlist $parents($curview,$id)
1312 }
1313 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
1314 set i $r
1315 foreach id $varccommits($curview,$a) {
1316 lset displayorder $i $id
1317 lset parentlist $i $parents($curview,$id)
1318 incr i
1319 }
1320 }
1321 incr r $al
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001322 }
1323}
1324
1325proc commitonrow {row} {
1326 global displayorder
1327
1328 set id [lindex $displayorder $row]
1329 if {$id eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07001330 make_disporder $row [expr {$row + 1}]
1331 set id [lindex $displayorder $row]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001332 }
1333 return $id
1334}
1335
1336proc closevarcs {v} {
1337 global varctok varccommits varcid parents children
Stefan Dotterweichd92aa572016-06-04 10:47:16 +02001338 global cmitlisted commitidx vtokmod curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001339
1340 set missing_parents 0
1341 set scripts {}
1342 set narcs [llength $varctok($v)]
1343 for {set a 1} {$a < $narcs} {incr a} {
Denton Liue2445882020-09-10 21:36:33 -07001344 set id [lindex $varccommits($v,$a) end]
1345 foreach p $parents($v,$id) {
1346 if {[info exists varcid($v,$p)]} continue
1347 # add p as a new commit
1348 incr missing_parents
1349 set cmitlisted($v,$p) 0
1350 set parents($v,$p) {}
1351 if {[llength $children($v,$p)] == 1 &&
1352 [llength $parents($v,$id)] == 1} {
1353 set b $a
1354 } else {
1355 set b [newvarc $v $p]
1356 }
1357 set varcid($v,$p) $b
1358 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1359 modify_arc $v $b
1360 }
1361 lappend varccommits($v,$b) $p
1362 incr commitidx($v)
1363 if {$v == $curview} {
1364 set numcommits $commitidx($v)
1365 }
1366 set scripts [check_interest $p $scripts]
1367 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001368 }
1369 if {$missing_parents > 0} {
Denton Liue2445882020-09-10 21:36:33 -07001370 foreach s $scripts {
1371 eval $s
1372 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001373 }
1374}
1375
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001376# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1377# Assumes we already have an arc for $rwid.
1378proc rewrite_commit {v id rwid} {
1379 global children parents varcid varctok vtokmod varccommits
1380
1381 foreach ch $children($v,$id) {
Denton Liue2445882020-09-10 21:36:33 -07001382 # make $rwid be $ch's parent in place of $id
1383 set i [lsearch -exact $parents($v,$ch) $id]
1384 if {$i < 0} {
1385 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1386 }
1387 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1388 # add $ch to $rwid's children and sort the list if necessary
1389 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1390 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1391 $children($v,$rwid)]
1392 }
1393 # fix the graph after joining $id to $rwid
1394 set a $varcid($v,$ch)
1395 fix_reversal $rwid $a $v
1396 # parentlist is wrong for the last element of arc $a
1397 # even if displayorder is right, hence the 3rd arg here
1398 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001399 }
1400}
1401
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001402# Mechanism for registering a command to be executed when we come
1403# across a particular commit. To handle the case when only the
1404# prefix of the commit is known, the commitinterest array is now
1405# indexed by the first 4 characters of the ID. Each element is a
1406# list of id, cmd pairs.
1407proc interestedin {id cmd} {
1408 global commitinterest
1409
1410 lappend commitinterest([string range $id 0 3]) $id $cmd
1411}
1412
1413proc check_interest {id scripts} {
1414 global commitinterest
1415
1416 set prefix [string range $id 0 3]
1417 if {[info exists commitinterest($prefix)]} {
Denton Liue2445882020-09-10 21:36:33 -07001418 set newlist {}
1419 foreach {i script} $commitinterest($prefix) {
1420 if {[string match "$i*" $id]} {
1421 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1422 } else {
1423 lappend newlist $i $script
1424 }
1425 }
1426 if {$newlist ne {}} {
1427 set commitinterest($prefix) $newlist
1428 } else {
1429 unset commitinterest($prefix)
1430 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001431 }
1432 return $scripts
1433}
1434
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001435proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001436 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001437 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001438 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001439 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001440 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001441
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001442 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001443 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001444 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Denton Liue2445882020-09-10 21:36:33 -07001445 set stuff "\0"
Paul Mackerras005a2f42007-07-26 22:36:39 +10001446 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001447 if {$stuff == {}} {
Denton Liue2445882020-09-10 21:36:33 -07001448 if {![eof $fd]} {
1449 return 1
1450 }
1451 global commfd viewcomplete viewactive viewname
1452 global viewinstances
1453 unset commfd($inst)
1454 set i [lsearch -exact $viewinstances($view) $inst]
1455 if {$i >= 0} {
1456 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
1457 }
1458 # set it blocking so we wait for the process to terminate
1459 fconfigure $fd -blocking 1
1460 if {[catch {close $fd} err]} {
1461 set fv {}
1462 if {$view != $curview} {
1463 set fv " for the \"$viewname($view)\" view"
1464 }
1465 if {[string range $err 0 4] == "usage"} {
1466 set err "Gitk: error reading commits$fv:\
1467 bad arguments to git log."
1468 if {$viewname($view) eq [mc "Command line"]} {
1469 append err \
1470 " (Note: arguments to gitk are passed to git log\
1471 to allow selection of commits to be displayed.)"
1472 }
1473 } else {
1474 set err "Error reading commits$fv: $err"
1475 }
1476 error_popup $err
1477 }
1478 if {[incr viewactive($view) -1] <= 0} {
1479 set viewcomplete($view) 1
1480 # Check if we have seen any ids listed as parents that haven't
1481 # appeared in the list
1482 closevarcs $view
1483 notbusy $view
1484 }
1485 if {$view == $curview} {
1486 run chewcommits
1487 }
1488 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001489 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001490 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001491 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001492 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001493 while 1 {
Denton Liue2445882020-09-10 21:36:33 -07001494 set i [string first "\0" $stuff $start]
1495 if {$i < 0} {
1496 append leftover($inst) [string range $stuff $start end]
1497 break
1498 }
1499 if {$start == 0} {
1500 set cmit $leftover($inst)
1501 append cmit [string range $stuff 0 [expr {$i - 1}]]
1502 set leftover($inst) {}
1503 } else {
1504 set cmit [string range $stuff $start [expr {$i - 1}]]
1505 }
1506 set start [expr {$i + 1}]
1507 set j [string first "\n" $cmit]
1508 set ok 0
1509 set listed 1
1510 if {$j >= 0 && [string match "commit *" $cmit]} {
1511 set ids [string range $cmit 7 [expr {$j - 1}]]
1512 if {[string match {[-^<>]*} $ids]} {
1513 switch -- [string index $ids 0] {
1514 "-" {set listed 0}
1515 "^" {set listed 2}
1516 "<" {set listed 3}
1517 ">" {set listed 4}
1518 }
1519 set ids [string range $ids 1 end]
1520 }
1521 set ok 1
1522 foreach id $ids {
1523 if {[string length $id] != 40} {
1524 set ok 0
1525 break
1526 }
1527 }
1528 }
1529 if {!$ok} {
1530 set shortcmit $cmit
1531 if {[string length $shortcmit] > 80} {
1532 set shortcmit "[string range $shortcmit 0 80]..."
1533 }
1534 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
1535 exit 1
1536 }
1537 set id [lindex $ids 0]
1538 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001539
Denton Liue2445882020-09-10 21:36:33 -07001540 lappend vshortids($view,[string range $id 0 3]) $id
Paul Mackerras22387f22012-03-19 11:21:08 +11001541
Denton Liue2445882020-09-10 21:36:33 -07001542 if {!$listed && $updating && ![info exists varcid($vid)] &&
1543 $vfilelimit($view) ne {}} {
1544 # git log doesn't rewrite parents for unlisted commits
1545 # when doing path limiting, so work around that here
1546 # by working out the rewritten parent with git rev-list
1547 # and if we already know about it, using the rewritten
1548 # parent as a substitute parent for $id's children.
1549 if {![catch {
1550 set rwid [exec git rev-list --first-parent --max-count=1 \
1551 $id -- $vfilelimit($view)]
1552 }]} {
1553 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1554 # use $rwid in place of $id
1555 rewrite_commit $view $id $rwid
1556 continue
1557 }
1558 }
1559 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001560
Denton Liue2445882020-09-10 21:36:33 -07001561 set a 0
1562 if {[info exists varcid($vid)]} {
1563 if {$cmitlisted($vid) || !$listed} continue
1564 set a $varcid($vid)
1565 }
1566 if {$listed} {
1567 set olds [lrange $ids 1 end]
1568 } else {
1569 set olds {}
1570 }
1571 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
1572 set cmitlisted($vid) $listed
1573 set parents($vid) $olds
1574 if {![info exists children($vid)]} {
1575 set children($vid) {}
1576 } elseif {$a == 0 && [llength $children($vid)] == 1} {
1577 set k [lindex $children($vid) 0]
1578 if {[llength $parents($view,$k)] == 1 &&
1579 (!$vdatemode($view) ||
1580 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1581 set a $varcid($view,$k)
1582 }
1583 }
1584 if {$a == 0} {
1585 # new arc
1586 set a [newvarc $view $id]
1587 }
1588 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1589 modify_arc $view $a
1590 }
1591 if {![info exists varcid($vid)]} {
1592 set varcid($vid) $a
1593 lappend varccommits($view,$a) $id
1594 incr commitidx($view)
1595 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001596
Denton Liue2445882020-09-10 21:36:33 -07001597 set i 0
1598 foreach p $olds {
1599 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1600 set vp $view,$p
1601 if {[llength [lappend children($vp) $id]] > 1 &&
1602 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1603 set children($vp) [lsort -command [list vtokcmp $view] \
1604 $children($vp)]
1605 unset -nocomplain ordertok
1606 }
1607 if {[info exists varcid($view,$p)]} {
1608 fix_reversal $p $a $view
1609 }
1610 }
1611 incr i
1612 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001613
Denton Liue2445882020-09-10 21:36:33 -07001614 set scripts [check_interest $id $scripts]
1615 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001616 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001617 if {$gotsome} {
Denton Liue2445882020-09-10 21:36:33 -07001618 global numcommits hlview
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001619
Denton Liue2445882020-09-10 21:36:33 -07001620 if {$view == $curview} {
1621 set numcommits $commitidx($view)
1622 run chewcommits
1623 }
1624 if {[info exists hlview] && $view == $hlview} {
1625 # we never actually get here...
1626 run vhighlightmore
1627 }
1628 foreach s $scripts {
1629 eval $s
1630 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001631 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001632 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001633}
1634
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001635proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001636 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001637 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001638
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001639 layoutmore
1640 if {$viewcomplete($curview)} {
Denton Liue2445882020-09-10 21:36:33 -07001641 global commitidx varctok
1642 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001643
Denton Liue2445882020-09-10 21:36:33 -07001644 if {[info exists pending_select]} {
1645 update
1646 reset_pending_select {}
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001647
Denton Liue2445882020-09-10 21:36:33 -07001648 if {[commitinview $pending_select $curview]} {
1649 selectline [rowofcommit $pending_select] 1
1650 } else {
1651 set row [first_real_row]
1652 selectline $row 1
1653 }
1654 }
1655 if {$commitidx($curview) > 0} {
1656 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1657 #puts "overall $ms ms for $numcommits commits"
1658 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1659 } else {
1660 show_status [mc "No commits selected"]
1661 }
1662 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001663 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001664 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001665}
1666
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001667proc do_readcommit {id} {
1668 global tclencoding
1669
1670 # Invoke git-log to handle automatic encoding conversion
1671 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1672 # Read the results using i18n.logoutputencoding
1673 fconfigure $fd -translation lf -eofchar {}
1674 if {$tclencoding != {}} {
Denton Liue2445882020-09-10 21:36:33 -07001675 fconfigure $fd -encoding $tclencoding
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001676 }
1677 set contents [read $fd]
1678 close $fd
1679 # Remove the heading line
1680 regsub {^commit [0-9a-f]+\n} $contents {} contents
1681
1682 return $contents
1683}
1684
Paul Mackerras1db95b02005-05-09 04:08:39 +00001685proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001686 if {[catch {set contents [do_readcommit $id]}]} return
1687 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001688}
1689
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001690proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001691 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001692
1693 set inhdr 1
1694 set comment {}
1695 set headline {}
1696 set auname {}
1697 set audate {}
1698 set comname {}
1699 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001700 set hdrend [string first "\n\n" $contents]
1701 if {$hdrend < 0} {
Denton Liue2445882020-09-10 21:36:33 -07001702 # should never happen...
1703 set hdrend [string length $contents]
Paul Mackerras232475d2005-11-15 10:34:03 +11001704 }
1705 set header [string range $contents 0 [expr {$hdrend - 1}]]
1706 set comment [string range $contents [expr {$hdrend + 2}] end]
1707 foreach line [split $header "\n"] {
Denton Liue2445882020-09-10 21:36:33 -07001708 set line [split $line " "]
1709 set tag [lindex $line 0]
1710 if {$tag == "author"} {
1711 set audate [lrange $line end-1 end]
1712 set auname [join [lrange $line 1 end-2] " "]
1713 } elseif {$tag == "committer"} {
1714 set comdate [lrange $line end-1 end]
1715 set comname [join [lrange $line 1 end-2] " "]
1716 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00001717 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001718 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001719 # take the first non-blank line of the comment as the headline
1720 set headline [string trimleft $comment]
1721 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001722 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07001723 set headline [string range $headline 0 $i]
Paul Mackerras43c25072006-09-27 10:56:02 +10001724 }
1725 set headline [string trimright $headline]
1726 set i [string first "\r" $headline]
1727 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07001728 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001729 }
1730 if {!$listed} {
Denton Liue2445882020-09-10 21:36:33 -07001731 # git log indents the comment by 4 spaces;
1732 # if we got this via git cat-file, add the indentation
1733 set newcomment {}
1734 foreach line [split $comment "\n"] {
1735 append newcomment " "
1736 append newcomment $line
1737 append newcomment "\n"
1738 }
1739 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001740 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001741 set hasnote [string first "\nNotes:\n" $contents]
Thomas Rastb449eb22013-11-16 18:37:42 +01001742 set diff ""
1743 # If there is diff output shown in the git-log stream, split it
1744 # out. But get rid of the empty line that always precedes the
1745 # diff.
1746 set i [string first "\n\ndiff" $comment]
1747 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07001748 set diff [string range $comment $i+1 end]
1749 set comment [string range $comment 0 $i-1]
Thomas Rastb449eb22013-11-16 18:37:42 +01001750 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001751 set commitinfo($id) [list $headline $auname $audate \
Denton Liue2445882020-09-10 21:36:33 -07001752 $comname $comdate $comment $hasnote $diff]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001753}
1754
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001755proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001756 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001757
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001758 if {[info exists commitdata($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07001759 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001760 } else {
Denton Liue2445882020-09-10 21:36:33 -07001761 readcommit $id
1762 if {![info exists commitinfo($id)]} {
1763 set commitinfo($id) [list [mc "No commit information available"]]
1764 }
Paul Mackerras8ed16482006-03-02 22:56:44 +11001765 }
1766 return 1
1767}
1768
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001769# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1770# and are present in the current view.
1771# This is fairly slow...
1772proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001773 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001774
1775 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001776 if {[string length $prefix] >= 4} {
Denton Liue2445882020-09-10 21:36:33 -07001777 set vshortid $curview,[string range $prefix 0 3]
1778 if {[info exists vshortids($vshortid)]} {
1779 foreach id $vshortids($vshortid) {
1780 if {[string match "$prefix*" $id]} {
1781 if {[lsearch -exact $ids $id] < 0} {
1782 lappend ids $id
1783 if {[llength $ids] >= 2} break
1784 }
1785 }
1786 }
1787 }
Paul Mackerras22387f22012-03-19 11:21:08 +11001788 } else {
Denton Liue2445882020-09-10 21:36:33 -07001789 foreach match [array names varcid "$curview,$prefix*"] {
1790 lappend ids [lindex [split $match ","] 1]
1791 if {[llength $ids] >= 2} break
1792 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001793 }
1794 return $ids
1795}
1796
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001797proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001798 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001799 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001800 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001801 global hideremotes
Kazuhiro Katod4247e02019-12-07 00:32:25 +00001802 global tclencoding
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001803
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001804 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
Denton Liue2445882020-09-10 21:36:33 -07001805 unset -nocomplain $v
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001806 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001807 set refd [open [list | git show-ref -d] r]
Kazuhiro Katod4247e02019-12-07 00:32:25 +00001808 if {$tclencoding != {}} {
Denton Liue2445882020-09-10 21:36:33 -07001809 fconfigure $refd -encoding $tclencoding
Kazuhiro Katod4247e02019-12-07 00:32:25 +00001810 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001811 while {[gets $refd line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07001812 if {[string index $line 40] ne " "} continue
1813 set id [string range $line 0 39]
1814 set ref [string range $line 41 end]
1815 if {![string match "refs/*" $ref]} continue
1816 set name [string range $ref 5 end]
1817 if {[string match "remotes/*" $name]} {
1818 if {![string match "*/HEAD" $name] && !$hideremotes} {
1819 set headids($name) $id
1820 lappend idheads($id) $name
1821 }
1822 } elseif {[string match "heads/*" $name]} {
1823 set name [string range $name 6 end]
1824 set headids($name) $id
1825 lappend idheads($id) $name
1826 } elseif {[string match "tags/*" $name]} {
1827 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1828 # which is what we want since the former is the commit ID
1829 set name [string range $name 5 end]
1830 if {[string match "*^{}" $name]} {
1831 set name [string range $name 0 end-3]
1832 } else {
1833 set tagobjid($name) $id
1834 }
1835 set tagids($name) $id
1836 lappend idtags($id) $name
1837 } else {
1838 set otherrefids($name) $id
1839 lappend idotherrefs($id) $name
1840 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001841 }
Alex Riesen062d6712007-07-29 22:28:40 +02001842 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001843 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001844 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001845 catch {
Denton Liue2445882020-09-10 21:36:33 -07001846 set mainheadid [exec git rev-parse HEAD]
1847 set thehead [exec git symbolic-ref HEAD]
1848 if {[string match "refs/heads/*" $thehead]} {
1849 set mainhead [string range $thehead 11 end]
1850 }
Paul Mackerras8a485712006-07-06 10:21:23 +10001851 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001852 set selectheadid {}
1853 if {$selecthead ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07001854 catch {
1855 set selectheadid [exec git rev-parse --verify $selecthead]
1856 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001857 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001858}
1859
Paul Mackerras8f489362007-07-13 19:49:37 +10001860# skip over fake commits
1861proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001862 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001863
1864 for {set row 0} {$row < $numcommits} {incr row} {
Denton Liue2445882020-09-10 21:36:33 -07001865 set id [commitonrow $row]
1866 if {$id ne $nullid && $id ne $nullid2} {
1867 break
1868 }
Paul Mackerras8f489362007-07-13 19:49:37 +10001869 }
1870 return $row
1871}
1872
Paul Mackerrase11f1232007-06-16 20:29:25 +10001873# update things for a head moved to a child of its previous location
1874proc movehead {id name} {
1875 global headids idheads
1876
1877 removehead $headids($name) $name
1878 set headids($name) $id
1879 lappend idheads($id) $name
1880}
1881
1882# update things when a head has been removed
1883proc removehead {id name} {
1884 global headids idheads
1885
1886 if {$idheads($id) eq $name} {
Denton Liue2445882020-09-10 21:36:33 -07001887 unset idheads($id)
Paul Mackerrase11f1232007-06-16 20:29:25 +10001888 } else {
Denton Liue2445882020-09-10 21:36:33 -07001889 set i [lsearch -exact $idheads($id) $name]
1890 if {$i >= 0} {
1891 set idheads($id) [lreplace $idheads($id) $i $i]
1892 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10001893 }
1894 unset headids($name)
1895}
1896
Pat Thoytsd93f1712009-04-17 01:24:35 +01001897proc ttk_toplevel {w args} {
1898 global use_ttk
1899 eval [linsert $args 0 ::toplevel $w]
1900 if {$use_ttk} {
1901 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1902 }
1903 return $w
1904}
1905
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001906proc make_transient {window origin} {
1907 global have_tk85
1908
1909 # In MacOS Tk 8.4 transient appears to work by setting
1910 # overrideredirect, which is utterly useless, since the
1911 # windows get no border, and are not even kept above
1912 # the parent.
1913 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1914
1915 wm transient $window $origin
1916
1917 # Windows fails to place transient windows normally, so
1918 # schedule a callback to center them on the parent.
1919 if {[tk windowingsystem] eq {win32}} {
Denton Liue2445882020-09-10 21:36:33 -07001920 after idle [list tk::PlaceWindow $window widget $origin]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001921 }
1922}
1923
Alex Henrieef87a482015-05-11 13:26:41 -06001924proc show_error {w top msg} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001925 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001926 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001927 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001928 message $w.m -text $msg -justify center -aspect 400
1929 pack $w.m -side top -fill x -padx 20 -pady 20
Alex Henrieef87a482015-05-11 13:26:41 -06001930 ${NS}::button $w.ok -default active -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001931 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001932 bind $top <Visibility> "grab $top; focus $top"
1933 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001934 bind $top <Key-space> "destroy $top"
1935 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001936 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001937}
1938
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001939proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001940 if {[tk windowingsystem] eq "win32"} {
1941 tk_messageBox -icon error -type ok -title [wm title .] \
1942 -parent $owner -message $msg
1943 } else {
1944 set w .error
1945 ttk_toplevel $w
1946 make_transient $w $owner
1947 show_error $w $w $msg
1948 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001949}
1950
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001951proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001952 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001953 set confirm_ok 0
1954 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001955 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001956 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001957 message $w.m -text $msg -justify center -aspect 400
1958 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001959 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001960 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001961 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001962 pack $w.cancel -side right -fill x
1963 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001964 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1965 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1966 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001967 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001968 tkwait window $w
1969 return $confirm_ok
1970}
1971
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001972proc setoptions {} {
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001973 global use_ttk
1974
Pat Thoytsd93f1712009-04-17 01:24:35 +01001975 if {[tk windowingsystem] ne "win32"} {
1976 option add *Panedwindow.showHandle 1 startupFile
1977 option add *Panedwindow.sashRelief raised startupFile
1978 if {[tk windowingsystem] ne "aqua"} {
1979 option add *Menu.font uifont startupFile
1980 }
1981 } else {
1982 option add *Menu.TearOff 0 startupFile
1983 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001984 option add *Button.font uifont startupFile
1985 option add *Checkbutton.font uifont startupFile
1986 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001987 option add *Menubutton.font uifont startupFile
1988 option add *Label.font uifont startupFile
1989 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001990 option add *Entry.font textfont startupFile
1991 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001992 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001993 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001994 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001995}
1996
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001997proc setttkstyle {} {
1998 eval font configure TkDefaultFont [fontflags mainfont]
1999 eval font configure TkTextFont [fontflags textfont]
2000 eval font configure TkHeadingFont [fontflags mainfont]
2001 eval font configure TkCaptionFont [fontflags mainfont] -weight bold
2002 eval font configure TkTooltipFont [fontflags uifont]
2003 eval font configure TkFixedFont [fontflags textfont]
2004 eval font configure TkIconFont [fontflags uifont]
2005 eval font configure TkMenuFont [fontflags uifont]
2006 eval font configure TkSmallCaptionFont [fontflags uifont]
2007}
2008
Paul Mackerras79056032008-10-18 16:24:46 +11002009# Make a menu and submenus.
2010# m is the window name for the menu, items is the list of menu items to add.
2011# Each item is a list {mc label type description options...}
2012# mc is ignored; it's so we can put mc there to alert xgettext
2013# label is the string that appears in the menu
2014# type is cascade, command or radiobutton (should add checkbutton)
2015# description depends on type; it's the sublist for cascade, the
2016# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002017proc makemenu {m items} {
2018 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002019 if {[tk windowingsystem] eq {aqua}} {
Denton Liue2445882020-09-10 21:36:33 -07002020 set Meta1 Cmd
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002021 } else {
Denton Liue2445882020-09-10 21:36:33 -07002022 set Meta1 Ctrl
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002023 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002024 foreach i $items {
Denton Liue2445882020-09-10 21:36:33 -07002025 set name [mc [lindex $i 1]]
2026 set type [lindex $i 2]
2027 set thing [lindex $i 3]
2028 set params [list $type]
2029 if {$name ne {}} {
2030 set u [string first "&" [string map {&& x} $name]]
2031 lappend params -label [string map {&& & & {}} $name]
2032 if {$u >= 0} {
2033 lappend params -underline $u
2034 }
2035 }
2036 switch -- $type {
2037 "cascade" {
2038 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
2039 lappend params -menu $m.$submenu
2040 }
2041 "command" {
2042 lappend params -command $thing
2043 }
2044 "radiobutton" {
2045 lappend params -variable [lindex $thing 0] \
2046 -value [lindex $thing 1]
2047 }
2048 }
2049 set tail [lrange $i 4 end]
2050 regsub -all {\yMeta1\y} $tail $Meta1 tail
2051 eval $m add $params $tail
2052 if {$type eq "cascade"} {
2053 makemenu $m.$submenu $thing
2054 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002055 }
2056}
2057
2058# translate string and remove ampersands
2059proc mca {str} {
2060 return [string map {&& & & {}} [mc $str]]
2061}
2062
Paul Mackerras39c12692013-05-11 17:08:41 +10002063proc cleardropsel {w} {
2064 $w selection clear
2065}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002066proc makedroplist {w varname args} {
2067 global use_ttk
2068 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002069 set width 0
2070 foreach label $args {
2071 set cx [string length $label]
2072 if {$cx > $width} {set width $cx}
2073 }
Denton Liue2445882020-09-10 21:36:33 -07002074 set gm [ttk::combobox $w -width $width -state readonly\
2075 -textvariable $varname -values $args \
2076 -exportselection false]
2077 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002078 } else {
Denton Liue2445882020-09-10 21:36:33 -07002079 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002080 }
2081 return $gm
2082}
2083
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002084proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002085 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002086 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002087 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002088 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002089 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002090 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002091 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002092 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002093 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002094 global searchstring sstring
Stefan Dotterweich113ce122020-02-11 22:24:48 +01002095 global bgcolor fgcolor bglist fglist diffcolors diffbgcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002096 global uifgcolor uifgdisabledcolor
2097 global filesepbgcolor filesepfgcolor
2098 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002099 global headctxmenu progresscanv progressitem progresscoords statusw
2100 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002101 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002102 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002103 global git_version
2104 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002105
Paul Mackerras79056032008-10-18 16:24:46 +11002106 # The "mc" arguments here are purely so that xgettext
2107 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002108 set file {
Denton Liue2445882020-09-10 21:36:33 -07002109 mc "&File" cascade {
2110 {mc "&Update" command updatecommits -accelerator F5}
2111 {mc "&Reload" command reloadcommits -accelerator Shift-F5}
2112 {mc "Reread re&ferences" command rereadrefs}
2113 {mc "&List references" command showrefs -accelerator F2}
2114 {xx "" separator}
2115 {mc "Start git &gui" command {exec git gui &}}
2116 {xx "" separator}
2117 {mc "&Quit" command doquit -accelerator Meta1-Q}
2118 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002119 set edit {
Denton Liue2445882020-09-10 21:36:33 -07002120 mc "&Edit" cascade {
2121 {mc "&Preferences" command doprefs}
2122 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002123 set view {
Denton Liue2445882020-09-10 21:36:33 -07002124 mc "&View" cascade {
2125 {mc "&New view..." command {newview 0} -accelerator Shift-F4}
2126 {mc "&Edit view..." command editview -state disabled -accelerator F4}
2127 {mc "&Delete view" command delview -state disabled}
2128 {xx "" separator}
2129 {mc "&All files" radiobutton {selectedview 0} -command {showview 0}}
2130 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002131 if {[tk windowingsystem] ne "aqua"} {
Denton Liue2445882020-09-10 21:36:33 -07002132 set help {
2133 mc "&Help" cascade {
2134 {mc "&About gitk" command about}
2135 {mc "&Key bindings" command keys}
2136 }}
2137 set bar [list $file $edit $view $help]
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002138 } else {
Denton Liue2445882020-09-10 21:36:33 -07002139 proc ::tk::mac::ShowPreferences {} {doprefs}
2140 proc ::tk::mac::Quit {} {doquit}
2141 lset file end [lreplace [lindex $file end] end-1 end]
2142 set apple {
2143 xx "&Apple" cascade {
2144 {mc "&About gitk" command about}
2145 {xx "" separator}
2146 }}
2147 set help {
2148 mc "&Help" cascade {
2149 {mc "&Key bindings" command keys}
2150 }}
2151 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002152 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002153 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002154 . configure -menu .bar
2155
Pat Thoytsd93f1712009-04-17 01:24:35 +01002156 if {$use_ttk} {
2157 # cover the non-themed toplevel with a themed frame.
2158 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2159 }
2160
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002161 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002162 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002163
2164 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002165 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002166 set geometry(topheight) [expr {15 * $linespc}]
2167 set geometry(topwidth) [expr {80 * $charspc}]
2168 set geometry(botheight) [expr {15 * $linespc}]
2169 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002170 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2171 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002172 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002173
2174 # 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 +01002175 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2176 ${NS}::frame .tf.histframe
2177 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2178 if {!$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002179 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
Pat Thoytsd93f1712009-04-17 01:24:35 +01002180 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002181
2182 # create three canvases
2183 set cscroll .tf.histframe.csb
2184 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002185 canvas $canv \
Denton Liue2445882020-09-10 21:36:33 -07002186 -selectbackground $selectbgcolor \
2187 -background $bgcolor -bd 0 \
2188 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002189 .tf.histframe.pwclist add $canv
2190 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002191 canvas $canv2 \
Denton Liue2445882020-09-10 21:36:33 -07002192 -selectbackground $selectbgcolor \
2193 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002194 .tf.histframe.pwclist add $canv2
2195 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002196 canvas $canv3 \
Denton Liue2445882020-09-10 21:36:33 -07002197 -selectbackground $selectbgcolor \
2198 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002199 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002200 if {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002201 bind .tf.histframe.pwclist <Map> {
2202 bind %W <Map> {}
2203 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2204 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2205 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002206 } else {
Denton Liue2445882020-09-10 21:36:33 -07002207 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2208 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Pat Thoytsd93f1712009-04-17 01:24:35 +01002209 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002210
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002211 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002212 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2213 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002214 pack $cscroll -side right -fill y
2215 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2216 lappend bglist $canv $canv2 $canv3
2217 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2218
2219 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002220 ${NS}::frame .tf.bar
2221 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002222
2223 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002224 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002225 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002226 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Denton Liue2445882020-09-10 21:36:33 -07002227 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002228 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002229 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002230 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002231 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002232 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002233
Stefan Hallerf062e502012-09-22 09:46:48 +02002234 set bm_left_data {
Denton Liue2445882020-09-10 21:36:33 -07002235 #define left_width 16
2236 #define left_height 16
2237 static unsigned char left_bits[] = {
2238 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2239 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2240 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
Paul Mackerrasd6982062005-08-06 22:06:06 +10002241 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002242 set bm_right_data {
Denton Liue2445882020-09-10 21:36:33 -07002243 #define right_width 16
2244 #define right_height 16
2245 static unsigned char right_bits[] = {
2246 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2247 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2248 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
Paul Mackerrasd6982062005-08-06 22:06:06 +10002249 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002250 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2251 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2252 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2253 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002254
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002255 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2256 if {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002257 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002258 } else {
Denton Liue2445882020-09-10 21:36:33 -07002259 .tf.bar.leftbut configure -image bm-left
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002260 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002261 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002262 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2263 if {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002264 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002265 } else {
Denton Liue2445882020-09-10 21:36:33 -07002266 .tf.bar.rightbut configure -image bm-right
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002267 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002268 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002269
Pat Thoytsd93f1712009-04-17 01:24:35 +01002270 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002271 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002272 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Denton Liue2445882020-09-10 21:36:33 -07002273 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002274 ${NS}::label .tf.bar.rowlabel2 -text "/"
2275 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Denton Liue2445882020-09-10 21:36:33 -07002276 -relief sunken -anchor e
Paul Mackerras6df74032008-05-11 22:13:02 +10002277 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
Denton Liue2445882020-09-10 21:36:33 -07002278 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002279 if {!$use_ttk} {
2280 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2281 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002282 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002283 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002284
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002285 # Status label and progress bar
2286 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002287 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002288 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002289 if {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002290 set progresscanv [ttk::progressbar .tf.bar.progress]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002291 } else {
Denton Liue2445882020-09-10 21:36:33 -07002292 set h [expr {[font metrics uifont -linespace] + 2}]
2293 set progresscanv .tf.bar.progress
2294 canvas $progresscanv -relief sunken -height $h -borderwidth 2
2295 set progressitem [$progresscanv create rect -1 0 0 $h -fill "#00ff00"]
2296 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2297 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002298 }
2299 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002300 set progresscoords {0 0}
2301 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002302 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002303 bind $progresscanv <Configure> adjustprogress
2304 set lastprogupdate [clock clicks -milliseconds]
2305 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002306
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002307 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002308 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002309
2310 set bm_down_data {
Denton Liue2445882020-09-10 21:36:33 -07002311 #define down_width 16
2312 #define down_height 16
2313 static unsigned char down_bits[] = {
2314 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2315 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2316 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
2317 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
Marc Branchaud786f15c2013-12-18 11:04:13 -05002318 }
2319 image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
2320 ${NS}::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
2321 .tf.lbar.fnext configure -image bm-down
2322
2323 set bm_up_data {
Denton Liue2445882020-09-10 21:36:33 -07002324 #define up_width 16
2325 #define up_height 16
2326 static unsigned char up_bits[] = {
2327 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
2328 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
2329 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2330 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
Marc Branchaud786f15c2013-12-18 11:04:13 -05002331 }
2332 image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
2333 ${NS}::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
2334 .tf.lbar.fprev configure -image bm-up
2335
Pat Thoytsd93f1712009-04-17 01:24:35 +01002336 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002337
Paul Mackerras687c8762007-09-22 12:49:33 +10002338 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
Denton Liue2445882020-09-10 21:36:33 -07002339 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002340 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002341 set gm [makedroplist .tf.lbar.gdttype gdttype \
Denton Liue2445882020-09-10 21:36:33 -07002342 [mc "containing:"] \
2343 [mc "touching paths:"] \
2344 [mc "adding/removing string:"] \
2345 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002346 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002347 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002348
2349 set findstring {}
2350 set fstring .tf.lbar.findstring
2351 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002352 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002353 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002354 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002355 set findtypemenu [makedroplist .tf.lbar.findtype \
Denton Liue2445882020-09-10 21:36:33 -07002356 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002357 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002358 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002359 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Denton Liue2445882020-09-10 21:36:33 -07002360 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002361 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002362 pack .tf.lbar.findloc -side right
2363 pack .tf.lbar.findtype -side right
2364 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002365
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002366 # Finish putting the upper half of the viewer together
2367 pack .tf.lbar -in .tf -side bottom -fill x
2368 pack .tf.bar -in .tf -side bottom -fill x
2369 pack .tf.histframe -fill both -side top -expand 1
2370 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002371 if {!$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002372 .ctop paneconfigure .tf -height $geometry(topheight)
2373 .ctop paneconfigure .tf -width $geometry(topwidth)
Pat Thoytsd93f1712009-04-17 01:24:35 +01002374 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002375
2376 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002377 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002378
2379 # lower left, a text box over search bar, scroll bar to the right
2380 # if we know window height, then that will set the lower text height, otherwise
2381 # we set lower text height which will drive window height
2382 if {[info exists geometry(main)]} {
Denton Liue2445882020-09-10 21:36:33 -07002383 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002384 } else {
Denton Liue2445882020-09-10 21:36:33 -07002385 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002386 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002387 ${NS}::frame .bleft.top
2388 ${NS}::frame .bleft.mid
2389 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002390
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002391 # gap between sub-widgets
2392 set wgap [font measure uifont "i"]
2393
Pat Thoytsd93f1712009-04-17 01:24:35 +01002394 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002395 pack .bleft.top.search -side left -padx 5
2396 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002397 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002398 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002399 lappend entries $sstring
2400 trace add variable searchstring write incrsearch
2401 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002402 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Denton Liue2445882020-09-10 21:36:33 -07002403 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002404 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Denton Liue2445882020-09-10 21:36:33 -07002405 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002406 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Denton Liue2445882020-09-10 21:36:33 -07002407 -command changediffdisp -variable diffelide -value {1 0}
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002408
Pat Thoytsd93f1712009-04-17 01:24:35 +01002409 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002410 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left -ipadx $wgap
Mark Hills0933b042010-01-13 20:40:19 +00002411 spinbox .bleft.mid.diffcontext -width 5 \
Denton Liue2445882020-09-10 21:36:33 -07002412 -from 0 -increment 1 -to 10000000 \
2413 -validate all -validatecommand "diffcontextvalidate %P" \
2414 -textvariable diffcontextstring
Steffen Prohaska890fae72007-08-12 12:05:46 +02002415 .bleft.mid.diffcontext set $diffcontext
2416 trace add variable diffcontextstring write diffcontextchange
2417 lappend entries .bleft.mid.diffcontext
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002418 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left -ipadx $wgap
Pat Thoytsd93f1712009-04-17 01:24:35 +01002419 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Denton Liue2445882020-09-10 21:36:33 -07002420 -command changeignorespace -variable ignorespace
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002421 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002422
2423 set worddiff [mc "Line diff"]
2424 if {[package vcompare $git_version "1.7.2"] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07002425 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2426 [mc "Markup words"] [mc "Color words"]
2427 trace add variable worddiff write changeworddiff
2428 pack .bleft.mid.worddiff -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002429 }
2430
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002431 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002432 text $ctext -background $bgcolor -foreground $fgcolor \
Denton Liue2445882020-09-10 21:36:33 -07002433 -state disabled -undo 0 -font textfont \
2434 -yscrollcommand scrolltext -wrap none \
2435 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002436 if {$have_tk85} {
Denton Liue2445882020-09-10 21:36:33 -07002437 $ctext conf -tabstyle wordprocessor
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002438 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002439 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2440 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002441 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002442 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002443 grid $ctext .bleft.bottom.sb -sticky nsew
2444 grid .bleft.bottom.sbhorizontal -sticky ew
2445 grid columnconfigure .bleft.bottom 0 -weight 1
2446 grid rowconfigure .bleft.bottom 0 -weight 1
2447 grid rowconfigure .bleft.bottom 1 -weight 0
2448 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002449 lappend bglist $ctext
2450 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002451
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002452 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002453 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002454 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2455 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Stefan Dotterweich113ce122020-02-11 22:24:48 +01002456 $ctext tag conf d0 -back [lindex $diffbgcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002457 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Stefan Dotterweich113ce122020-02-11 22:24:48 +01002458 $ctext tag conf dresult -back [lindex $diffbgcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002459 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2460 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2461 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2462 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2463 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2464 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2465 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2466 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2467 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2468 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2469 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2470 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2471 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2472 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2473 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2474 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002475 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002476 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002477 $ctext tag conf mresult -font textfontbold
2478 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002479 $ctext tag conf found -back $foundbgcolor
2480 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerras76d64ca2014-01-23 22:06:22 +11002481 $ctext tag conf wwrap -wrap word -lmargin2 1c
Paul Mackerras4399fe32013-01-03 10:10:31 +11002482 $ctext tag conf bold -font textfontbold
Johannes Sixt2faa6cd2020-04-09 19:48:12 +02002483 # set these to the lowest priority:
2484 $ctext tag lower currentsearchhit
2485 $ctext tag lower found
2486 $ctext tag lower filesep
2487 $ctext tag lower dresult
2488 $ctext tag lower d0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002489
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002490 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002491 if {!$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002492 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Pat Thoytsd93f1712009-04-17 01:24:35 +01002493 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002494
2495 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002496 ${NS}::frame .bright
2497 ${NS}::frame .bright.mode
2498 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Denton Liue2445882020-09-10 21:36:33 -07002499 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002500 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Denton Liue2445882020-09-10 21:36:33 -07002501 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002502 grid .bright.mode.patch .bright.mode.tree -sticky ew
2503 pack .bright.mode -side top -fill x
2504 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002505 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002506 text $cflist \
Denton Liue2445882020-09-10 21:36:33 -07002507 -selectbackground $selectbgcolor \
2508 -background $bgcolor -foreground $fgcolor \
2509 -font mainfont \
2510 -tabs [list $indent [expr {2 * $indent}]] \
2511 -yscrollcommand ".bright.sb set" \
2512 -cursor [. cget -cursor] \
2513 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002514 lappend bglist $cflist
2515 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002516 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002517 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002518 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002519 $cflist tag configure highlight \
Denton Liue2445882020-09-10 21:36:33 -07002520 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002521 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002522
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002523 .pwbottom add .bright
2524 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002525
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002526 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002527 if {[info exists geometry(main)]} {
Denton Liue2445882020-09-10 21:36:33 -07002528 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2529 if {$w > [winfo screenwidth .]} {
2530 set w [winfo screenwidth .]
2531 }
2532 if {$h > [winfo screenheight .]} {
2533 set h [winfo screenheight .]
2534 }
2535 wm geometry . "${w}x$h"
2536 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002537 }
2538
Pat Thoytsc876dba2009-04-14 22:09:53 +01002539 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2540 wm state . $geometry(state)
2541 }
2542
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002543 if {[tk windowingsystem] eq {aqua}} {
2544 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002545 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002546 } else {
2547 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002548 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002549 }
2550
Pat Thoytsd93f1712009-04-17 01:24:35 +01002551 if {$use_ttk} {
2552 bind .ctop <Map> {
2553 bind %W <Map> {}
2554 %W sashpos 0 $::geometry(topheight)
2555 }
2556 bind .pwbottom <Map> {
2557 bind %W <Map> {}
2558 %W sashpos 0 $::geometry(botwidth)
2559 }
Denton Liue2445882020-09-10 21:36:33 -07002560 bind .pwbottom <Configure> {resizecdetpanes %W %w}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002561 }
2562
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002563 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002564 bindall <1> {selcanvline %W %x %y}
2565 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002566 if {[tk windowingsystem] == "win32"} {
Denton Liue2445882020-09-10 21:36:33 -07002567 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2568 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
Mark Levedahl314c3092007-08-07 21:40:35 -04002569 } else {
Denton Liue2445882020-09-10 21:36:33 -07002570 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2571 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
2572 bind $ctext <Button> {
2573 if {"%b" eq 6} {
2574 $ctext xview scroll -5 units
2575 } elseif {"%b" eq 7} {
2576 $ctext xview scroll 5 units
2577 }
2578 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002579 if {[tk windowingsystem] eq "aqua"} {
2580 bindall <MouseWheel> {
2581 set delta [expr {- (%D)}]
2582 allcanvs yview scroll $delta units
2583 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002584 bindall <Shift-MouseWheel> {
2585 set delta [expr {- (%D)}]
2586 $canv xview scroll $delta units
2587 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002588 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002589 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002590 bindall <$::BM> "canvscan mark %W %x %y"
2591 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002592 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2593 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002594 bindkey <Home> selfirstline
2595 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002596 bind . <Key-Up> "selnextline -1"
2597 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002598 bind . <Shift-Key-Up> "dofind -1 0"
2599 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002600 bindkey <Key-Right> "goforw"
2601 bindkey <Key-Left> "goback"
2602 bind . <Key-Prior> "selnextpage -1"
2603 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002604 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2605 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2606 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2607 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2608 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2609 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002610 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2611 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2612 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002613 bindkey p "selnextline -1"
2614 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002615 bindkey z "goback"
2616 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002617 bindkey k "selnextline -1"
2618 bindkey j "selnextline 1"
2619 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002620 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002621 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002622 bindkey d "$ctext yview scroll 18 units"
2623 bindkey u "$ctext yview scroll -18 units"
Ismael Luceno0deb5c92015-04-15 13:18:17 -03002624 bindkey g {$sha1entry delete 0 end; focus $sha1entry}
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002625 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002626 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002627 bindkey <Key-Return> {dofind 1 1}
2628 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002629 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002630 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002631 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002632 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002633 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002634 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002635 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002636 bind . <$M1B-f> {dofind 1 1}
2637 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002638 bind . <$M1B-r> dosearchback
2639 bind . <$M1B-s> dosearch
2640 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002641 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002642 bind . <$M1B-KP_Add> {incrfont 1}
2643 bind . <$M1B-minus> {incrfont -1}
2644 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002645 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002646 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002647 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002648 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002649 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002650 bind $sha1entry <<PasteSelection>> clearsha1
Ilya Bobyrada2ea12014-03-20 01:58:51 -07002651 bind $sha1entry <<Paste>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002652 bind $cflist <1> {sel_flist %W %x %y; break}
2653 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002654 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002655 global ctxbut
2656 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002657 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002658 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002659 bind $ctext <<Selection>> rehighlight_search_results
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002660 for {set i 1} {$i < 10} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07002661 bind . <$M1B-Key-$i> [list go_to_parent $i]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002662 }
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002663
2664 set maincursor [. cget -cursor]
2665 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002666 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002667
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002668 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002669 makemenu $rowctxmenu {
Denton Liue2445882020-09-10 21:36:33 -07002670 {mc "Diff this -> selected" command {diffvssel 0}}
2671 {mc "Diff selected -> this" command {diffvssel 1}}
2672 {mc "Make patch" command mkpatch}
2673 {mc "Create tag" command mktag}
2674 {mc "Copy commit reference" command copyreference}
2675 {mc "Write commit to file" command writecommit}
2676 {mc "Create new branch" command mkbranch}
2677 {mc "Cherry-pick this commit" command cherrypick}
2678 {mc "Reset HEAD branch to here" command resethead}
2679 {mc "Mark this commit" command markhere}
2680 {mc "Return to mark" command gotomark}
2681 {mc "Find descendant of this and mark" command find_common_desc}
2682 {mc "Compare with marked commit" command compare_commits}
2683 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2684 {mc "Diff marked commit -> this" command {diffvsmark 1}}
2685 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002686 }
2687 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002688
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002689 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002690 makemenu $fakerowmenu {
Denton Liue2445882020-09-10 21:36:33 -07002691 {mc "Diff this -> selected" command {diffvssel 0}}
2692 {mc "Diff selected -> this" command {diffvssel 1}}
2693 {mc "Make patch" command mkpatch}
2694 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2695 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002696 }
2697 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002698
Paul Mackerras10299152006-08-02 09:52:01 +10002699 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002700 makemenu $headctxmenu {
Denton Liue2445882020-09-10 21:36:33 -07002701 {mc "Check out this branch" command cobranch}
2702 {mc "Rename this branch" command mvbranch}
2703 {mc "Remove this branch" command rmbranch}
2704 {mc "Copy branch name" command {clipboard clear; clipboard append $headmenuhead}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002705 }
2706 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002707
2708 global flist_menu
2709 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002710 makemenu $flist_menu {
Denton Liue2445882020-09-10 21:36:33 -07002711 {mc "Highlight this too" command {flist_hl 0}}
2712 {mc "Highlight this only" command {flist_hl 1}}
2713 {mc "External diff" command {external_diff}}
2714 {mc "Blame parent commit" command {external_blame 1}}
2715 {mc "Copy path" command {clipboard clear; clipboard append $flist_menu_file}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002716 }
2717 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002718
2719 global diff_menu
2720 set diff_menu .diffctxmenu
2721 makemenu $diff_menu {
Denton Liue2445882020-09-10 21:36:33 -07002722 {mc "Show origin of this line" command show_line_source}
2723 {mc "Run git gui blame on this line" command {external_blame_diff}}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002724 }
2725 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002726}
2727
Mark Levedahl314c3092007-08-07 21:40:35 -04002728# Windows sends all mouse wheel events to the current focused window, not
2729# the one where the mouse hovers, so bind those events here and redirect
2730# to the correct window
2731proc windows_mousewheel_redirector {W X Y D} {
2732 global canv canv2 canv3
2733 set w [winfo containing -displayof $W $X $Y]
2734 if {$w ne ""} {
Denton Liue2445882020-09-10 21:36:33 -07002735 set u [expr {$D < 0 ? 5 : -5}]
2736 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2737 allcanvs yview scroll $u units
2738 } else {
2739 catch {
2740 $w yview scroll $u units
2741 }
2742 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002743 }
2744}
2745
Paul Mackerras6df74032008-05-11 22:13:02 +10002746# Update row number label when selectedline changes
2747proc selectedline_change {n1 n2 op} {
2748 global selectedline rownumsel
2749
Paul Mackerras94b4a692008-05-20 20:51:06 +10002750 if {$selectedline eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07002751 set rownumsel {}
Paul Mackerras6df74032008-05-11 22:13:02 +10002752 } else {
Denton Liue2445882020-09-10 21:36:33 -07002753 set rownumsel [expr {$selectedline + 1}]
Paul Mackerras6df74032008-05-11 22:13:02 +10002754 }
2755}
2756
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002757# mouse-2 makes all windows scan vertically, but only the one
2758# the cursor is in scans horizontally
2759proc canvscan {op w x y} {
2760 global canv canv2 canv3
2761 foreach c [list $canv $canv2 $canv3] {
Denton Liue2445882020-09-10 21:36:33 -07002762 if {$c == $w} {
2763 $c scan $op $x $y
2764 } else {
2765 $c scan $op 0 $y
2766 }
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002767 }
2768}
2769
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002770proc scrollcanv {cscroll f0 f1} {
2771 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002772 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002773 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002774}
2775
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002776# when we make a key binding for the toplevel, make sure
2777# it doesn't get triggered when that key is pressed in the
2778# find string entry widget.
2779proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002780 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002781 bind . $ev $script
2782 set escript [bind Entry $ev]
2783 if {$escript == {}} {
Denton Liue2445882020-09-10 21:36:33 -07002784 set escript [bind Entry <Key>]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002785 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002786 foreach e $entries {
Denton Liue2445882020-09-10 21:36:33 -07002787 bind $e $ev "$escript; break"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002788 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002789}
2790
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002791proc bindmodfunctionkey {mod n script} {
2792 bind . <$mod-F$n> $script
2793 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2794}
2795
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002796# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002797# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002798proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002799 global ctext entries
2800 foreach e [concat $entries $ctext] {
Denton Liue2445882020-09-10 21:36:33 -07002801 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002802 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002803 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002804}
2805
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002806# Adjust the progress bar for a change in requested extent or canvas size
2807proc adjustprogress {} {
2808 global progresscanv progressitem progresscoords
2809 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002810 global rprogitem rprogcoord use_ttk
2811
2812 if {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002813 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2814 return
Pat Thoytsd93f1712009-04-17 01:24:35 +01002815 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002816
2817 set w [expr {[winfo width $progresscanv] - 4}]
2818 set x0 [expr {$w * [lindex $progresscoords 0]}]
2819 set x1 [expr {$w * [lindex $progresscoords 1]}]
2820 set h [winfo height $progresscanv]
2821 $progresscanv coords $progressitem $x0 0 $x1 $h
2822 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002823 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002824 set now [clock clicks -milliseconds]
2825 if {$now >= $lastprogupdate + 100} {
Denton Liue2445882020-09-10 21:36:33 -07002826 set progupdatepending 0
2827 update
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002828 } elseif {!$progupdatepending} {
Denton Liue2445882020-09-10 21:36:33 -07002829 set progupdatepending 1
2830 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002831 }
2832}
2833
2834proc doprogupdate {} {
2835 global lastprogupdate progupdatepending
2836
2837 if {$progupdatepending} {
Denton Liue2445882020-09-10 21:36:33 -07002838 set progupdatepending 0
2839 set lastprogupdate [clock clicks -milliseconds]
2840 update
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002841 }
2842}
2843
Max Kirilloveaf7e832015-03-04 05:58:18 +02002844proc config_check_tmp_exists {tries_left} {
2845 global config_file_tmp
2846
2847 if {[file exists $config_file_tmp]} {
Denton Liue2445882020-09-10 21:36:33 -07002848 incr tries_left -1
2849 if {$tries_left > 0} {
2850 after 100 [list config_check_tmp_exists $tries_left]
2851 } else {
2852 error_popup "There appears to be a stale $config_file_tmp\
Max Kirilloveaf7e832015-03-04 05:58:18 +02002853 file, which will prevent gitk from saving its configuration on exit.\
2854 Please remove it if it is not being used by any existing gitk process."
Denton Liue2445882020-09-10 21:36:33 -07002855 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002856 }
2857}
2858
Max Kirillov995f7922015-03-04 05:58:16 +02002859proc config_init_trace {name} {
2860 global config_variable_changed config_variable_original
2861
2862 upvar #0 $name var
2863 set config_variable_changed($name) 0
2864 set config_variable_original($name) $var
2865}
2866
2867proc config_variable_change_cb {name name2 op} {
2868 global config_variable_changed config_variable_original
2869
2870 upvar #0 $name var
2871 if {$op eq "write" &&
Denton Liue2445882020-09-10 21:36:33 -07002872 (![info exists config_variable_original($name)] ||
2873 $config_variable_original($name) ne $var)} {
2874 set config_variable_changed($name) 1
Max Kirillov995f7922015-03-04 05:58:16 +02002875 }
2876}
2877
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002878proc savestuff {w} {
Max Kirillov9fabefb2014-09-14 23:35:57 +03002879 global stuffsaved
Astril Hayato8f863392014-01-21 19:10:16 +00002880 global config_file config_file_tmp
Max Kirillov995f7922015-03-04 05:58:16 +02002881 global config_variables config_variable_changed
2882 global viewchanged
2883
2884 upvar #0 viewname current_viewname
2885 upvar #0 viewfiles current_viewfiles
2886 upvar #0 viewargs current_viewargs
2887 upvar #0 viewargscmd current_viewargscmd
2888 upvar #0 viewperm current_viewperm
2889 upvar #0 nextviewnum current_nextviewnum
2890 upvar #0 use_ttk current_use_ttk
Paul Mackerras4ef17532005-07-27 22:16:51 -05002891
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002892 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002893 if {![winfo viewable .]} return
Max Kirilloveaf7e832015-03-04 05:58:18 +02002894 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002895 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07002896 set try_count 0
2897 while {[catch {set f [open $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2898 if {[incr try_count] > 50} {
2899 error "Unable to write config file: $config_file_tmp exists"
2900 }
2901 after 100
2902 }
2903 set remove_tmp 1
2904 if {$::tcl_platform(platform) eq {windows}} {
2905 file attributes $config_file_tmp -hidden true
2906 }
2907 if {[file exists $config_file]} {
2908 source $config_file
2909 }
2910 foreach var_name $config_variables {
2911 upvar #0 $var_name var
2912 upvar 0 $var_name old_var
2913 if {!$config_variable_changed($var_name) && [info exists old_var]} {
2914 puts $f [list set $var_name $old_var]
2915 } else {
2916 puts $f [list set $var_name $var]
2917 }
2918 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002919
Denton Liue2445882020-09-10 21:36:33 -07002920 puts $f "set geometry(main) [wm geometry .]"
2921 puts $f "set geometry(state) [wm state .]"
2922 puts $f "set geometry(topwidth) [winfo width .tf]"
2923 puts $f "set geometry(topheight) [winfo height .tf]"
2924 if {$current_use_ttk} {
2925 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2926 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2927 } else {
2928 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2929 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2930 }
2931 puts $f "set geometry(botwidth) [winfo width .bleft]"
2932 puts $f "set geometry(botheight) [winfo height .bleft]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002933
Denton Liue2445882020-09-10 21:36:33 -07002934 array set view_save {}
2935 array set views {}
2936 if {![info exists permviews]} { set permviews {} }
2937 foreach view $permviews {
2938 set view_save([lindex $view 0]) 1
2939 set views([lindex $view 0]) $view
2940 }
2941 puts -nonewline $f "set permviews {"
2942 for {set v 1} {$v < $current_nextviewnum} {incr v} {
2943 if {$viewchanged($v)} {
2944 if {$current_viewperm($v)} {
2945 set views($current_viewname($v)) [list $current_viewname($v) $current_viewfiles($v) $current_viewargs($v) $current_viewargscmd($v)]
2946 } else {
2947 set view_save($current_viewname($v)) 0
2948 }
2949 }
2950 }
2951 # write old and updated view to their places and append remaining to the end
2952 foreach view $permviews {
2953 set view_name [lindex $view 0]
2954 if {$view_save($view_name)} {
2955 puts $f "{$views($view_name)}"
2956 }
2957 unset views($view_name)
2958 }
2959 foreach view_name [array names views] {
2960 puts $f "{$views($view_name)}"
2961 }
2962 puts $f "}"
2963 close $f
2964 file rename -force $config_file_tmp $config_file
2965 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002966 } err]} {
2967 puts "Error saving config: $err"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002968 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002969 if {$remove_tmp} {
Denton Liue2445882020-09-10 21:36:33 -07002970 file delete -force $config_file_tmp
Max Kirilloveaf7e832015-03-04 05:58:18 +02002971 }
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002972 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002973}
2974
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002975proc resizeclistpanes {win w} {
Paul Mackerras6cd80492020-10-03 15:20:33 +10002976 global oldwidth oldsash use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002977 if {[info exists oldwidth($win)]} {
halilsen1f6b1962022-02-20 19:47:35 +00002978 if {[info exists oldsash($win)]} {
2979 set s0 [lindex $oldsash($win) 0]
2980 set s1 [lindex $oldsash($win) 1]
Paul Mackerras6cd80492020-10-03 15:20:33 +10002981 } elseif {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07002982 set s0 [$win sashpos 0]
2983 set s1 [$win sashpos 1]
2984 } else {
2985 set s0 [$win sash coord 0]
2986 set s1 [$win sash coord 1]
2987 }
2988 if {$w < 60} {
2989 set sash0 [expr {int($w/2 - 2)}]
2990 set sash1 [expr {int($w*5/6 - 2)}]
2991 } else {
2992 set factor [expr {1.0 * $w / $oldwidth($win)}]
2993 set sash0 [expr {int($factor * [lindex $s0 0])}]
2994 set sash1 [expr {int($factor * [lindex $s1 0])}]
2995 if {$sash0 < 30} {
2996 set sash0 30
2997 }
2998 if {$sash1 < $sash0 + 20} {
2999 set sash1 [expr {$sash0 + 20}]
3000 }
3001 if {$sash1 > $w - 10} {
3002 set sash1 [expr {$w - 10}]
3003 if {$sash0 > $sash1 - 20} {
3004 set sash0 [expr {$sash1 - 20}]
3005 }
3006 }
3007 }
3008 if {$use_ttk} {
3009 $win sashpos 0 $sash0
3010 $win sashpos 1 $sash1
3011 } else {
3012 $win sash place 0 $sash0 [lindex $s0 1]
3013 $win sash place 1 $sash1 [lindex $s1 1]
halilsen465f0382022-02-20 19:47:36 +00003014 set sash0 [list $sash0 [lindex $s0 1]]
3015 set sash1 [list $sash1 [lindex $s1 1]]
Denton Liue2445882020-09-10 21:36:33 -07003016 }
halilsen1f6b1962022-02-20 19:47:35 +00003017 set oldsash($win) [list $sash0 $sash1]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003018 }
3019 set oldwidth($win) $w
3020}
3021
3022proc resizecdetpanes {win w} {
Paul Mackerras6cd80492020-10-03 15:20:33 +10003023 global oldwidth oldsash use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11003024 if {[info exists oldwidth($win)]} {
halilsen1f6b1962022-02-20 19:47:35 +00003025 if {[info exists oldsash($win)]} {
3026 set s0 $oldsash($win)
Paul Mackerras6cd80492020-10-03 15:20:33 +10003027 } elseif {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07003028 set s0 [$win sashpos 0]
3029 } else {
3030 set s0 [$win sash coord 0]
3031 }
3032 if {$w < 60} {
3033 set sash0 [expr {int($w*3/4 - 2)}]
3034 } else {
3035 set factor [expr {1.0 * $w / $oldwidth($win)}]
3036 set sash0 [expr {int($factor * [lindex $s0 0])}]
3037 if {$sash0 < 45} {
3038 set sash0 45
3039 }
3040 if {$sash0 > $w - 15} {
3041 set sash0 [expr {$w - 15}]
3042 }
3043 }
3044 if {$use_ttk} {
3045 $win sashpos 0 $sash0
3046 } else {
3047 $win sash place 0 $sash0 [lindex $s0 1]
halilsen465f0382022-02-20 19:47:36 +00003048 set sash0 [list $sash0 [lindex $s0 1]]
Denton Liue2445882020-09-10 21:36:33 -07003049 }
halilsen1f6b1962022-02-20 19:47:35 +00003050 set oldsash($win) $sash0
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003051 }
3052 set oldwidth($win) $w
3053}
3054
Paul Mackerrasb5721c72005-05-10 12:08:22 +00003055proc allcanvs args {
3056 global canv canv2 canv3
3057 eval $canv $args
3058 eval $canv2 $args
3059 eval $canv3 $args
3060}
3061
3062proc bindall {event action} {
3063 global canv canv2 canv3
3064 bind $canv $event $action
3065 bind $canv2 $event $action
3066 bind $canv3 $event $action
3067}
3068
Paul Mackerras9a40c502005-05-12 23:46:16 +00003069proc about {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003070 global bgcolor NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00003071 set w .about
3072 if {[winfo exists $w]} {
Denton Liue2445882020-09-10 21:36:33 -07003073 raise $w
3074 return
Paul Mackerras9a40c502005-05-12 23:46:16 +00003075 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003076 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003077 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003078 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01003079 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003080Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00003081
Paul Mackerrasfbf42642016-12-12 20:46:42 +11003082Copyright \u00a9 2005-2016 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00003083
Christian Stimmingd990ced2007-11-07 18:42:55 +01003084Use and redistribute under the terms of the GNU General Public License"] \
Denton Liue2445882020-09-10 21:36:33 -07003085 -justify center -aspect 400 -border 2 -bg $bgcolor -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003086 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003087 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00003088 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003089 bind $w <Visibility> "focus $w.ok"
3090 bind $w <Key-Escape> "destroy $w"
3091 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01003092 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00003093}
3094
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003095proc keys {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003096 global bgcolor NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003097 set w .keys
3098 if {[winfo exists $w]} {
Denton Liue2445882020-09-10 21:36:33 -07003099 raise $w
3100 return
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003101 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003102 if {[tk windowingsystem] eq {aqua}} {
Denton Liue2445882020-09-10 21:36:33 -07003103 set M1T Cmd
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003104 } else {
Denton Liue2445882020-09-10 21:36:33 -07003105 set M1T Ctrl
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003106 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003107 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003108 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003109 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003110 message $w.m -text "
3111[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003112
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003113[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01003114[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003115[mc "<Home> Move to first commit"]
3116[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05003117[mc "<Up>, p, k Move up one commit"]
3118[mc "<Down>, n, j Move down one commit"]
3119[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003120[mc "<Right>, x, l Go forward in history list"]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03003121[mc "<%s-n> Go to n-th parent of current commit in history list" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003122[mc "<PageUp> Move up one page in commit list"]
3123[mc "<PageDown> Move down one page in commit list"]
3124[mc "<%s-Home> Scroll to top of commit list" $M1T]
3125[mc "<%s-End> Scroll to bottom of commit list" $M1T]
3126[mc "<%s-Up> Scroll commit list up one line" $M1T]
3127[mc "<%s-Down> Scroll commit list down one line" $M1T]
3128[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
3129[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
3130[mc "<Shift-Up> Find backwards (upwards, later commits)"]
3131[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
3132[mc "<Delete>, b Scroll diff view up one page"]
3133[mc "<Backspace> Scroll diff view up one page"]
3134[mc "<Space> Scroll diff view down one page"]
3135[mc "u Scroll diff view up 18 lines"]
3136[mc "d Scroll diff view down 18 lines"]
3137[mc "<%s-F> Find" $M1T]
3138[mc "<%s-G> Move to next find hit" $M1T]
3139[mc "<Return> Move to next find hit"]
Ismael Luceno0deb5c92015-04-15 13:18:17 -03003140[mc "g Go to commit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01003141[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003142[mc "? Move to previous find hit"]
3143[mc "f Scroll diff view to next file"]
3144[mc "<%s-S> Search for next hit in diff view" $M1T]
3145[mc "<%s-R> Search for previous hit in diff view" $M1T]
3146[mc "<%s-KP+> Increase font size" $M1T]
3147[mc "<%s-plus> Increase font size" $M1T]
3148[mc "<%s-KP-> Decrease font size" $M1T]
3149[mc "<%s-minus> Decrease font size" $M1T]
3150[mc "<F5> Update"]
3151" \
Denton Liue2445882020-09-10 21:36:33 -07003152 -justify left -bg $bgcolor -border 2 -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003153 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003154 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003155 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003156 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003157 bind $w <Visibility> "focus $w.ok"
3158 bind $w <Key-Escape> "destroy $w"
3159 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003160}
3161
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003162# Procedures for manipulating the file list window at the
3163# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003164
3165proc treeview {w l openlevs} {
3166 global treecontents treediropen treeheight treeparent treeindex
3167
3168 set ix 0
3169 set treeindex() 0
3170 set lev 0
3171 set prefix {}
3172 set prefixend -1
3173 set prefendstack {}
3174 set htstack {}
3175 set ht 0
3176 set treecontents() {}
3177 $w conf -state normal
3178 foreach f $l {
Denton Liue2445882020-09-10 21:36:33 -07003179 while {[string range $f 0 $prefixend] ne $prefix} {
3180 if {$lev <= $openlevs} {
3181 $w mark set e:$treeindex($prefix) "end -1c"
3182 $w mark gravity e:$treeindex($prefix) left
3183 }
3184 set treeheight($prefix) $ht
3185 incr ht [lindex $htstack end]
3186 set htstack [lreplace $htstack end end]
3187 set prefixend [lindex $prefendstack end]
3188 set prefendstack [lreplace $prefendstack end end]
3189 set prefix [string range $prefix 0 $prefixend]
3190 incr lev -1
3191 }
3192 set tail [string range $f [expr {$prefixend+1}] end]
3193 while {[set slash [string first "/" $tail]] >= 0} {
3194 lappend htstack $ht
3195 set ht 0
3196 lappend prefendstack $prefixend
3197 incr prefixend [expr {$slash + 1}]
3198 set d [string range $tail 0 $slash]
3199 lappend treecontents($prefix) $d
3200 set oldprefix $prefix
3201 append prefix $d
3202 set treecontents($prefix) {}
3203 set treeindex($prefix) [incr ix]
3204 set treeparent($prefix) $oldprefix
3205 set tail [string range $tail [expr {$slash+1}] end]
3206 if {$lev <= $openlevs} {
3207 set ht 1
3208 set treediropen($prefix) [expr {$lev < $openlevs}]
3209 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3210 $w mark set d:$ix "end -1c"
3211 $w mark gravity d:$ix left
3212 set str "\n"
3213 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3214 $w insert end $str
3215 $w image create end -align center -image $bm -padx 1 \
3216 -name a:$ix
3217 $w insert end $d [highlight_tag $prefix]
3218 $w mark set s:$ix "end -1c"
3219 $w mark gravity s:$ix left
3220 }
3221 incr lev
3222 }
3223 if {$tail ne {}} {
3224 if {$lev <= $openlevs} {
3225 incr ht
3226 set str "\n"
3227 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3228 $w insert end $str
3229 $w insert end $tail [highlight_tag $f]
3230 }
3231 lappend treecontents($prefix) $tail
3232 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003233 }
3234 while {$htstack ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003235 set treeheight($prefix) $ht
3236 incr ht [lindex $htstack end]
3237 set htstack [lreplace $htstack end end]
3238 set prefixend [lindex $prefendstack end]
3239 set prefendstack [lreplace $prefendstack end end]
3240 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003241 }
3242 $w conf -state disabled
3243}
3244
3245proc linetoelt {l} {
3246 global treeheight treecontents
3247
3248 set y 2
3249 set prefix {}
3250 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07003251 foreach e $treecontents($prefix) {
3252 if {$y == $l} {
3253 return "$prefix$e"
3254 }
3255 set n 1
3256 if {[string index $e end] eq "/"} {
3257 set n $treeheight($prefix$e)
3258 if {$y + $n > $l} {
3259 append prefix $e
3260 incr y
3261 break
3262 }
3263 }
3264 incr y $n
3265 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003266 }
3267}
3268
Paul Mackerras45a9d502006-05-20 22:56:27 +10003269proc highlight_tree {y prefix} {
3270 global treeheight treecontents cflist
3271
3272 foreach e $treecontents($prefix) {
Denton Liue2445882020-09-10 21:36:33 -07003273 set path $prefix$e
3274 if {[highlight_tag $path] ne {}} {
3275 $cflist tag add bold $y.0 "$y.0 lineend"
3276 }
3277 incr y
3278 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3279 set y [highlight_tree $y $path]
3280 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003281 }
3282 return $y
3283}
3284
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003285proc treeclosedir {w dir} {
3286 global treediropen treeheight treeparent treeindex
3287
3288 set ix $treeindex($dir)
3289 $w conf -state normal
3290 $w delete s:$ix e:$ix
3291 set treediropen($dir) 0
3292 $w image configure a:$ix -image tri-rt
3293 $w conf -state disabled
3294 set n [expr {1 - $treeheight($dir)}]
3295 while {$dir ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003296 incr treeheight($dir) $n
3297 set dir $treeparent($dir)
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003298 }
3299}
3300
3301proc treeopendir {w dir} {
3302 global treediropen treeheight treeparent treecontents treeindex
3303
3304 set ix $treeindex($dir)
3305 $w conf -state normal
3306 $w image configure a:$ix -image tri-dn
3307 $w mark set e:$ix s:$ix
3308 $w mark gravity e:$ix right
3309 set lev 0
3310 set str "\n"
3311 set n [llength $treecontents($dir)]
3312 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
Denton Liue2445882020-09-10 21:36:33 -07003313 incr lev
3314 append str "\t"
3315 incr treeheight($x) $n
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003316 }
3317 foreach e $treecontents($dir) {
Denton Liue2445882020-09-10 21:36:33 -07003318 set de $dir$e
3319 if {[string index $e end] eq "/"} {
3320 set iy $treeindex($de)
3321 $w mark set d:$iy e:$ix
3322 $w mark gravity d:$iy left
3323 $w insert e:$ix $str
3324 set treediropen($de) 0
3325 $w image create e:$ix -align center -image tri-rt -padx 1 \
3326 -name a:$iy
3327 $w insert e:$ix $e [highlight_tag $de]
3328 $w mark set s:$iy e:$ix
3329 $w mark gravity s:$iy left
3330 set treeheight($de) 1
3331 } else {
3332 $w insert e:$ix $str
3333 $w insert e:$ix $e [highlight_tag $de]
3334 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003335 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003336 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003337 $w conf -state disabled
3338 set treediropen($dir) 1
3339 set top [lindex [split [$w index @0,0] .] 0]
3340 set ht [$w cget -height]
3341 set l [lindex [split [$w index s:$ix] .] 0]
3342 if {$l < $top} {
Denton Liue2445882020-09-10 21:36:33 -07003343 $w yview $l.0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003344 } elseif {$l + $n + 1 > $top + $ht} {
Denton Liue2445882020-09-10 21:36:33 -07003345 set top [expr {$l + $n + 2 - $ht}]
3346 if {$l < $top} {
3347 set top $l
3348 }
3349 $w yview $top.0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003350 }
3351}
3352
3353proc treeclick {w x y} {
3354 global treediropen cmitmode ctext cflist cflist_top
3355
3356 if {$cmitmode ne "tree"} return
3357 if {![info exists cflist_top]} return
3358 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3359 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3360 $cflist tag add highlight $l.0 "$l.0 lineend"
3361 set cflist_top $l
3362 if {$l == 1} {
Denton Liue2445882020-09-10 21:36:33 -07003363 $ctext yview 1.0
3364 return
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003365 }
3366 set e [linetoelt $l]
3367 if {[string index $e end] ne "/"} {
Denton Liue2445882020-09-10 21:36:33 -07003368 showfile $e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003369 } elseif {$treediropen($e)} {
Denton Liue2445882020-09-10 21:36:33 -07003370 treeclosedir $w $e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003371 } else {
Denton Liue2445882020-09-10 21:36:33 -07003372 treeopendir $w $e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003373 }
3374}
3375
3376proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003377 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003378
3379 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003380 if {$jump_to_here ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003381 set f [lindex $jump_to_here 0]
3382 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3383 showfile $f
3384 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003385 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003386}
3387
3388image create bitmap tri-rt -background black -foreground blue -data {
3389 #define tri-rt_width 13
3390 #define tri-rt_height 13
3391 static unsigned char tri-rt_bits[] = {
3392 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3393 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3394 0x00, 0x00};
3395} -maskdata {
3396 #define tri-rt-mask_width 13
3397 #define tri-rt-mask_height 13
3398 static unsigned char tri-rt-mask_bits[] = {
3399 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3400 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3401 0x08, 0x00};
3402}
3403image create bitmap tri-dn -background black -foreground blue -data {
3404 #define tri-dn_width 13
3405 #define tri-dn_height 13
3406 static unsigned char tri-dn_bits[] = {
3407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3408 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3409 0x00, 0x00};
3410} -maskdata {
3411 #define tri-dn-mask_width 13
3412 #define tri-dn-mask_height 13
3413 static unsigned char tri-dn-mask_bits[] = {
3414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3415 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3416 0x00, 0x00};
3417}
3418
Paul Mackerras887c9962007-08-20 19:36:20 +10003419image create bitmap reficon-T -background black -foreground yellow -data {
3420 #define tagicon_width 13
3421 #define tagicon_height 9
3422 static unsigned char tagicon_bits[] = {
3423 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3424 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3425} -maskdata {
3426 #define tagicon-mask_width 13
3427 #define tagicon-mask_height 9
3428 static unsigned char tagicon-mask_bits[] = {
3429 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3430 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3431}
3432set rectdata {
3433 #define headicon_width 13
3434 #define headicon_height 9
3435 static unsigned char headicon_bits[] = {
3436 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3437 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3438}
3439set rectmask {
3440 #define headicon-mask_width 13
3441 #define headicon-mask_height 9
3442 static unsigned char headicon-mask_bits[] = {
3443 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3444 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3445}
Paul Mackerras6e8fda52016-12-12 11:29:21 +11003446image create bitmap reficon-H -background black -foreground "#00ff00" \
Paul Mackerras887c9962007-08-20 19:36:20 +10003447 -data $rectdata -maskdata $rectmask
Paul Wised7cc4fb2019-03-21 15:05:32 +08003448image create bitmap reficon-R -background black -foreground "#ffddaa" \
3449 -data $rectdata -maskdata $rectmask
Paul Mackerras887c9962007-08-20 19:36:20 +10003450image create bitmap reficon-o -background black -foreground "#ddddff" \
3451 -data $rectdata -maskdata $rectmask
3452
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003453proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003454 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003455
3456 $cflist conf -state normal
3457 $cflist delete 0.0 end
3458 if {$first ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003459 $cflist insert end $first
3460 set cflist_top 1
3461 $cflist tag add highlight 1.0 "1.0 lineend"
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003462 } else {
Denton Liue2445882020-09-10 21:36:33 -07003463 unset -nocomplain cflist_top
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003464 }
3465 $cflist conf -state disabled
3466 set difffilestart {}
3467}
3468
Paul Mackerras63b79192006-05-20 21:31:52 +10003469proc highlight_tag {f} {
3470 global highlight_paths
3471
3472 foreach p $highlight_paths {
Denton Liue2445882020-09-10 21:36:33 -07003473 if {[string match $p $f]} {
3474 return "bold"
3475 }
Paul Mackerras63b79192006-05-20 21:31:52 +10003476 }
3477 return {}
3478}
3479
3480proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003481 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003482
Paul Mackerras45a9d502006-05-20 22:56:27 +10003483 $cflist conf -state normal
3484 if {$cmitmode ne "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07003485 set end [lindex [split [$cflist index end] .] 0]
3486 for {set l 2} {$l < $end} {incr l} {
3487 set line [$cflist get $l.0 "$l.0 lineend"]
3488 if {[highlight_tag $line] ne {}} {
3489 $cflist tag add bold $l.0 "$l.0 lineend"
3490 }
3491 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003492 } else {
Denton Liue2445882020-09-10 21:36:33 -07003493 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003494 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003495 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003496}
3497
3498proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003499 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003500
Paul Mackerras45a9d502006-05-20 22:56:27 +10003501 $cflist conf -state normal
3502 $cflist tag remove bold 1.0 end
3503 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003504}
3505
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003506proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003507 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003508
Paul Mackerras45a9d502006-05-20 22:56:27 +10003509 $cflist conf -state normal
3510 foreach f $fl {
Denton Liue2445882020-09-10 21:36:33 -07003511 $cflist insert end "\n"
3512 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003513 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003514 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003515}
3516
3517proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003518 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003519
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003520 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003521 if {![info exists cflist_top]} return
3522 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003523 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3524 $cflist tag add highlight $l.0 "$l.0 lineend"
3525 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003526 if {$l == 1} {
Denton Liue2445882020-09-10 21:36:33 -07003527 $ctext yview 1.0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003528 } else {
Denton Liue2445882020-09-10 21:36:33 -07003529 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003530 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003531 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003532}
3533
Paul Mackerras32447292007-07-27 22:30:15 +10003534proc pop_flist_menu {w X Y x y} {
3535 global ctext cflist cmitmode flist_menu flist_menu_file
3536 global treediffs diffids
3537
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003538 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003539 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3540 if {$l <= 1} return
3541 if {$cmitmode eq "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07003542 set e [linetoelt $l]
3543 if {[string index $e end] eq "/"} return
Paul Mackerras32447292007-07-27 22:30:15 +10003544 } else {
Denton Liue2445882020-09-10 21:36:33 -07003545 set e [lindex $treediffs($diffids) [expr {$l-2}]]
Paul Mackerras32447292007-07-27 22:30:15 +10003546 }
3547 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003548 set xdiffstate "normal"
3549 if {$cmitmode eq "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07003550 set xdiffstate "disabled"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003551 }
3552 # Disable "External diff" item in tree mode
3553 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003554 tk_popup $flist_menu $X $Y
3555}
3556
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003557proc find_ctext_fileinfo {line} {
3558 global ctext_file_names ctext_file_lines
3559
3560 set ok [bsearch $ctext_file_lines $line]
3561 set tline [lindex $ctext_file_lines $ok]
3562
3563 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3564 return {}
3565 } else {
3566 return [list [lindex $ctext_file_names $ok] $tline]
3567 }
3568}
3569
3570proc pop_diff_menu {w X Y x y} {
3571 global ctext diff_menu flist_menu_file
3572 global diff_menu_txtpos diff_menu_line
3573 global diff_menu_filebase
3574
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003575 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3576 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003577 # don't pop up the menu on hunk-separator or file-separator lines
3578 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07003579 return
Paul Mackerras190ec522008-10-27 21:13:37 +11003580 }
3581 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003582 set f [find_ctext_fileinfo $diff_menu_line]
3583 if {$f eq {}} return
3584 set flist_menu_file [lindex $f 0]
3585 set diff_menu_filebase [lindex $f 1]
3586 tk_popup $diff_menu $X $Y
3587}
3588
Paul Mackerras32447292007-07-27 22:30:15 +10003589proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003590 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003591
3592 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003593 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Denton Liue2445882020-09-10 21:36:33 -07003594 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003595 } else {
Denton Liue2445882020-09-10 21:36:33 -07003596 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003597 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003598 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003599}
3600
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003601proc gitknewtmpdir {} {
David Aguilarc7664f12014-06-13 14:13:37 -07003602 global diffnum gitktmpdir gitdir env
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003603
3604 if {![info exists gitktmpdir]} {
Denton Liue2445882020-09-10 21:36:33 -07003605 if {[info exists env(GITK_TMPDIR)]} {
3606 set tmpdir $env(GITK_TMPDIR)
3607 } elseif {[info exists env(TMPDIR)]} {
3608 set tmpdir $env(TMPDIR)
3609 } else {
3610 set tmpdir $gitdir
3611 }
3612 set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
3613 if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
3614 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
3615 }
3616 if {[catch {file mkdir $gitktmpdir} err]} {
3617 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3618 unset gitktmpdir
3619 return {}
3620 }
3621 set diffnum 0
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003622 }
3623 incr diffnum
3624 set diffdir [file join $gitktmpdir $diffnum]
3625 if {[catch {file mkdir $diffdir} err]} {
Denton Liue2445882020-09-10 21:36:33 -07003626 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3627 return {}
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003628 }
3629 return $diffdir
3630}
3631
Thomas Arcila314f5de2008-03-24 12:55:36 +01003632proc save_file_from_commit {filename output what} {
3633 global nullfile
3634
3635 if {[catch {exec git show $filename -- > $output} err]} {
Denton Liue2445882020-09-10 21:36:33 -07003636 if {[string match "fatal: bad revision *" $err]} {
3637 return $nullfile
3638 }
3639 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
3640 return {}
Thomas Arcila314f5de2008-03-24 12:55:36 +01003641 }
3642 return $output
3643}
3644
3645proc external_diff_get_one_file {diffid filename diffdir} {
3646 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003647 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003648
3649 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003650 set difffile [file join $worktree $filename]
Denton Liue2445882020-09-10 21:36:33 -07003651 if {[file exists $difffile]} {
3652 return $difffile
3653 }
3654 return $nullfile
Thomas Arcila314f5de2008-03-24 12:55:36 +01003655 }
3656 if {$diffid == $nullid2} {
3657 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3658 return [save_file_from_commit :$filename $difffile index]
3659 }
3660 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3661 return [save_file_from_commit $diffid:$filename $difffile \
Denton Liue2445882020-09-10 21:36:33 -07003662 "revision $diffid"]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003663}
3664
3665proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003666 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003667 global flist_menu_file
3668 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003669 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003670
3671 if {[llength $diffids] == 1} {
3672 # no reference commit given
3673 set diffidto [lindex $diffids 0]
3674 if {$diffidto eq $nullid} {
3675 # diffing working copy with index
3676 set diffidfrom $nullid2
3677 } elseif {$diffidto eq $nullid2} {
3678 # diffing index with HEAD
3679 set diffidfrom "HEAD"
3680 } else {
3681 # use first parent commit
3682 global parentlist selectedline
3683 set diffidfrom [lindex $parentlist $selectedline 0]
3684 }
3685 } else {
3686 set diffidfrom [lindex $diffids 0]
3687 set diffidto [lindex $diffids 1]
3688 }
3689
3690 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003691 set diffdir [gitknewtmpdir]
3692 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003693
3694 # gather files to diff
3695 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3696 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3697
3698 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003699 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3700 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003701 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003702 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003703 } else {
3704 fconfigure $fl -blocking 0
3705 filerun $fl [list delete_at_eof $fl $diffdir]
3706 }
3707 }
3708}
3709
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003710proc find_hunk_blamespec {base line} {
3711 global ctext
3712
3713 # Find and parse the hunk header
3714 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3715 if {$s_lix eq {}} return
3716
3717 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3718 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
Denton Liue2445882020-09-10 21:36:33 -07003719 s_line old_specs osz osz1 new_line nsz]} {
3720 return
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003721 }
3722
3723 # base lines for the parents
3724 set base_lines [list $new_line]
3725 foreach old_spec [lrange [split $old_specs " "] 1 end] {
Denton Liue2445882020-09-10 21:36:33 -07003726 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3727 old_spec old_line osz]} {
3728 return
3729 }
3730 lappend base_lines $old_line
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003731 }
3732
3733 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003734 set max_parent [expr {[llength $base_lines]-2}]
3735 set dline 0
3736 set s_lno [lindex [split $s_lix "."] 0]
3737
Paul Mackerras190ec522008-10-27 21:13:37 +11003738 # Determine if the line is removed
3739 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3740 if {[string match {[-+ ]*} $chunk]} {
Denton Liue2445882020-09-10 21:36:33 -07003741 set removed_idx [string first "-" $chunk]
3742 # Choose a parent index
3743 if {$removed_idx >= 0} {
3744 set parent $removed_idx
3745 } else {
3746 set unchanged_idx [string first " " $chunk]
3747 if {$unchanged_idx >= 0} {
3748 set parent $unchanged_idx
3749 } else {
3750 # blame the current commit
3751 set parent -1
3752 }
3753 }
3754 # then count other lines that belong to it
3755 for {set i $line} {[incr i -1] > $s_lno} {} {
3756 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3757 # Determine if the line is removed
3758 set removed_idx [string first "-" $chunk]
3759 if {$parent >= 0} {
3760 set code [string index $chunk $parent]
3761 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3762 incr dline
3763 }
3764 } else {
3765 if {$removed_idx < 0} {
3766 incr dline
3767 }
3768 }
3769 }
3770 incr parent
Paul Mackerras190ec522008-10-27 21:13:37 +11003771 } else {
Denton Liue2445882020-09-10 21:36:33 -07003772 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003773 }
3774
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003775 incr dline [lindex $base_lines $parent]
3776 return [list $parent $dline]
3777}
3778
3779proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003780 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003781 global diff_menu_txtpos diff_menu_line
3782 global diff_menu_filebase flist_menu_file
3783
3784 if {$cmitmode eq "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07003785 set parent_idx 0
3786 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003787 } else {
Denton Liue2445882020-09-10 21:36:33 -07003788 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3789 if {$hinfo ne {}} {
3790 set parent_idx [lindex $hinfo 0]
3791 set line [lindex $hinfo 1]
3792 } else {
3793 set parent_idx 0
3794 set line 0
3795 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003796 }
3797
3798 external_blame $parent_idx $line
3799}
3800
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003801# Find the SHA1 ID of the blob for file $fname in the index
3802# at stage 0 or 2
3803proc index_sha1 {fname} {
3804 set f [open [list | git ls-files -s $fname] r]
3805 while {[gets $f line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07003806 set info [lindex [split $line "\t"] 0]
3807 set stage [lindex $info 2]
3808 if {$stage eq "0" || $stage eq "2"} {
3809 close $f
3810 return [lindex $info 1]
3811 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003812 }
3813 close $f
3814 return {}
3815}
3816
Paul Mackerras9712b812008-12-06 21:44:05 +11003817# Turn an absolute path into one relative to the current directory
3818proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003819 if {[file pathtype $f] eq "relative"} {
Denton Liue2445882020-09-10 21:36:33 -07003820 return $f
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003821 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003822 set elts [file split $f]
3823 set here [file split [pwd]]
3824 set ei 0
3825 set hi 0
3826 set res {}
3827 foreach d $here {
Denton Liue2445882020-09-10 21:36:33 -07003828 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3829 lappend res ".."
3830 } else {
3831 incr ei
3832 }
3833 incr hi
Paul Mackerras9712b812008-12-06 21:44:05 +11003834 }
3835 set elts [concat $res [lrange $elts $ei end]]
3836 return [eval file join $elts]
3837}
3838
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003839proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003840 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003841 global nullid nullid2
3842 global parentlist selectedline currentid
3843
3844 if {$parent_idx > 0} {
Denton Liue2445882020-09-10 21:36:33 -07003845 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003846 } else {
Denton Liue2445882020-09-10 21:36:33 -07003847 set base_commit $currentid
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003848 }
3849
3850 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
Denton Liue2445882020-09-10 21:36:33 -07003851 error_popup [mc "No such commit"]
3852 return
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003853 }
3854
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003855 set cmdline [list git gui blame]
3856 if {$line ne {} && $line > 1} {
Denton Liue2445882020-09-10 21:36:33 -07003857 lappend cmdline "--line=$line"
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003858 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003859 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003860 # Unfortunately it seems git gui blame doesn't like
3861 # being given an absolute path...
3862 set f [make_relative $f]
3863 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003864 if {[catch {eval exec $cmdline &} err]} {
Denton Liue2445882020-09-10 21:36:33 -07003865 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003866 }
3867}
3868
Paul Mackerras8a897742008-10-27 21:36:25 +11003869proc show_line_source {} {
3870 global cmitmode currentid parents curview blamestuff blameinst
3871 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003872 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003873
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003874 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003875 if {$cmitmode eq "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07003876 set id $currentid
3877 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Paul Mackerras8a897742008-10-27 21:36:25 +11003878 } else {
Denton Liue2445882020-09-10 21:36:33 -07003879 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3880 if {$h eq {}} return
3881 set pi [lindex $h 0]
3882 if {$pi == 0} {
3883 mark_ctext_line $diff_menu_line
3884 return
3885 }
3886 incr pi -1
3887 if {$currentid eq $nullid} {
3888 if {$pi > 0} {
3889 # must be a merge in progress...
3890 if {[catch {
3891 # get the last line from .git/MERGE_HEAD
3892 set f [open [file join $gitdir MERGE_HEAD] r]
3893 set id [lindex [split [read $f] "\n"] end-1]
3894 close $f
3895 } err]} {
3896 error_popup [mc "Couldn't read merge head: %s" $err]
3897 return
3898 }
3899 } elseif {$parents($curview,$currentid) eq $nullid2} {
3900 # need to do the blame from the index
3901 if {[catch {
3902 set from_index [index_sha1 $flist_menu_file]
3903 } err]} {
3904 error_popup [mc "Error reading index: %s" $err]
3905 return
3906 }
3907 } else {
3908 set id $parents($curview,$currentid)
3909 }
3910 } else {
3911 set id [lindex $parents($curview,$currentid) $pi]
3912 }
3913 set line [lindex $h 1]
Paul Mackerras8a897742008-10-27 21:36:25 +11003914 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003915 set blameargs {}
3916 if {$from_index ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003917 lappend blameargs | git cat-file blob $from_index
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003918 }
3919 lappend blameargs | git blame -p -L$line,+1
3920 if {$from_index ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003921 lappend blameargs --contents -
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003922 } else {
Denton Liue2445882020-09-10 21:36:33 -07003923 lappend blameargs $id
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003924 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003925 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003926 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07003927 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003928 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07003929 error_popup [mc "Couldn't start git blame: %s" $err]
3930 return
Paul Mackerras8a897742008-10-27 21:36:25 +11003931 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003932 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003933 fconfigure $f -blocking 0
3934 set i [reg_instance $f]
3935 set blamestuff($i) {}
3936 set blameinst $i
3937 filerun $f [list read_line_source $f $i]
3938}
3939
3940proc stopblaming {} {
3941 global blameinst
3942
3943 if {[info exists blameinst]} {
Denton Liue2445882020-09-10 21:36:33 -07003944 stop_instance $blameinst
3945 unset blameinst
3946 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003947 }
3948}
3949
3950proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003951 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003952
3953 while {[gets $fd line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07003954 lappend blamestuff($inst) $line
Paul Mackerras8a897742008-10-27 21:36:25 +11003955 }
3956 if {![eof $fd]} {
Denton Liue2445882020-09-10 21:36:33 -07003957 return 1
Paul Mackerras8a897742008-10-27 21:36:25 +11003958 }
3959 unset commfd($inst)
3960 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003961 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003962 fconfigure $fd -blocking 1
3963 if {[catch {close $fd} err]} {
Denton Liue2445882020-09-10 21:36:33 -07003964 error_popup [mc "Error running git blame: %s" $err]
3965 return 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003966 }
3967
3968 set fname {}
3969 set line [split [lindex $blamestuff($inst) 0] " "]
3970 set id [lindex $line 0]
3971 set lnum [lindex $line 1]
3972 if {[string length $id] == 40 && [string is xdigit $id] &&
Denton Liue2445882020-09-10 21:36:33 -07003973 [string is digit -strict $lnum]} {
3974 # look for "filename" line
3975 foreach l $blamestuff($inst) {
3976 if {[string match "filename *" $l]} {
3977 set fname [string range $l 9 end]
3978 break
3979 }
3980 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003981 }
3982 if {$fname ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07003983 # all looks good, select it
3984 if {$id eq $nullid} {
3985 # blame uses all-zeroes to mean not committed,
3986 # which would mean a change in the index
3987 set id $nullid2
3988 }
3989 if {[commitinview $id $curview]} {
3990 selectline [rowofcommit $id] 1 [list $fname $lnum] 1
3991 } else {
3992 error_popup [mc "That line comes from commit %s, \
3993 which is not in this view" [shortids $id]]
3994 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003995 } else {
Denton Liue2445882020-09-10 21:36:33 -07003996 puts "oops couldn't parse git blame output"
Paul Mackerras8a897742008-10-27 21:36:25 +11003997 }
3998 return 0
3999}
4000
Thomas Arcila314f5de2008-03-24 12:55:36 +01004001# delete $dir when we see eof on $f (presumably because the child has exited)
4002proc delete_at_eof {f dir} {
4003 while {[gets $f line] >= 0} {}
4004 if {[eof $f]} {
Denton Liue2445882020-09-10 21:36:33 -07004005 if {[catch {close $f} err]} {
4006 error_popup "[mc "External diff viewer failed:"] $err"
4007 }
4008 file delete -force $dir
4009 return 0
Thomas Arcila314f5de2008-03-24 12:55:36 +01004010 }
4011 return 1
4012}
4013
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004014# Functions for adding and removing shell-type quoting
4015
4016proc shellquote {str} {
4017 if {![string match "*\['\"\\ \t]*" $str]} {
Denton Liue2445882020-09-10 21:36:33 -07004018 return $str
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004019 }
4020 if {![string match "*\['\"\\]*" $str]} {
Denton Liue2445882020-09-10 21:36:33 -07004021 return "\"$str\""
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004022 }
4023 if {![string match "*'*" $str]} {
Denton Liue2445882020-09-10 21:36:33 -07004024 return "'$str'"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004025 }
4026 return "\"[string map {\" \\\" \\ \\\\} $str]\""
4027}
4028
4029proc shellarglist {l} {
4030 set str {}
4031 foreach a $l {
Denton Liue2445882020-09-10 21:36:33 -07004032 if {$str ne {}} {
4033 append str " "
4034 }
4035 append str [shellquote $a]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004036 }
4037 return $str
4038}
4039
4040proc shelldequote {str} {
4041 set ret {}
4042 set used -1
4043 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07004044 incr used
4045 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
4046 append ret [string range $str $used end]
4047 set used [string length $str]
4048 break
4049 }
4050 set first [lindex $first 0]
4051 set ch [string index $str $first]
4052 if {$first > $used} {
4053 append ret [string range $str $used [expr {$first - 1}]]
4054 set used $first
4055 }
4056 if {$ch eq " " || $ch eq "\t"} break
4057 incr used
4058 if {$ch eq "'"} {
4059 set first [string first "'" $str $used]
4060 if {$first < 0} {
4061 error "unmatched single-quote"
4062 }
4063 append ret [string range $str $used [expr {$first - 1}]]
4064 set used $first
4065 continue
4066 }
4067 if {$ch eq "\\"} {
4068 if {$used >= [string length $str]} {
4069 error "trailing backslash"
4070 }
4071 append ret [string index $str $used]
4072 continue
4073 }
4074 # here ch == "\""
4075 while {1} {
4076 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
4077 error "unmatched double-quote"
4078 }
4079 set first [lindex $first 0]
4080 set ch [string index $str $first]
4081 if {$first > $used} {
4082 append ret [string range $str $used [expr {$first - 1}]]
4083 set used $first
4084 }
4085 if {$ch eq "\""} break
4086 incr used
4087 append ret [string index $str $used]
4088 incr used
4089 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004090 }
4091 return [list $used $ret]
4092}
4093
4094proc shellsplit {str} {
4095 set l {}
4096 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07004097 set str [string trimleft $str]
4098 if {$str eq {}} break
4099 set dq [shelldequote $str]
4100 set n [lindex $dq 0]
4101 set word [lindex $dq 1]
4102 set str [string range $str $n end]
4103 lappend l $word
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004104 }
4105 return $l
4106}
4107
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004108proc set_window_title {} {
4109 global appname curview viewname vrevs
4110 set rev [mc "All files"]
4111 if {$curview ne 0} {
Denton Liue2445882020-09-10 21:36:33 -07004112 if {$viewname($curview) eq [mc "Command line"]} {
4113 set rev [string map {"--gitk-symmetric-diff-marker" "--merge"} $vrevs($curview)]
4114 } else {
4115 set rev $viewname($curview)
4116 }
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004117 }
4118 wm title . "[reponame]: $rev - $appname"
4119}
4120
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004121# Code to implement multiple views
4122
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004123proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004124 global nextviewnum newviewname newishighlight
4125 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004126
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004127 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004128 set top .gitkview
4129 if {[winfo exists $top]} {
Denton Liue2445882020-09-10 21:36:33 -07004130 raise $top
4131 return
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004132 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004133 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01004134 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004135 set newviewopts($nextviewnum,perm) 0
4136 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01004137 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004138}
4139
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004140set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004141 {perm b . {} {mc "Remember this view"}}
4142 {reflabel l + {} {mc "References (space separated list):"}}
4143 {refs t15 .. {} {mc "Branches & tags:"}}
4144 {allrefs b *. "--all" {mc "All refs"}}
4145 {branches b . "--branches" {mc "All (local) branches"}}
4146 {tags b . "--tags" {mc "All tags"}}
4147 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
4148 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
4149 {author t15 .. "--author=*" {mc "Author:"}}
4150 {committer t15 . "--committer=*" {mc "Committer:"}}
4151 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
4152 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
Alex Henrie00132512015-04-02 15:05:06 -06004153 {igrep b .. "--invert-grep" {mc "Matches no Commit Info criteria"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004154 {changes_l l + {} {mc "Changes to Files:"}}
4155 {pickaxe_s r0 . {} {mc "Fixed String"}}
4156 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
4157 {pickaxe t15 .. "-S*" {mc "Search string:"}}
4158 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
4159 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
4160 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
4161 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
4162 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
4163 {skip t10 . "--skip=*" {mc "Number to skip:"}}
4164 {misc_lbl l + {} {mc "Miscellaneous options:"}}
4165 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
4166 {lright b . "--left-right" {mc "Mark branch sides"}}
4167 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02004168 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004169 {args t50 *. {} {mc "Additional arguments to git log:"}}
4170 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
4171 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004172 }
4173
Jonathan Niedere7feb692010-03-06 16:48:38 -06004174# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004175proc encode_view_opts {n} {
4176 global known_view_options newviewopts
4177
4178 set rargs [list]
4179 foreach opt $known_view_options {
Denton Liue2445882020-09-10 21:36:33 -07004180 set patterns [lindex $opt 3]
4181 if {$patterns eq {}} continue
4182 set pattern [lindex $patterns 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004183
Denton Liue2445882020-09-10 21:36:33 -07004184 if {[lindex $opt 1] eq "b"} {
4185 set val $newviewopts($n,[lindex $opt 0])
4186 if {$val} {
4187 lappend rargs $pattern
4188 }
4189 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4190 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4191 set val $newviewopts($n,$button_id)
4192 if {$val eq $value} {
4193 lappend rargs $pattern
4194 }
4195 } else {
4196 set val $newviewopts($n,[lindex $opt 0])
4197 set val [string trim $val]
4198 if {$val ne {}} {
4199 set pfix [string range $pattern 0 end-1]
4200 lappend rargs $pfix$val
4201 }
4202 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004203 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004204 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004205 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4206}
4207
Jonathan Niedere7feb692010-03-06 16:48:38 -06004208# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004209proc decode_view_opts {n view_args} {
4210 global known_view_options newviewopts
4211
4212 foreach opt $known_view_options {
Denton Liue2445882020-09-10 21:36:33 -07004213 set id [lindex $opt 0]
4214 if {[lindex $opt 1] eq "b"} {
4215 # Checkboxes
4216 set val 0
Elijah Newren13d40b62009-03-23 11:57:46 -06004217 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
Denton Liue2445882020-09-10 21:36:33 -07004218 # Radiobuttons
4219 regexp {^(.*_)} $id uselessvar id
4220 set val 0
4221 } else {
4222 # Text fields
4223 set val {}
4224 }
4225 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004226 }
4227 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004228 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004229 foreach arg $view_args {
Denton Liue2445882020-09-10 21:36:33 -07004230 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4231 && ![info exists found(limit)]} {
4232 set newviewopts($n,limit) $cnt
4233 set found(limit) 1
4234 continue
4235 }
4236 catch { unset val }
4237 foreach opt $known_view_options {
4238 set id [lindex $opt 0]
4239 if {[info exists found($id)]} continue
4240 foreach pattern [lindex $opt 3] {
4241 if {![string match $pattern $arg]} continue
4242 if {[lindex $opt 1] eq "b"} {
4243 # Check buttons
4244 set val 1
4245 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4246 # Radio buttons
4247 regexp {^(.*_)} $id uselessvar id
4248 set val $num
4249 } else {
4250 # Text input fields
4251 set size [string length $pattern]
4252 set val [string range $arg [expr {$size-1}] end]
4253 }
4254 set newviewopts($n,$id) $val
4255 set found($id) 1
4256 break
4257 }
4258 if {[info exists val]} break
4259 }
4260 if {[info exists val]} continue
4261 if {[regexp {^-} $arg]} {
4262 lappend oargs $arg
4263 } else {
4264 lappend refargs $arg
4265 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004266 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004267 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004268 set newviewopts($n,args) [shellarglist $oargs]
4269}
4270
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004271proc edit_or_newview {} {
4272 global curview
4273
4274 if {$curview > 0} {
Denton Liue2445882020-09-10 21:36:33 -07004275 editview
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004276 } else {
Denton Liue2445882020-09-10 21:36:33 -07004277 newview 0
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004278 }
4279}
4280
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004281proc editview {} {
4282 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004283 global viewname viewperm newviewname newviewopts
4284 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004285
4286 set top .gitkvedit-$curview
4287 if {[winfo exists $top]} {
Denton Liue2445882020-09-10 21:36:33 -07004288 raise $top
4289 return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004290 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004291 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004292 set newviewname($curview) $viewname($curview)
4293 set newviewopts($curview,perm) $viewperm($curview)
4294 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004295 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004296}
4297
4298proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004299 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004300 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004301
Pat Thoytsd93f1712009-04-17 01:24:35 +01004302 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004303 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004304 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004305
4306 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004307 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004308 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004309 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004310 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004311 pack $top.nl -in $top.nfr -side left -padx {0 5}
4312 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004313
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004314 # View options
4315 set cframe $top.nfr
4316 set cexpand 0
4317 set cnt 0
4318 foreach opt $known_view_options {
Denton Liue2445882020-09-10 21:36:33 -07004319 set id [lindex $opt 0]
4320 set type [lindex $opt 1]
4321 set flags [lindex $opt 2]
4322 set title [eval [lindex $opt 4]]
4323 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004324
Denton Liue2445882020-09-10 21:36:33 -07004325 if {$flags eq "+" || $flags eq "*"} {
4326 set cframe $top.fr$cnt
4327 incr cnt
4328 ${NS}::frame $cframe
4329 pack $cframe -in $top -fill x -pady 3 -padx 3
4330 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004331 } elseif {$flags eq ".." || $flags eq "*."} {
Denton Liue2445882020-09-10 21:36:33 -07004332 set cframe $top.fr$cnt
4333 incr cnt
4334 ${NS}::frame $cframe
4335 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4336 set cexpand [expr {$flags eq "*."}]
4337 } else {
4338 set lxpad 5
4339 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004340
Denton Liue2445882020-09-10 21:36:33 -07004341 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004342 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004343 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
Denton Liue2445882020-09-10 21:36:33 -07004344 } elseif {$type eq "b"} {
4345 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
4346 pack $cframe.c_$id -in $cframe -side left \
4347 -padx [list $lxpad 0] -expand $cexpand -anchor w
4348 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4349 regexp {^(.*_)} $id uselessvar button_id
4350 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
4351 pack $cframe.c_$id -in $cframe -side left \
4352 -padx [list $lxpad 0] -expand $cexpand -anchor w
4353 } elseif {[regexp {^t(\d+)$} $type type sz]} {
4354 ${NS}::label $cframe.l_$id -text $title
4355 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
4356 -textvariable newviewopts($n,$id)
4357 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4358 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4359 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
4360 ${NS}::label $cframe.l_$id -text $title
4361 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
4362 -textvariable newviewopts($n,$id)
4363 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4364 pack $cframe.e_$id -in $cframe -side top -fill x
4365 } elseif {$type eq "path"} {
4366 ${NS}::label $top.l -text $title
4367 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
4368 text $top.t -width 40 -height 5 -background $bgcolor
4369 if {[info exists viewfiles($n)]} {
4370 foreach f $viewfiles($n) {
4371 $top.t insert end $f
4372 $top.t insert end "\n"
4373 }
4374 $top.t delete {end - 1c} end
4375 $top.t mark set insert 0.0
4376 }
4377 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
4378 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004379 }
4380
Pat Thoytsd93f1712009-04-17 01:24:35 +01004381 ${NS}::frame $top.buts
4382 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4383 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4384 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004385 bind $top <Control-Return> [list newviewok $top $n]
4386 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004387 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004388 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004389 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4390 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004391 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4392 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004393 focus $top.t
4394}
4395
Paul Mackerras908c3582006-05-20 09:38:11 +10004396proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004397 set nmenu [$m index end]
4398 for {set i $first} {$i <= $nmenu} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07004399 if {[$m entrycget $i -command] eq $cmd} {
4400 eval $m $op $i $argv
4401 break
4402 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004403 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004404}
4405
4406proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004407 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004408
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004409 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004410 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004411}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004412
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004413proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004414 global nextviewnum newviewperm newviewname newishighlight
Max Kirillov995f7922015-03-04 05:58:16 +02004415 global viewname viewfiles viewperm viewchanged selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004416 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004417
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004418 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07004419 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004420 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07004421 error_popup "[mc "Error in commit selection arguments:"] $err" $top
4422 return
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004423 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004424 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004425 foreach f [split [$top.t get 0.0 end] "\n"] {
Denton Liue2445882020-09-10 21:36:33 -07004426 set ft [string trim $f]
4427 if {$ft ne {}} {
4428 lappend files $ft
4429 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004430 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004431 if {![info exists viewfiles($n)]} {
Denton Liue2445882020-09-10 21:36:33 -07004432 # creating a new view
4433 incr nextviewnum
4434 set viewname($n) $newviewname($n)
4435 set viewperm($n) $newviewopts($n,perm)
4436 set viewchanged($n) 1
4437 set viewfiles($n) $files
4438 set viewargs($n) $newargs
4439 set viewargscmd($n) $newviewopts($n,cmd)
4440 addviewmenu $n
4441 if {!$newishighlight} {
4442 run showview $n
4443 } else {
4444 run addvhighlight $n
4445 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004446 } else {
Denton Liue2445882020-09-10 21:36:33 -07004447 # editing an existing view
4448 set viewperm($n) $newviewopts($n,perm)
4449 set viewchanged($n) 1
4450 if {$newviewname($n) ne $viewname($n)} {
4451 set viewname($n) $newviewname($n)
4452 doviewmenu .bar.view 5 [list showview $n] \
4453 entryconf [list -label $viewname($n)]
4454 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4455 # entryconf [list -label $viewname($n) -value $viewname($n)]
4456 }
4457 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
4458 $newviewopts($n,cmd) ne $viewargscmd($n)} {
4459 set viewfiles($n) $files
4460 set viewargs($n) $newargs
4461 set viewargscmd($n) $newviewopts($n,cmd)
4462 if {$curview == $n} {
4463 run reloadcommits
4464 }
4465 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004466 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004467 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004468 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004469}
4470
4471proc delview {} {
Max Kirillov995f7922015-03-04 05:58:16 +02004472 global curview viewperm hlview selectedhlview viewchanged
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004473
4474 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004475 if {[info exists hlview] && $hlview == $curview} {
Denton Liue2445882020-09-10 21:36:33 -07004476 set selectedhlview [mc "None"]
4477 unset hlview
Paul Mackerras908c3582006-05-20 09:38:11 +10004478 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004479 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004480 set viewperm($curview) 0
Max Kirillov995f7922015-03-04 05:58:16 +02004481 set viewchanged($curview) 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004482 showview 0
4483}
4484
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004485proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004486 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004487
4488 .bar.view add radiobutton -label $viewname($n) \
Denton Liue2445882020-09-10 21:36:33 -07004489 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004490 #$viewhlmenu add radiobutton -label $viewname($n) \
4491 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004492}
4493
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004494proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004495 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004496 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004497 global colormap rowtextx nextcolor canvxmax
4498 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004499 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004500 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004501 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004502 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004503 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004504 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004505
4506 if {$n == $curview} return
4507 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004508 set ymax [lindex [$canv cget -scrollregion] 3]
4509 set span [$canv yview]
4510 set ytop [expr {[lindex $span 0] * $ymax}]
4511 set ybot [expr {[lindex $span 1] * $ymax}]
4512 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004513 if {$selectedline ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07004514 set selid $currentid
4515 set y [yc $selectedline]
4516 if {$ytop < $y && $y < $ybot} {
4517 set yscreen [expr {$y - $ytop}]
4518 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004519 } elseif {[info exists pending_select]} {
Denton Liue2445882020-09-10 21:36:33 -07004520 set selid $pending_select
4521 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004522 }
4523 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004524 normalline
Paul Mackerras009409f2015-05-02 20:53:36 +10004525 unset -nocomplain treediffs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004526 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004527 if {[info exists hlview] && $hlview == $n} {
Denton Liue2445882020-09-10 21:36:33 -07004528 unset hlview
4529 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004530 }
Paul Mackerras009409f2015-05-02 20:53:36 +10004531 unset -nocomplain commitinterest
4532 unset -nocomplain cached_commitrow
4533 unset -nocomplain ordertok
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004534
4535 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004536 set selectedview $n
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02004537 .bar.view entryconf [mca "&Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4538 .bar.view entryconf [mca "&Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004539
Paul Mackerrasdf904492007-08-29 22:03:07 +10004540 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004541 if {![info exists viewcomplete($n)]} {
Denton Liue2445882020-09-10 21:36:33 -07004542 getcommits $selid
4543 return
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004544 }
4545
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004546 set displayorder {}
4547 set parentlist {}
4548 set rowidlist {}
4549 set rowisopt {}
4550 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004551 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004552
Paul Mackerras009409f2015-05-02 20:53:36 +10004553 unset -nocomplain colormap
4554 unset -nocomplain rowtextx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004555 set nextcolor 0
4556 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004557 set curview $n
4558 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004559 setcanvscroll
4560 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004561 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004562 if {$selid ne {} && [commitinview $selid $n]} {
Denton Liue2445882020-09-10 21:36:33 -07004563 set row [rowofcommit $selid]
4564 # try to get the selected row in the same position on the screen
4565 set ymax [lindex [$canv cget -scrollregion] 3]
4566 set ytop [expr {[yc $row] - $yscreen}]
4567 if {$ytop < 0} {
4568 set ytop 0
4569 }
4570 set yf [expr {$ytop * 1.0 / $ymax}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004571 }
4572 allcanvs yview moveto $yf
4573 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004574 if {$row ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07004575 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004576 } elseif {!$viewcomplete($n)} {
Denton Liue2445882020-09-10 21:36:33 -07004577 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004578 } else {
Denton Liue2445882020-09-10 21:36:33 -07004579 reset_pending_select {}
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004580
Denton Liue2445882020-09-10 21:36:33 -07004581 if {[commitinview $pending_select $curview]} {
4582 selectline [rowofcommit $pending_select] 1
4583 } else {
4584 set row [first_real_row]
4585 if {$row < $numcommits} {
4586 selectline $row 0
4587 }
4588 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004589 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004590 if {!$viewcomplete($n)} {
Denton Liue2445882020-09-10 21:36:33 -07004591 if {$numcommits == 0} {
4592 show_status [mc "Reading commits..."]
4593 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004594 } elseif {$numcommits == 0} {
Denton Liue2445882020-09-10 21:36:33 -07004595 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004596 }
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004597 set_window_title
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004598}
4599
Paul Mackerras908c3582006-05-20 09:38:11 +10004600# Stuff relating to the highlighting facility
4601
Paul Mackerras476ca632008-01-07 22:16:31 +11004602proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004603 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004604
Paul Mackerras476ca632008-01-07 22:16:31 +11004605 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
Denton Liue2445882020-09-10 21:36:33 -07004606 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004607 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004608 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
Denton Liue2445882020-09-10 21:36:33 -07004609 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004610 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004611 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
Denton Liue2445882020-09-10 21:36:33 -07004612 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004613 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004614 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
Denton Liue2445882020-09-10 21:36:33 -07004615 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004616 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004617 return 0
4618}
4619
Paul Mackerras28593d32008-11-13 23:01:46 +11004620proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004621 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004622
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004623 # need_redisplay = 1 means the display is stale and about to be redrawn
4624 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004625 lappend boldids $id
4626 $canv itemconf $linehtag($id) -font $font
4627 if {[info exists currentid] && $id eq $currentid} {
Denton Liue2445882020-09-10 21:36:33 -07004628 $canv delete secsel
4629 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
4630 -outline {{}} -tags secsel \
4631 -fill [$canv cget -selectbackground]]
4632 $canv lower $t
Paul Mackerras908c3582006-05-20 09:38:11 +10004633 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004634 if {[info exists markedid] && $id eq $markedid} {
Denton Liue2445882020-09-10 21:36:33 -07004635 make_idmark $id
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004636 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004637}
4638
Paul Mackerras28593d32008-11-13 23:01:46 +11004639proc bolden_name {id font} {
4640 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004641
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004642 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004643 lappend boldnameids $id
4644 $canv2 itemconf $linentag($id) -font $font
4645 if {[info exists currentid] && $id eq $currentid} {
Denton Liue2445882020-09-10 21:36:33 -07004646 $canv2 delete secsel
4647 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
4648 -outline {{}} -tags secsel \
4649 -fill [$canv2 cget -selectbackground]]
4650 $canv2 lower $t
Paul Mackerras908c3582006-05-20 09:38:11 +10004651 }
4652}
4653
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004654proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004655 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004656
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004657 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004658 foreach id $boldids {
Denton Liue2445882020-09-10 21:36:33 -07004659 if {![ishighlighted $id]} {
4660 bolden $id mainfont
4661 } else {
4662 lappend stillbold $id
4663 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004664 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004665 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004666}
4667
4668proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004669 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004670
4671 if {[info exists hlview]} {
Denton Liue2445882020-09-10 21:36:33 -07004672 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004673 }
4674 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004675 if {$n != $curview && ![info exists viewcomplete($n)]} {
Denton Liue2445882020-09-10 21:36:33 -07004676 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004677 }
4678 set vhl_done $commitidx($hlview)
4679 if {$vhl_done > 0} {
Denton Liue2445882020-09-10 21:36:33 -07004680 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004681 }
4682}
4683
Paul Mackerras908c3582006-05-20 09:38:11 +10004684proc delvhighlight {} {
4685 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004686
4687 if {![info exists hlview]} return
4688 unset hlview
Paul Mackerras009409f2015-05-02 20:53:36 +10004689 unset -nocomplain vhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004690 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004691}
4692
Paul Mackerras908c3582006-05-20 09:38:11 +10004693proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004694 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004695
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004696 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004697 set vr [visiblerows]
4698 set r0 [lindex $vr 0]
4699 set r1 [lindex $vr 1]
4700 for {set i $vhl_done} {$i < $max} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07004701 set id [commitonrow $i $hlview]
4702 if {[commitinview $id $curview]} {
4703 set row [rowofcommit $id]
4704 if {$r0 <= $row && $row <= $r1} {
4705 if {![highlighted $row]} {
4706 bolden $id mainfontbold
4707 }
4708 set vhighlights($id) 1
4709 }
4710 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004711 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004712 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004713 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004714}
4715
4716proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004717 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004718
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004719 if {[commitinview $id $hlview]} {
Denton Liue2445882020-09-10 21:36:33 -07004720 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
4721 bolden $id mainfontbold
4722 }
4723 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004724 } else {
Denton Liue2445882020-09-10 21:36:33 -07004725 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004726 }
4727}
4728
Paul Mackerras687c8762007-09-22 12:49:33 +10004729proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004730 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004731 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004732
4733 if {[info exists filehighlight]} {
Denton Liue2445882020-09-10 21:36:33 -07004734 # delete previous highlights
4735 catch {close $filehighlight}
4736 unset filehighlight
4737 unset -nocomplain fhighlights
4738 unbolden
4739 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004740 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004741 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004742 after cancel do_file_hl $fh_serial
4743 incr fh_serial
4744 if {$highlight_files ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07004745 after 300 do_file_hl $fh_serial
Paul Mackerras908c3582006-05-20 09:38:11 +10004746 }
4747}
4748
Paul Mackerras687c8762007-09-22 12:49:33 +10004749proc gdttype_change {name ix op} {
4750 global gdttype highlight_files findstring findpattern
4751
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004752 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004753 if {$findstring ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07004754 if {$gdttype eq [mc "containing:"]} {
4755 if {$highlight_files ne {}} {
4756 set highlight_files {}
4757 hfiles_change
4758 }
4759 findcom_change
4760 } else {
4761 if {$findpattern ne {}} {
4762 set findpattern {}
4763 findcom_change
4764 }
4765 set highlight_files $findstring
4766 hfiles_change
4767 }
4768 drawvisible
Paul Mackerras687c8762007-09-22 12:49:33 +10004769 }
4770 # enable/disable findtype/findloc menus too
4771}
4772
4773proc find_change {name ix op} {
4774 global gdttype findstring highlight_files
4775
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004776 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004777 if {$gdttype eq [mc "containing:"]} {
Denton Liue2445882020-09-10 21:36:33 -07004778 findcom_change
Paul Mackerras687c8762007-09-22 12:49:33 +10004779 } else {
Denton Liue2445882020-09-10 21:36:33 -07004780 if {$highlight_files ne $findstring} {
4781 set highlight_files $findstring
4782 hfiles_change
4783 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004784 }
4785 drawvisible
4786}
4787
Paul Mackerras64b5f142007-10-04 22:19:24 +10004788proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004789 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004790 global findpattern findtype findstring gdttype
4791
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004792 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004793 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004794 foreach id $boldnameids {
Denton Liue2445882020-09-10 21:36:33 -07004795 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004796 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004797 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10004798 unset -nocomplain nhighlights
Paul Mackerras687c8762007-09-22 12:49:33 +10004799 unbolden
4800 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004801 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07004802 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004803 } elseif {$findtype eq [mc "Regexp"]} {
Denton Liue2445882020-09-10 21:36:33 -07004804 set findpattern $findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10004805 } else {
Denton Liue2445882020-09-10 21:36:33 -07004806 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4807 $findstring]
4808 set findpattern "*$e*"
Paul Mackerras687c8762007-09-22 12:49:33 +10004809 }
4810}
4811
Paul Mackerras63b79192006-05-20 21:31:52 +10004812proc makepatterns {l} {
4813 set ret {}
4814 foreach e $l {
Denton Liue2445882020-09-10 21:36:33 -07004815 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4816 if {[string index $ee end] eq "/"} {
4817 lappend ret "$ee*"
4818 } else {
4819 lappend ret $ee
4820 lappend ret "$ee/*"
4821 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004822 }
4823 return $ret
4824}
4825
Paul Mackerras908c3582006-05-20 09:38:11 +10004826proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004827 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004828 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004829
Christian Stimmingb007ee22007-11-07 18:44:35 +01004830 if {$gdttype eq [mc "touching paths:"]} {
Denton Liue2445882020-09-10 21:36:33 -07004831 # If "exact" match then convert backslashes to forward slashes.
4832 # Most useful to support Windows-flavoured file paths.
4833 if {$findtype eq [mc "Exact"]} {
4834 set highlight_files [string map {"\\" "/"} $highlight_files]
4835 }
4836 if {[catch {set paths [shellsplit $highlight_files]}]} return
4837 set highlight_paths [makepatterns $paths]
4838 highlight_filelist
4839 set relative_paths {}
4840 foreach path $paths {
4841 lappend relative_paths [file join $cdup $path]
4842 }
4843 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004844 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Denton Liue2445882020-09-10 21:36:33 -07004845 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004846 } elseif {$gdttype eq [mc "changing lines matching:"]} {
Denton Liue2445882020-09-10 21:36:33 -07004847 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004848 } else {
Denton Liue2445882020-09-10 21:36:33 -07004849 # must be "containing:", i.e. we're searching commit info
4850 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004851 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004852 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004853 set filehighlight [open $cmd r+]
4854 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004855 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004856 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004857 drawvisible
4858 flushhighlights
4859}
4860
4861proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004862 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004863
4864 if {[info exists filehighlight]} {
Denton Liue2445882020-09-10 21:36:33 -07004865 lappend fhl_list {}
4866 puts $filehighlight ""
4867 flush $filehighlight
Paul Mackerras908c3582006-05-20 09:38:11 +10004868 }
4869}
4870
4871proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004872 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004873
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004874 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004875 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004876 puts $filehighlight $id
4877}
4878
4879proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004880 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004881 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004882
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004883 if {![info exists filehighlight]} {
Denton Liue2445882020-09-10 21:36:33 -07004884 return 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004885 }
4886 set nr 0
4887 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07004888 set line [string trim $line]
4889 set i [lsearch -exact $fhl_list $line]
4890 if {$i < 0} continue
4891 for {set j 0} {$j < $i} {incr j} {
4892 set id [lindex $fhl_list $j]
4893 set fhighlights($id) 0
4894 }
4895 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4896 if {$line eq {}} continue
4897 if {![commitinview $line $curview]} continue
4898 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
4899 bolden $line mainfontbold
4900 }
4901 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004902 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004903 if {[eof $filehighlight]} {
Denton Liue2445882020-09-10 21:36:33 -07004904 # strange...
4905 puts "oops, git diff-tree died"
4906 catch {close $filehighlight}
4907 unset filehighlight
4908 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004909 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004910 if {[info exists find_dirn]} {
Denton Liue2445882020-09-10 21:36:33 -07004911 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004912 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004913 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004914}
4915
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004916proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004917 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004918
Christian Stimmingb007ee22007-11-07 18:44:35 +01004919 if {$findtype eq [mc "Regexp"]} {
Denton Liue2445882020-09-10 21:36:33 -07004920 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004921 } elseif {$findtype eq [mc "IgnCase"]} {
Denton Liue2445882020-09-10 21:36:33 -07004922 return [string match -nocase $findpattern $f]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004923 } else {
Denton Liue2445882020-09-10 21:36:33 -07004924 return [string match $findpattern $f]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004925 }
4926}
4927
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004928proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004929 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004930 global findloc
4931 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004932
4933 if {![info exists commitinfo($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07004934 getcommit $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004935 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004936 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004937 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004938 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004939 foreach f $info ty $fldtypes {
Denton Liue2445882020-09-10 21:36:33 -07004940 if {$ty eq ""} continue
4941 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
4942 [doesmatch $f]} {
4943 if {$ty eq [mc "Author"]} {
4944 set isbold 2
4945 break
4946 }
4947 set isbold 1
4948 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004949 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004950 if {$isbold && [info exists iddrawn($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07004951 if {![ishighlighted $id]} {
4952 bolden $id mainfontbold
4953 if {$isbold > 1} {
4954 bolden_name $id mainfontbold
4955 }
4956 }
4957 if {$markingmatches} {
4958 markrowmatches $row $id
4959 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004960 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004961 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004962}
4963
Paul Mackerras005a2f42007-07-26 22:36:39 +10004964proc markrowmatches {row id} {
4965 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004966
Paul Mackerras005a2f42007-07-26 22:36:39 +10004967 set headline [lindex $commitinfo($id) 0]
4968 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004969 $canv delete match$row
4970 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004971 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Denton Liue2445882020-09-10 21:36:33 -07004972 set m [findmatches $headline]
4973 if {$m ne {}} {
4974 markmatches $canv $row $headline $linehtag($id) $m \
4975 [$canv itemcget $linehtag($id) -font] $row
4976 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004977 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004978 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Denton Liue2445882020-09-10 21:36:33 -07004979 set m [findmatches $author]
4980 if {$m ne {}} {
4981 markmatches $canv2 $row $author $linentag($id) $m \
4982 [$canv2 itemcget $linentag($id) -font] $row
4983 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004984 }
4985}
4986
Paul Mackerras164ff272006-05-29 19:50:02 +10004987proc vrel_change {name ix op} {
4988 global highlight_related
4989
4990 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004991 if {$highlight_related ne [mc "None"]} {
Denton Liue2445882020-09-10 21:36:33 -07004992 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004993 }
4994}
4995
4996# prepare for testing whether commits are descendents or ancestors of a
4997proc rhighlight_sel {a} {
4998 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004999 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10005000
Paul Mackerras009409f2015-05-02 20:53:36 +10005001 unset -nocomplain descendent
Paul Mackerras164ff272006-05-29 19:50:02 +10005002 set desc_todo [list $a]
Paul Mackerras009409f2015-05-02 20:53:36 +10005003 unset -nocomplain ancestor
Paul Mackerras164ff272006-05-29 19:50:02 +10005004 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01005005 if {$highlight_related ne [mc "None"]} {
Denton Liue2445882020-09-10 21:36:33 -07005006 rhighlight_none
5007 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10005008 }
5009}
5010
5011proc rhighlight_none {} {
5012 global rhighlights
5013
Paul Mackerras009409f2015-05-02 20:53:36 +10005014 unset -nocomplain rhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10005015 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10005016}
5017
5018proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005019 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10005020
5021 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005022 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10005023 set todo $desc_todo
5024 set leftover {}
5025 set done 0
5026 for {set i 0} {$i < [llength $todo]} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07005027 set do [lindex $todo $i]
5028 if {[rowofcommit $do] < $la} {
5029 lappend leftover $do
5030 continue
5031 }
5032 foreach nk $children($v,$do) {
5033 if {![info exists descendent($nk)]} {
5034 set descendent($nk) 1
5035 lappend todo $nk
5036 if {$nk eq $a} {
5037 set done 1
5038 }
5039 }
5040 }
5041 if {$done} {
5042 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5043 return
5044 }
Paul Mackerras164ff272006-05-29 19:50:02 +10005045 }
5046 set descendent($a) 0
5047 set desc_todo $leftover
5048}
5049
5050proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005051 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10005052
5053 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005054 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10005055 set todo $anc_todo
5056 set leftover {}
5057 set done 0
5058 for {set i 0} {$i < [llength $todo]} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07005059 set do [lindex $todo $i]
5060 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
5061 lappend leftover $do
5062 continue
5063 }
5064 foreach np $parents($v,$do) {
5065 if {![info exists ancestor($np)]} {
5066 set ancestor($np) 1
5067 lappend todo $np
5068 if {$np eq $a} {
5069 set done 1
5070 }
5071 }
5072 }
5073 if {$done} {
5074 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5075 return
5076 }
Paul Mackerras164ff272006-05-29 19:50:02 +10005077 }
5078 set ancestor($a) 0
5079 set anc_todo $leftover
5080}
5081
5082proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005083 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005084 global selectedline ancestor
5085
Paul Mackerras94b4a692008-05-20 20:51:06 +10005086 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10005087 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01005088 if {$highlight_related eq [mc "Descendant"] ||
Denton Liue2445882020-09-10 21:36:33 -07005089 $highlight_related eq [mc "Not descendant"]} {
5090 if {![info exists descendent($id)]} {
5091 is_descendent $id
5092 }
5093 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
5094 set isbold 1
5095 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005096 } elseif {$highlight_related eq [mc "Ancestor"] ||
Denton Liue2445882020-09-10 21:36:33 -07005097 $highlight_related eq [mc "Not ancestor"]} {
5098 if {![info exists ancestor($id)]} {
5099 is_ancestor $id
5100 }
5101 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
5102 set isbold 1
5103 }
Paul Mackerras164ff272006-05-29 19:50:02 +10005104 }
5105 if {[info exists iddrawn($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07005106 if {$isbold && ![ishighlighted $id]} {
5107 bolden $id mainfontbold
5108 }
Paul Mackerras164ff272006-05-29 19:50:02 +10005109 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005110 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005111}
5112
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005113# Graph layout functions
5114
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005115proc shortids {ids} {
5116 set res {}
5117 foreach id $ids {
Denton Liue2445882020-09-10 21:36:33 -07005118 if {[llength $id] > 1} {
5119 lappend res [shortids $id]
5120 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
5121 lappend res [string range $id 0 7]
5122 } else {
5123 lappend res $id
5124 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005125 }
5126 return $res
5127}
5128
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005129proc ntimes {n o} {
5130 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10005131 set o [list $o]
5132 for {set mask 1} {$mask <= $n} {incr mask $mask} {
Denton Liue2445882020-09-10 21:36:33 -07005133 if {($n & $mask) != 0} {
5134 set ret [concat $ret $o]
5135 }
5136 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005137 }
5138 return $ret
5139}
5140
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005141proc ordertoken {id} {
5142 global ordertok curview varcid varcstart varctok curview parents children
5143 global nullid nullid2
5144
5145 if {[info exists ordertok($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07005146 return $ordertok($id)
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005147 }
5148 set origid $id
5149 set todo {}
5150 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07005151 if {[info exists varcid($curview,$id)]} {
5152 set a $varcid($curview,$id)
5153 set p [lindex $varcstart($curview) $a]
5154 } else {
5155 set p [lindex $children($curview,$id) 0]
5156 }
5157 if {[info exists ordertok($p)]} {
5158 set tok $ordertok($p)
5159 break
5160 }
5161 set id [first_real_child $curview,$p]
5162 if {$id eq {}} {
5163 # it's a root
5164 set tok [lindex $varctok($curview) $varcid($curview,$p)]
5165 break
5166 }
5167 if {[llength $parents($curview,$id)] == 1} {
5168 lappend todo [list $p {}]
5169 } else {
5170 set j [lsearch -exact $parents($curview,$id) $p]
5171 if {$j < 0} {
5172 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
5173 }
5174 lappend todo [list $p [strrep $j]]
5175 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005176 }
5177 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
Denton Liue2445882020-09-10 21:36:33 -07005178 set p [lindex $todo $i 0]
5179 append tok [lindex $todo $i 1]
5180 set ordertok($p) $tok
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005181 }
5182 set ordertok($origid) $tok
5183 return $tok
5184}
5185
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005186# Work out where id should go in idlist so that order-token
5187# values increase from left to right
5188proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005189 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005190 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005191 set i 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005192 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005193 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Denton Liue2445882020-09-10 21:36:33 -07005194 if {$i > [llength $idlist]} {
5195 set i [llength $idlist]
5196 }
5197 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
5198 incr i
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005199 } else {
Denton Liue2445882020-09-10 21:36:33 -07005200 if {$t > [ordertoken [lindex $idlist $i]]} {
5201 while {[incr i] < [llength $idlist] &&
5202 $t >= [ordertoken [lindex $idlist $i]]} {}
5203 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005204 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005205 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005206}
5207
5208proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005209 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005210 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005211 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005212 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005213
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005214 set numcommits 0
5215 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005216 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005217 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005218 set rowidlist {}
5219 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005220 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005221 set canvxmax [$canv cget -width]
Paul Mackerras009409f2015-05-02 20:53:36 +10005222 unset -nocomplain colormap
5223 unset -nocomplain rowtextx
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005224 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005225}
5226
5227proc setcanvscroll {} {
5228 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005229 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005230
5231 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5232 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5233 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5234 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005235 set lastscrollset [clock clicks -milliseconds]
5236 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005237}
5238
5239proc visiblerows {} {
5240 global canv numcommits linespc
5241
5242 set ymax [lindex [$canv cget -scrollregion] 3]
5243 if {$ymax eq {} || $ymax == 0} return
5244 set f [$canv yview]
5245 set y0 [expr {int([lindex $f 0] * $ymax)}]
5246 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5247 if {$r0 < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005248 set r0 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005249 }
5250 set y1 [expr {int([lindex $f 1] * $ymax)}]
5251 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5252 if {$r1 >= $numcommits} {
Denton Liue2445882020-09-10 21:36:33 -07005253 set r1 [expr {$numcommits - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005254 }
5255 return [list $r0 $r1]
5256}
5257
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005258proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005259 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005260 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005261 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005262
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005263 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
Denton Liue2445882020-09-10 21:36:33 -07005264 [clock clicks -milliseconds] - $lastscrollset > 500} {
5265 setcanvscroll
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005266 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005267 if {[info exists pending_select] &&
Denton Liue2445882020-09-10 21:36:33 -07005268 [commitinview $pending_select $curview]} {
5269 update
5270 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005271 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005272 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005273}
5274
Paul Mackerrascdc84292008-11-18 19:54:14 +11005275# With path limiting, we mightn't get the actual HEAD commit,
5276# so ask git rev-list what is the first ancestor of HEAD that
5277# touches a file in the path limit.
5278proc get_viewmainhead {view} {
5279 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005280
Paul Mackerrascdc84292008-11-18 19:54:14 +11005281 catch {
Denton Liue2445882020-09-10 21:36:33 -07005282 set rfd [open [concat | git rev-list -1 $mainheadid \
5283 -- $vfilelimit($view)] r]
5284 set j [reg_instance $rfd]
5285 lappend viewinstances($view) $j
5286 fconfigure $rfd -blocking 0
5287 filerun $rfd [list getviewhead $rfd $j $view]
5288 set viewmainheadid($curview) {}
Paul Mackerrascdc84292008-11-18 19:54:14 +11005289 }
5290}
5291
5292# git rev-list should give us just 1 line to use as viewmainheadid($view)
5293proc getviewhead {fd inst view} {
5294 global viewmainheadid commfd curview viewinstances showlocalchanges
5295
5296 set id {}
5297 if {[gets $fd line] < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005298 if {![eof $fd]} {
5299 return 1
5300 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005301 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
Denton Liue2445882020-09-10 21:36:33 -07005302 set id $line
Paul Mackerrascdc84292008-11-18 19:54:14 +11005303 }
5304 set viewmainheadid($view) $id
5305 close $fd
5306 unset commfd($inst)
5307 set i [lsearch -exact $viewinstances($view) $inst]
5308 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07005309 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +11005310 }
5311 if {$showlocalchanges && $id ne {} && $view == $curview} {
Denton Liue2445882020-09-10 21:36:33 -07005312 doshowlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +11005313 }
5314 return 0
5315}
5316
5317proc doshowlocalchanges {} {
5318 global curview viewmainheadid
5319
5320 if {$viewmainheadid($curview) eq {}} return
5321 if {[commitinview $viewmainheadid($curview) $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005322 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005323 } else {
Denton Liue2445882020-09-10 21:36:33 -07005324 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005325 }
5326}
5327
5328proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005329 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005330
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005331 if {[commitinview $nullid $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005332 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005333 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005334 if {[commitinview $nullid2 $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005335 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005336 }
5337 incr lserial
5338}
5339
Paul Mackerras8f489362007-07-13 19:49:37 +10005340# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005341proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005342 global lserial showlocalchanges vfilelimit curview
Jens Lehmann17f98362014-04-08 21:36:08 +02005343 global hasworktree git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005344
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005345 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005346 incr lserial
Jens Lehmann17f98362014-04-08 21:36:08 +02005347 if {[package vcompare $git_version "1.7.2"] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07005348 set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
Jens Lehmann17f98362014-04-08 21:36:08 +02005349 } else {
Denton Liue2445882020-09-10 21:36:33 -07005350 set cmd "|git diff-index --cached HEAD"
Jens Lehmann17f98362014-04-08 21:36:08 +02005351 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005352 if {$vfilelimit($curview) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07005353 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerrascdc84292008-11-18 19:54:14 +11005354 }
5355 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005356 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005357 set i [reg_instance $fd]
5358 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005359}
5360
Alexander Gavrilove439e092008-07-13 16:40:47 +04005361proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005362 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5363 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005364
Paul Mackerras8f489362007-07-13 19:49:37 +10005365 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005366 if {[gets $fd line] < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005367 if {![eof $fd]} {
5368 return 1
5369 }
5370 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005371 }
5372 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005373 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005374
Paul Mackerras24f7a662007-12-19 09:35:33 +11005375 if {$serial != $lserial} {
Denton Liue2445882020-09-10 21:36:33 -07005376 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005377 }
5378
Paul Mackerras24f7a662007-12-19 09:35:33 +11005379 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005380 set cmd "|git diff-files"
5381 if {$vfilelimit($curview) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07005382 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerrascdc84292008-11-18 19:54:14 +11005383 }
5384 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005385 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005386 set i [reg_instance $fd]
5387 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005388
5389 if {$isdiff && ![commitinview $nullid2 $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005390 # add the line for the changes in the index to the graph
5391 set hl [mc "Local changes checked in to index but not committed"]
5392 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5393 set commitdata($nullid2) "\n $hl\n"
5394 if {[commitinview $nullid $curview]} {
5395 removefakerow $nullid
5396 }
5397 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005398 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005399 if {[commitinview $nullid $curview]} {
5400 removefakerow $nullid
5401 }
5402 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005403 }
5404 return 0
5405}
5406
Alexander Gavrilove439e092008-07-13 16:40:47 +04005407proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005408 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005409 global commitinfo commitdata lserial
5410
5411 set isdiff 1
5412 if {[gets $fd line] < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005413 if {![eof $fd]} {
5414 return 1
5415 }
5416 set isdiff 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005417 }
5418 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005419 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005420
Paul Mackerras24f7a662007-12-19 09:35:33 +11005421 if {$serial != $lserial} {
Denton Liue2445882020-09-10 21:36:33 -07005422 return 0
Paul Mackerras24f7a662007-12-19 09:35:33 +11005423 }
5424
5425 if {$isdiff && ![commitinview $nullid $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005426 # add the line for the local diff to the graph
5427 set hl [mc "Local uncommitted changes, not checked in to index"]
5428 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5429 set commitdata($nullid) "\n $hl\n"
5430 if {[commitinview $nullid2 $curview]} {
5431 set p $nullid2
5432 } else {
5433 set p $viewmainheadid($curview)
5434 }
5435 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005436 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005437 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005438 }
5439 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005440}
5441
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005442proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005443 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005444
5445 if {[info exists children($curview,$id)]} {
Denton Liue2445882020-09-10 21:36:33 -07005446 foreach kid $children($curview,$id) {
5447 if {![commitinview $kid $curview]} {
5448 return -1
5449 }
5450 if {[rowofcommit $kid] > $row} {
5451 return [rowofcommit $kid]
5452 }
5453 }
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005454 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005455 if {[commitinview $id $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07005456 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005457 }
5458 return -1
5459}
5460
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005461proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005462 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005463
5464 set ret -1
5465 if {[info exists children($curview,$id)]} {
Denton Liue2445882020-09-10 21:36:33 -07005466 foreach kid $children($curview,$id) {
5467 if {![commitinview $kid $curview]} break
5468 if {[rowofcommit $kid] < $row} {
5469 set ret [rowofcommit $kid]
5470 }
5471 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005472 }
5473 return $ret
5474}
5475
Paul Mackerras03800812007-08-29 21:45:21 +10005476proc make_idlist {row} {
5477 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005478 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005479
5480 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5481 if {$r < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005482 set r 0
Paul Mackerras03800812007-08-29 21:45:21 +10005483 }
5484 set ra [expr {$row - $downarrowlen}]
5485 if {$ra < 0} {
Denton Liue2445882020-09-10 21:36:33 -07005486 set ra 0
Paul Mackerras03800812007-08-29 21:45:21 +10005487 }
5488 set rb [expr {$row + $uparrowlen}]
5489 if {$rb > $commitidx($curview)} {
Denton Liue2445882020-09-10 21:36:33 -07005490 set rb $commitidx($curview)
Paul Mackerras03800812007-08-29 21:45:21 +10005491 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005492 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005493 set ids {}
5494 for {} {$r < $ra} {incr r} {
Denton Liue2445882020-09-10 21:36:33 -07005495 set nextid [lindex $displayorder [expr {$r + 1}]]
5496 foreach p [lindex $parentlist $r] {
5497 if {$p eq $nextid} continue
5498 set rn [nextuse $p $r]
5499 if {$rn >= $row &&
5500 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
5501 lappend ids [list [ordertoken $p] $p]
5502 }
5503 }
Paul Mackerras03800812007-08-29 21:45:21 +10005504 }
5505 for {} {$r < $row} {incr r} {
Denton Liue2445882020-09-10 21:36:33 -07005506 set nextid [lindex $displayorder [expr {$r + 1}]]
5507 foreach p [lindex $parentlist $r] {
5508 if {$p eq $nextid} continue
5509 set rn [nextuse $p $r]
5510 if {$rn < 0 || $rn >= $row} {
5511 lappend ids [list [ordertoken $p] $p]
5512 }
5513 }
Paul Mackerras03800812007-08-29 21:45:21 +10005514 }
5515 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005516 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005517 while {$r < $rb} {
Denton Liue2445882020-09-10 21:36:33 -07005518 foreach p [lindex $parentlist $r] {
5519 set firstkid [lindex $children($curview,$p) 0]
5520 if {[rowofcommit $firstkid] < $row} {
5521 lappend ids [list [ordertoken $p] $p]
5522 }
5523 }
5524 incr r
5525 set id [lindex $displayorder $r]
5526 if {$id ne {}} {
5527 set firstkid [lindex $children($curview,$id) 0]
5528 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
5529 lappend ids [list [ordertoken $id] $id]
5530 }
5531 }
Paul Mackerras03800812007-08-29 21:45:21 +10005532 }
5533 set idlist {}
5534 foreach idx [lsort -unique $ids] {
Denton Liue2445882020-09-10 21:36:33 -07005535 lappend idlist [lindex $idx 1]
Paul Mackerras03800812007-08-29 21:45:21 +10005536 }
5537 return $idlist
5538}
5539
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005540proc rowsequal {a b} {
5541 while {[set i [lsearch -exact $a {}]] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07005542 set a [lreplace $a $i $i]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005543 }
5544 while {[set i [lsearch -exact $b {}]] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07005545 set b [lreplace $b $i $i]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005546 }
5547 return [expr {$a eq $b}]
5548}
5549
5550proc makeupline {id row rend col} {
5551 global rowidlist uparrowlen downarrowlen mingaplen
5552
5553 for {set r $rend} {1} {set r $rstart} {
Denton Liue2445882020-09-10 21:36:33 -07005554 set rstart [prevuse $id $r]
5555 if {$rstart < 0} return
5556 if {$rstart < $row} break
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005557 }
5558 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
Denton Liue2445882020-09-10 21:36:33 -07005559 set rstart [expr {$rend - $uparrowlen - 1}]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005560 }
5561 for {set r $rstart} {[incr r] <= $row} {} {
Denton Liue2445882020-09-10 21:36:33 -07005562 set idlist [lindex $rowidlist $r]
5563 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5564 set col [idcol $idlist $id $col]
5565 lset rowidlist $r [linsert $idlist $col $id]
5566 changedrow $r
5567 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005568 }
5569}
5570
Paul Mackerras03800812007-08-29 21:45:21 +10005571proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005572 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005573 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005574 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005575 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005576
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005577 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005578 set idlist {}
5579 if {$row > 0} {
Denton Liue2445882020-09-10 21:36:33 -07005580 set rm1 [expr {$row - 1}]
5581 foreach id [lindex $rowidlist $rm1] {
5582 if {$id ne {}} {
5583 lappend idlist $id
5584 }
5585 }
5586 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005587 }
Paul Mackerras03800812007-08-29 21:45:21 +10005588 for {} {$row < $endrow} {incr row} {
Denton Liue2445882020-09-10 21:36:33 -07005589 set rm1 [expr {$row - 1}]
5590 if {$rm1 < 0 || $idlist eq {}} {
5591 set idlist [make_idlist $row]
5592 set final 1
5593 } else {
5594 set id [lindex $displayorder $rm1]
5595 set col [lsearch -exact $idlist $id]
5596 set idlist [lreplace $idlist $col $col]
5597 foreach p [lindex $parentlist $rm1] {
5598 if {[lsearch -exact $idlist $p] < 0} {
5599 set col [idcol $idlist $p $col]
5600 set idlist [linsert $idlist $col $p]
5601 # if not the first child, we have to insert a line going up
5602 if {$id ne [lindex $children($curview,$p) 0]} {
5603 makeupline $p $rm1 $row $col
5604 }
5605 }
5606 }
5607 set id [lindex $displayorder $row]
5608 if {$row > $downarrowlen} {
5609 set termrow [expr {$row - $downarrowlen - 1}]
5610 foreach p [lindex $parentlist $termrow] {
5611 set i [lsearch -exact $idlist $p]
5612 if {$i < 0} continue
5613 set nr [nextuse $p $termrow]
5614 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5615 set idlist [lreplace $idlist $i $i]
5616 }
5617 }
5618 }
5619 set col [lsearch -exact $idlist $id]
5620 if {$col < 0} {
5621 set col [idcol $idlist $id]
5622 set idlist [linsert $idlist $col $id]
5623 if {$children($curview,$id) ne {}} {
5624 makeupline $id $rm1 $row $col
5625 }
5626 }
5627 set r [expr {$row + $uparrowlen - 1}]
5628 if {$r < $commitidx($curview)} {
5629 set x $col
5630 foreach p [lindex $parentlist $r] {
5631 if {[lsearch -exact $idlist $p] >= 0} continue
5632 set fk [lindex $children($curview,$p) 0]
5633 if {[rowofcommit $fk] < $row} {
5634 set x [idcol $idlist $p $x]
5635 set idlist [linsert $idlist $x $p]
5636 }
5637 }
5638 if {[incr r] < $commitidx($curview)} {
5639 set p [lindex $displayorder $r]
5640 if {[lsearch -exact $idlist $p] < 0} {
5641 set fk [lindex $children($curview,$p) 0]
5642 if {$fk ne {} && [rowofcommit $fk] < $row} {
5643 set x [idcol $idlist $p $x]
5644 set idlist [linsert $idlist $x $p]
5645 }
5646 }
5647 }
5648 }
5649 }
5650 if {$final && !$viewcomplete($curview) &&
5651 $row + $uparrowlen + $mingaplen + $downarrowlen
5652 >= $commitidx($curview)} {
5653 set final 0
5654 }
5655 set l [llength $rowidlist]
5656 if {$row == $l} {
5657 lappend rowidlist $idlist
5658 lappend rowisopt 0
5659 lappend rowfinal $final
5660 } elseif {$row < $l} {
5661 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
5662 lset rowidlist $row $idlist
5663 changedrow $row
5664 }
5665 lset rowfinal $row $final
5666 } else {
5667 set pad [ntimes [expr {$row - $l}] {}]
5668 set rowidlist [concat $rowidlist $pad]
5669 lappend rowidlist $idlist
5670 set rowfinal [concat $rowfinal $pad]
5671 lappend rowfinal $final
5672 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
5673 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005674 }
5675 return $row
5676}
5677
Paul Mackerras03800812007-08-29 21:45:21 +10005678proc changedrow {row} {
5679 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005680
Paul Mackerras03800812007-08-29 21:45:21 +10005681 set l [llength $rowisopt]
5682 if {$row < $l} {
Denton Liue2445882020-09-10 21:36:33 -07005683 lset rowisopt $row 0
5684 if {$row + 1 < $l} {
5685 lset rowisopt [expr {$row + 1}] 0
5686 if {$row + 2 < $l} {
5687 lset rowisopt [expr {$row + 2}] 0
5688 }
5689 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005690 }
Paul Mackerras03800812007-08-29 21:45:21 +10005691 set id [lindex $displayorder $row]
5692 if {[info exists iddrawn($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07005693 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005694 }
5695}
5696
5697proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005698 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005699
5700 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005701 set idlist [lindex $rowidlist $row]
5702 set bef [lrange $idlist 0 [expr {$col - 1}]]
5703 set aft [lrange $idlist $col end]
5704 set i [lsearch -exact $aft {}]
5705 if {$i > 0} {
Denton Liue2445882020-09-10 21:36:33 -07005706 set aft [lreplace $aft $i $i]
Paul Mackerrase341c062007-08-12 12:42:57 +10005707 }
5708 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005709 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005710}
5711
5712proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005713 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005714
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005715 if {$row < 1} {
Denton Liue2445882020-09-10 21:36:33 -07005716 set row 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005717 }
Paul Mackerras03800812007-08-29 21:45:21 +10005718 for {} {$row < $endrow} {incr row; set col 0} {
Denton Liue2445882020-09-10 21:36:33 -07005719 if {[lindex $rowisopt $row]} continue
5720 set haspad 0
5721 set y0 [expr {$row - 1}]
5722 set ym [expr {$row - 2}]
5723 set idlist [lindex $rowidlist $row]
5724 set previdlist [lindex $rowidlist $y0]
5725 if {$idlist eq {} || $previdlist eq {}} continue
5726 if {$ym >= 0} {
5727 set pprevidlist [lindex $rowidlist $ym]
5728 if {$pprevidlist eq {}} continue
5729 } else {
5730 set pprevidlist {}
5731 }
5732 set x0 -1
5733 set xm -1
5734 for {} {$col < [llength $idlist]} {incr col} {
5735 set id [lindex $idlist $col]
5736 if {[lindex $previdlist $col] eq $id} continue
5737 if {$id eq {}} {
5738 set haspad 1
5739 continue
5740 }
5741 set x0 [lsearch -exact $previdlist $id]
5742 if {$x0 < 0} continue
5743 set z [expr {$x0 - $col}]
5744 set isarrow 0
5745 set z0 {}
5746 if {$ym >= 0} {
5747 set xm [lsearch -exact $pprevidlist $id]
5748 if {$xm >= 0} {
5749 set z0 [expr {$xm - $x0}]
5750 }
5751 }
5752 if {$z0 eq {}} {
5753 # if row y0 is the first child of $id then it's not an arrow
5754 if {[lindex $children($curview,$id) 0] ne
5755 [lindex $displayorder $y0]} {
5756 set isarrow 1
5757 }
5758 }
5759 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5760 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5761 set isarrow 1
5762 }
5763 # Looking at lines from this row to the previous row,
5764 # make them go straight up if they end in an arrow on
5765 # the previous row; otherwise make them go straight up
5766 # or at 45 degrees.
5767 if {$z < -1 || ($z < 0 && $isarrow)} {
5768 # Line currently goes left too much;
5769 # insert pads in the previous row, then optimize it
5770 set npad [expr {-1 - $z + $isarrow}]
5771 insert_pad $y0 $x0 $npad
5772 if {$y0 > 0} {
5773 optimize_rows $y0 $x0 $row
5774 }
5775 set previdlist [lindex $rowidlist $y0]
5776 set x0 [lsearch -exact $previdlist $id]
5777 set z [expr {$x0 - $col}]
5778 if {$z0 ne {}} {
5779 set pprevidlist [lindex $rowidlist $ym]
5780 set xm [lsearch -exact $pprevidlist $id]
5781 set z0 [expr {$xm - $x0}]
5782 }
5783 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
5784 # Line currently goes right too much;
5785 # insert pads in this line
5786 set npad [expr {$z - 1 + $isarrow}]
5787 insert_pad $row $col $npad
5788 set idlist [lindex $rowidlist $row]
5789 incr col $npad
5790 set z [expr {$x0 - $col}]
5791 set haspad 1
5792 }
5793 if {$z0 eq {} && !$isarrow && $ym >= 0} {
5794 # this line links to its first child on row $row-2
5795 set id [lindex $displayorder $ym]
5796 set xc [lsearch -exact $pprevidlist $id]
5797 if {$xc >= 0} {
5798 set z0 [expr {$xc - $x0}]
5799 }
5800 }
5801 # avoid lines jigging left then immediately right
5802 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5803 insert_pad $y0 $x0 1
5804 incr x0
5805 optimize_rows $y0 $x0 $row
5806 set previdlist [lindex $rowidlist $y0]
5807 }
5808 }
5809 if {!$haspad} {
5810 # Find the first column that doesn't have a line going right
5811 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
5812 set id [lindex $idlist $col]
5813 if {$id eq {}} break
5814 set x0 [lsearch -exact $previdlist $id]
5815 if {$x0 < 0} {
5816 # check if this is the link to the first child
5817 set kid [lindex $displayorder $y0]
5818 if {[lindex $children($curview,$id) 0] eq $kid} {
5819 # it is, work out offset to child
5820 set x0 [lsearch -exact $previdlist $kid]
5821 }
5822 }
5823 if {$x0 <= $col} break
5824 }
5825 # Insert a pad at that column as long as it has a line and
5826 # isn't the last column
5827 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
5828 set idlist [linsert $idlist $col {}]
5829 lset rowidlist $row $idlist
5830 changedrow $row
5831 }
5832 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005833 }
5834}
5835
5836proc xc {row col} {
5837 global canvx0 linespc
5838 return [expr {$canvx0 + $col * $linespc}]
5839}
5840
5841proc yc {row} {
5842 global canvy0 linespc
5843 return [expr {$canvy0 + $row * $linespc}]
5844}
5845
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005846proc linewidth {id} {
5847 global thickerline lthickness
5848
5849 set wid $lthickness
5850 if {[info exists thickerline] && $id eq $thickerline} {
Denton Liue2445882020-09-10 21:36:33 -07005851 set wid [expr {2 * $lthickness}]
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005852 }
5853 return $wid
5854}
5855
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005856proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005857 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005858 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005859
Paul Mackerras92ed6662007-08-22 22:35:28 +10005860 set kids $children($curview,$id)
5861 if {$kids eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07005862 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005863 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005864 set ret {}
5865 lappend kids $id
5866 foreach child $kids {
Denton Liue2445882020-09-10 21:36:33 -07005867 if {![commitinview $child $curview]} break
5868 set row [rowofcommit $child]
5869 if {![info exists prev]} {
5870 lappend ret [expr {$row + 1}]
5871 } else {
5872 if {$row <= $prevrow} {
5873 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
5874 }
5875 # see if the line extends the whole way from prevrow to row
5876 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5877 [lsearch -exact [lindex $rowidlist \
5878 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5879 # it doesn't, see where it ends
5880 set r [expr {$prevrow + $downarrowlen}]
5881 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5882 while {[incr r -1] > $prevrow &&
5883 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5884 } else {
5885 while {[incr r] <= $row &&
5886 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5887 incr r -1
5888 }
5889 lappend ret $r
5890 # see where it starts up again
5891 set r [expr {$row - $uparrowlen}]
5892 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5893 while {[incr r] < $row &&
5894 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5895 } else {
5896 while {[incr r -1] >= $prevrow &&
5897 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5898 incr r
5899 }
5900 lappend ret $r
5901 }
5902 }
5903 if {$child eq $id} {
5904 lappend ret $row
5905 }
5906 set prev $child
5907 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005908 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005909 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005910}
5911
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005912proc drawlineseg {id row endrow arrowlow} {
5913 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005914 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005915
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005916 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5917 set le [expr {$row + 1}]
5918 set arrowhigh 1
5919 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07005920 set c [lsearch -exact [lindex $rowidlist $le] $id]
5921 if {$c < 0} {
5922 incr le -1
5923 break
5924 }
5925 lappend cols $c
5926 set x [lindex $displayorder $le]
5927 if {$x eq $id} {
5928 set arrowhigh 0
5929 break
5930 }
5931 if {[info exists iddrawn($x)] || $le == $endrow} {
5932 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5933 if {$c >= 0} {
5934 lappend cols $c
5935 set arrowhigh 0
5936 }
5937 break
5938 }
5939 incr le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005940 }
5941 if {$le <= $row} {
Denton Liue2445882020-09-10 21:36:33 -07005942 return $row
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005943 }
5944
5945 set lines {}
5946 set i 0
5947 set joinhigh 0
5948 if {[info exists linesegs($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07005949 set lines $linesegs($id)
5950 foreach li $lines {
5951 set r0 [lindex $li 0]
5952 if {$r0 > $row} {
5953 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5954 set joinhigh 1
5955 }
5956 break
5957 }
5958 incr i
5959 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005960 }
5961 set joinlow 0
5962 if {$i > 0} {
Denton Liue2445882020-09-10 21:36:33 -07005963 set li [lindex $lines [expr {$i-1}]]
5964 set r1 [lindex $li 1]
5965 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5966 set joinlow 1
5967 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005968 }
5969
5970 set x [lindex $cols [expr {$le - $row}]]
5971 set xp [lindex $cols [expr {$le - 1 - $row}]]
5972 set dir [expr {$xp - $x}]
5973 if {$joinhigh} {
Denton Liue2445882020-09-10 21:36:33 -07005974 set ith [lindex $lines $i 2]
5975 set coords [$canv coords $ith]
5976 set ah [$canv itemcget $ith -arrow]
5977 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5978 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5979 if {$x2 ne {} && $x - $x2 == $dir} {
5980 set coords [lrange $coords 0 end-2]
5981 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005982 } else {
Denton Liue2445882020-09-10 21:36:33 -07005983 set coords [list [xc $le $x] [yc $le]]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005984 }
5985 if {$joinlow} {
Denton Liue2445882020-09-10 21:36:33 -07005986 set itl [lindex $lines [expr {$i-1}] 2]
5987 set al [$canv itemcget $itl -arrow]
5988 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005989 } elseif {$arrowlow} {
Denton Liue2445882020-09-10 21:36:33 -07005990 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5991 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5992 set arrowlow 0
5993 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005994 }
5995 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5996 for {set y $le} {[incr y -1] > $row} {} {
Denton Liue2445882020-09-10 21:36:33 -07005997 set x $xp
5998 set xp [lindex $cols [expr {$y - 1 - $row}]]
5999 set ndir [expr {$xp - $x}]
6000 if {$dir != $ndir || $xp < 0} {
6001 lappend coords [xc $y $x] [yc $y]
6002 }
6003 set dir $ndir
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006004 }
6005 if {!$joinlow} {
Denton Liue2445882020-09-10 21:36:33 -07006006 if {$xp < 0} {
6007 # join parent line to first child
6008 set ch [lindex $displayorder $row]
6009 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
6010 if {$xc < 0} {
6011 puts "oops: drawlineseg: child $ch not on row $row"
6012 } elseif {$xc != $x} {
6013 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
6014 set d [expr {int(0.5 * $linespc)}]
6015 set x1 [xc $row $x]
6016 if {$xc < $x} {
6017 set x2 [expr {$x1 - $d}]
6018 } else {
6019 set x2 [expr {$x1 + $d}]
6020 }
6021 set y2 [yc $row]
6022 set y1 [expr {$y2 + $d}]
6023 lappend coords $x1 $y1 $x2 $y2
6024 } elseif {$xc < $x - 1} {
6025 lappend coords [xc $row [expr {$x-1}]] [yc $row]
6026 } elseif {$xc > $x + 1} {
6027 lappend coords [xc $row [expr {$x+1}]] [yc $row]
6028 }
6029 set x $xc
6030 }
6031 lappend coords [xc $row $x] [yc $row]
6032 } else {
6033 set xn [xc $row $xp]
6034 set yn [yc $row]
6035 lappend coords $xn $yn
6036 }
6037 if {!$joinhigh} {
6038 assigncolor $id
6039 set t [$canv create line $coords -width [linewidth $id] \
6040 -fill $colormap($id) -tags lines.$id -arrow $arrow]
6041 $canv lower $t
6042 bindline $t $id
6043 set lines [linsert $lines $i [list $row $le $t]]
6044 } else {
6045 $canv coords $ith $coords
6046 if {$arrow ne $ah} {
6047 $canv itemconf $ith -arrow $arrow
6048 }
6049 lset lines $i 0 $row
6050 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006051 } else {
Denton Liue2445882020-09-10 21:36:33 -07006052 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
6053 set ndir [expr {$xo - $xp}]
6054 set clow [$canv coords $itl]
6055 if {$dir == $ndir} {
6056 set clow [lrange $clow 2 end]
6057 }
6058 set coords [concat $coords $clow]
6059 if {!$joinhigh} {
6060 lset lines [expr {$i-1}] 1 $le
6061 } else {
6062 # coalesce two pieces
6063 $canv delete $ith
6064 set b [lindex $lines [expr {$i-1}] 0]
6065 set e [lindex $lines $i 1]
6066 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
6067 }
6068 $canv coords $itl $coords
6069 if {$arrow ne $al} {
6070 $canv itemconf $itl -arrow $arrow
6071 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006072 }
6073
6074 set linesegs($id) $lines
6075 return $le
6076}
6077
6078proc drawparentlinks {id row} {
6079 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10006080 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006081
6082 set rowids [lindex $rowidlist $row]
6083 set col [lsearch -exact $rowids $id]
6084 if {$col < 0} return
6085 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006086 set row2 [expr {$row + 1}]
6087 set x [xc $row $col]
6088 set y [yc $row]
6089 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10006090 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006091 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006092 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006093 # rmx = right-most X coord used
6094 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006095 foreach p $olds {
Denton Liue2445882020-09-10 21:36:33 -07006096 set i [lsearch -exact $ids $p]
6097 if {$i < 0} {
6098 puts "oops, parent $p of $id not in list"
6099 continue
6100 }
6101 set x2 [xc $row2 $i]
6102 if {$x2 > $rmx} {
6103 set rmx $x2
6104 }
6105 set j [lsearch -exact $rowids $p]
6106 if {$j < 0} {
6107 # drawlineseg will do this one for us
6108 continue
6109 }
6110 assigncolor $p
6111 # should handle duplicated parents here...
6112 set coords [list $x $y]
6113 if {$i != $col} {
6114 # if attaching to a vertical segment, draw a smaller
6115 # slant for visual distinctness
6116 if {$i == $j} {
6117 if {$i < $col} {
6118 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
6119 } else {
6120 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
6121 }
6122 } elseif {$i < $col && $i < $j} {
6123 # segment slants towards us already
6124 lappend coords [xc $row $j] $y
6125 } else {
6126 if {$i < $col - 1} {
6127 lappend coords [expr {$x2 + $linespc}] $y
6128 } elseif {$i > $col + 1} {
6129 lappend coords [expr {$x2 - $linespc}] $y
6130 }
6131 lappend coords $x2 $y2
6132 }
6133 } else {
6134 lappend coords $x2 $y2
6135 }
6136 set t [$canv create line $coords -width [linewidth $p] \
6137 -fill $colormap($p) -tags lines.$p]
6138 $canv lower $t
6139 bindline $t $p
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006140 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006141 if {$rmx > [lindex $idpos($id) 1]} {
Denton Liue2445882020-09-10 21:36:33 -07006142 lset idpos($id) 1 $rmx
6143 redrawtags $id
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006144 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006145}
6146
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006147proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006148 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006149
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006150 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006151}
6152
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006153proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006154 global linespc canv canv2 canv3 fgcolor curview
6155 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006156 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10006157 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006158 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05006159 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006160 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
6161 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006162
Linus Torvalds1407ade2008-02-09 14:02:07 -08006163 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006164 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006165 if {$id eq $nullid} {
Denton Liue2445882020-09-10 21:36:33 -07006166 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10006167 } elseif {$id eq $nullid2} {
Denton Liue2445882020-09-10 21:36:33 -07006168 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006169 } elseif {$id eq $mainheadid} {
Denton Liue2445882020-09-10 21:36:33 -07006170 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006171 } else {
Denton Liue2445882020-09-10 21:36:33 -07006172 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006173 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006174 set x [xc $row $col]
6175 set y [yc $row]
6176 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006177 if {$listed <= 2} {
Denton Liue2445882020-09-10 21:36:33 -07006178 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
6179 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
6180 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006181 } elseif {$listed == 3} {
Denton Liue2445882020-09-10 21:36:33 -07006182 # triangle pointing left for left-side commits
6183 set t [$canv create polygon \
6184 [expr {$x - $orad}] $y \
6185 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
6186 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
6187 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006188 } else {
Denton Liue2445882020-09-10 21:36:33 -07006189 # triangle pointing right for right-side commits
6190 set t [$canv create polygon \
6191 [expr {$x + $orad - 1}] $y \
6192 [expr {$x - $orad}] [expr {$y - $orad}] \
6193 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
6194 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006195 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006196 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006197 $canv raise $t
6198 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006199 set rmx [llength [lindex $rowidlist $row]]
6200 set olds [lindex $parentlist $row]
6201 if {$olds ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07006202 set nextids [lindex $rowidlist [expr {$row + 1}]]
6203 foreach p $olds {
6204 set i [lsearch -exact $nextids $p]
6205 if {$i > $rmx} {
6206 set rmx $i
6207 }
6208 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006209 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006210 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006211 set rowtextx($row) $xt
6212 set idpos($id) [list $x $xt $y]
6213 if {[info exists idtags($id)] || [info exists idheads($id)]
Denton Liue2445882020-09-10 21:36:33 -07006214 || [info exists idotherrefs($id)]} {
6215 set xt [drawtags $id $x $xt $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006216 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006217 if {[lindex $commitinfo($id) 6] > 0} {
Denton Liue2445882020-09-10 21:36:33 -07006218 set xt [drawnotesign $xt $y]
Raphael Zimmerer36242492011-04-19 22:37:09 +02006219 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006220 set headline [lindex $commitinfo($id) 0]
6221 set name [lindex $commitinfo($id) 1]
6222 set date [lindex $commitinfo($id) 2]
6223 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006224 set font mainfont
6225 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006226 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006227 if {$isbold > 0} {
Denton Liue2445882020-09-10 21:36:33 -07006228 lappend boldids $id
6229 set font mainfontbold
6230 if {$isbold > 1} {
6231 lappend boldnameids $id
6232 set nfont mainfontbold
6233 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006234 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006235 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
Denton Liue2445882020-09-10 21:36:33 -07006236 -text $headline -font $font -tags text]
Paul Mackerras28593d32008-11-13 23:01:46 +11006237 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6238 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
Denton Liue2445882020-09-10 21:36:33 -07006239 -text $name -font $nfont -tags text]
Paul Mackerras28593d32008-11-13 23:01:46 +11006240 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
Denton Liue2445882020-09-10 21:36:33 -07006241 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006242 if {$selectedline == $row} {
Denton Liue2445882020-09-10 21:36:33 -07006243 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006244 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006245 if {[info exists markedid] && $markedid eq $id} {
Denton Liue2445882020-09-10 21:36:33 -07006246 make_idmark $id
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006247 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006248 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006249 if {$xr > $canvxmax} {
Denton Liue2445882020-09-10 21:36:33 -07006250 set canvxmax $xr
6251 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006252 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006253}
6254
6255proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006256 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006257 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006258 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006259 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006260 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006261 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006262
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006263 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006264
6265 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006266 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006267 askvhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006268 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006269 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006270 askfilehighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006271 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006272 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006273 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006274 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006275 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006276 askrelhighlight $row $id
Paul Mackerras164ff272006-05-29 19:50:02 +10006277 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006278 if {![info exists iddrawn($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006279 set col [lsearch -exact [lindex $rowidlist $row] $id]
6280 if {$col < 0} {
6281 puts "oops, row $row id $id not in list"
6282 return
6283 }
6284 if {![info exists commitinfo($id)]} {
6285 getcommit $id
6286 }
6287 assigncolor $id
6288 drawcmittext $id $row $col
6289 set iddrawn($id) 1
6290 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006291 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006292 if {$markingmatches} {
Denton Liue2445882020-09-10 21:36:33 -07006293 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006294 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006295}
6296
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006297proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006298 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006299 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006300
6301 if {$row < 0} {
Denton Liue2445882020-09-10 21:36:33 -07006302 set row 0
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006303 }
6304 if {$endrow eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07006305 set endrow $row
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006306 }
6307 if {$endrow >= $numcommits} {
Denton Liue2445882020-09-10 21:36:33 -07006308 set endrow [expr {$numcommits - 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006309 }
6310
Paul Mackerras03800812007-08-29 21:45:21 +10006311 set rl1 [expr {$row - $downarrowlen - 3}]
6312 if {$rl1 < 0} {
Denton Liue2445882020-09-10 21:36:33 -07006313 set rl1 0
Paul Mackerras03800812007-08-29 21:45:21 +10006314 }
6315 set ro1 [expr {$row - 3}]
6316 if {$ro1 < 0} {
Denton Liue2445882020-09-10 21:36:33 -07006317 set ro1 0
Paul Mackerras03800812007-08-29 21:45:21 +10006318 }
6319 set r2 [expr {$endrow + $uparrowlen + 3}]
6320 if {$r2 > $numcommits} {
Denton Liue2445882020-09-10 21:36:33 -07006321 set r2 $numcommits
Paul Mackerras03800812007-08-29 21:45:21 +10006322 }
6323 for {set r $rl1} {$r < $r2} {incr r} {
Denton Liue2445882020-09-10 21:36:33 -07006324 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
6325 if {$rl1 < $r} {
6326 layoutrows $rl1 $r
6327 }
6328 set rl1 [expr {$r + 1}]
6329 }
Paul Mackerras03800812007-08-29 21:45:21 +10006330 }
6331 if {$rl1 < $r} {
Denton Liue2445882020-09-10 21:36:33 -07006332 layoutrows $rl1 $r
Paul Mackerras03800812007-08-29 21:45:21 +10006333 }
6334 optimize_rows $ro1 0 $r2
6335 if {$need_redisplay || $nrows_drawn > 2000} {
Denton Liue2445882020-09-10 21:36:33 -07006336 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006337 }
6338
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006339 # make the lines join to already-drawn rows either side
6340 set r [expr {$row - 1}]
6341 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
Denton Liue2445882020-09-10 21:36:33 -07006342 set r $row
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006343 }
6344 set er [expr {$endrow + 1}]
6345 if {$er >= $numcommits ||
Denton Liue2445882020-09-10 21:36:33 -07006346 ![info exists iddrawn([lindex $displayorder $er])]} {
6347 set er $endrow
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006348 }
6349 for {} {$r <= $er} {incr r} {
Denton Liue2445882020-09-10 21:36:33 -07006350 set id [lindex $displayorder $r]
6351 set wasdrawn [info exists iddrawn($id)]
6352 drawcmitrow $r
6353 if {$r == $er} break
6354 set nextid [lindex $displayorder [expr {$r + 1}]]
6355 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
6356 drawparentlinks $id $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006357
Denton Liue2445882020-09-10 21:36:33 -07006358 set rowids [lindex $rowidlist $r]
6359 foreach lid $rowids {
6360 if {$lid eq {}} continue
6361 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
6362 if {$lid eq $id} {
6363 # see if this is the first child of any of its parents
6364 foreach p [lindex $parentlist $r] {
6365 if {[lsearch -exact $rowids $p] < 0} {
6366 # make this line extend up to the child
6367 set lineend($p) [drawlineseg $p $r $er 0]
6368 }
6369 }
6370 } else {
6371 set lineend($lid) [drawlineseg $lid $r $er 1]
6372 }
6373 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006374 }
6375}
6376
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006377proc undolayout {row} {
6378 global uparrowlen mingaplen downarrowlen
6379 global rowidlist rowisopt rowfinal need_redisplay
6380
6381 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6382 if {$r < 0} {
Denton Liue2445882020-09-10 21:36:33 -07006383 set r 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006384 }
6385 if {[llength $rowidlist] > $r} {
Denton Liue2445882020-09-10 21:36:33 -07006386 incr r -1
6387 set rowidlist [lrange $rowidlist 0 $r]
6388 set rowfinal [lrange $rowfinal 0 $r]
6389 set rowisopt [lrange $rowisopt 0 $r]
6390 set need_redisplay 1
6391 run drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006392 }
6393}
6394
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006395proc drawvisible {} {
6396 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006397 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006398
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006399 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006400 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006401 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006402 set f0 [lindex $fs 0]
6403 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006404 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006405 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006406
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006407 if {[info exists targetid]} {
Denton Liue2445882020-09-10 21:36:33 -07006408 if {[commitinview $targetid $curview]} {
6409 set r [rowofcommit $targetid]
6410 if {$r != $targetrow} {
6411 # Fix up the scrollregion and change the scrolling position
6412 # now that our target row has moved.
6413 set diff [expr {($r - $targetrow) * $linespc}]
6414 set targetrow $r
6415 setcanvscroll
6416 set ymax [lindex [$canv cget -scrollregion] 3]
6417 incr y0 $diff
6418 incr y1 $diff
6419 set f0 [expr {$y0 / $ymax}]
6420 set f1 [expr {$y1 / $ymax}]
6421 allcanvs yview moveto $f0
6422 $cscroll set $f0 $f1
6423 set need_redisplay 1
6424 }
6425 } else {
6426 unset targetid
6427 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006428 }
6429
6430 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6431 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6432 if {$endrow >= $vrowmod($curview)} {
Denton Liue2445882020-09-10 21:36:33 -07006433 update_arcrows $curview
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006434 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006435 if {$selectedline ne {} &&
Denton Liue2445882020-09-10 21:36:33 -07006436 $row <= $selectedline && $selectedline <= $endrow} {
6437 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006438 } elseif {[info exists targetid]} {
Denton Liue2445882020-09-10 21:36:33 -07006439 set targetrow [expr {int(($row + $endrow) / 2)}]
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006440 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006441 if {[info exists targetrow]} {
Denton Liue2445882020-09-10 21:36:33 -07006442 if {$targetrow >= $numcommits} {
6443 set targetrow [expr {$numcommits - 1}]
6444 }
6445 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006446 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006447 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006448}
6449
6450proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006451 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006452 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006453 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006454
6455 allcanvs delete all
Paul Mackerras009409f2015-05-02 20:53:36 +10006456 unset -nocomplain iddrawn
6457 unset -nocomplain linesegs
6458 unset -nocomplain linehtag
6459 unset -nocomplain linentag
6460 unset -nocomplain linedtag
Paul Mackerras28593d32008-11-13 23:01:46 +11006461 set boldids {}
6462 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10006463 unset -nocomplain vhighlights
6464 unset -nocomplain fhighlights
6465 unset -nocomplain nhighlights
6466 unset -nocomplain rhighlights
Paul Mackerras03800812007-08-29 21:45:21 +10006467 set need_redisplay 0
6468 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006469}
6470
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006471proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006472 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006473
6474 set cross {}
6475 set ccross {}
6476 foreach {s e} [rowranges $id] {
Denton Liue2445882020-09-10 21:36:33 -07006477 if {$e >= $numcommits} {
6478 set e [expr {$numcommits - 1}]
6479 }
6480 if {$e <= $s} continue
6481 for {set row $e} {[incr row -1] >= $s} {} {
6482 set x [lsearch -exact [lindex $rowidlist $row] $id]
6483 if {$x < 0} break
6484 set olds [lindex $parentlist $row]
6485 set kid [lindex $displayorder $row]
6486 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6487 if {$kidx < 0} continue
6488 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6489 foreach p $olds {
6490 set px [lsearch -exact $nextrow $p]
6491 if {$px < 0} continue
6492 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6493 if {[lsearch -exact $ccross $p] >= 0} continue
6494 if {$x == $px + ($kidx < $px? -1: 1)} {
6495 lappend ccross $p
6496 } elseif {[lsearch -exact $cross $p] < 0} {
6497 lappend cross $p
6498 }
6499 }
6500 }
6501 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006502 }
6503 return [concat $ccross {{}} $cross]
6504}
6505
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006506proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006507 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006508 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006509
Paul Mackerras418c4c72006-02-07 09:10:18 +11006510 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006511 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006512 if {[info exists children($curview,$id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006513 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006514 } else {
Denton Liue2445882020-09-10 21:36:33 -07006515 set kids {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10006516 }
6517 if {[llength $kids] == 1} {
Denton Liue2445882020-09-10 21:36:33 -07006518 set child [lindex $kids 0]
6519 if {[info exists colormap($child)]
6520 && [llength $parents($curview,$child)] == 1} {
6521 set colormap($id) $colormap($child)
6522 return
6523 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006524 }
6525 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006526 set origbad {}
6527 foreach x [findcrossings $id] {
Denton Liue2445882020-09-10 21:36:33 -07006528 if {$x eq {}} {
6529 # delimiter between corner crossings and other crossings
6530 if {[llength $badcolors] >= $ncolors - 1} break
6531 set origbad $badcolors
6532 }
6533 if {[info exists colormap($x)]
6534 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6535 lappend badcolors $colormap($x)
6536 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006537 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006538 if {[llength $badcolors] >= $ncolors} {
Denton Liue2445882020-09-10 21:36:33 -07006539 set badcolors $origbad
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006540 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006541 set origbad $badcolors
6542 if {[llength $badcolors] < $ncolors - 1} {
Denton Liue2445882020-09-10 21:36:33 -07006543 foreach child $kids {
6544 if {[info exists colormap($child)]
6545 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6546 lappend badcolors $colormap($child)
6547 }
6548 foreach p $parents($curview,$child) {
6549 if {[info exists colormap($p)]
6550 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6551 lappend badcolors $colormap($p)
6552 }
6553 }
6554 }
6555 if {[llength $badcolors] >= $ncolors} {
6556 set badcolors $origbad
6557 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006558 }
6559 for {set i 0} {$i <= $ncolors} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07006560 set c [lindex $colors $nextcolor]
6561 if {[incr nextcolor] >= $ncolors} {
6562 set nextcolor 0
6563 }
6564 if {[lsearch -exact $badcolors $c]} break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006565 }
6566 set colormap($id) $c
6567}
6568
Paul Mackerrasa823a912005-06-21 10:01:38 +10006569proc bindline {t id} {
6570 global canv
6571
Paul Mackerrasa823a912005-06-21 10:01:38 +10006572 $canv bind $t <Enter> "lineenter %x %y $id"
6573 $canv bind $t <Motion> "linemotion %x %y $id"
6574 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006575 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006576}
6577
Paul Mackerras4399fe32013-01-03 10:10:31 +11006578proc graph_pane_width {} {
6579 global use_ttk
6580
6581 if {$use_ttk} {
Denton Liue2445882020-09-10 21:36:33 -07006582 set g [.tf.histframe.pwclist sashpos 0]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006583 } else {
Denton Liue2445882020-09-10 21:36:33 -07006584 set g [.tf.histframe.pwclist sash coord 0]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006585 }
6586 return [lindex $g 0]
6587}
6588
6589proc totalwidth {l font extra} {
6590 set tot 0
6591 foreach str $l {
Denton Liue2445882020-09-10 21:36:33 -07006592 set tot [expr {$tot + [font measure $font $str] + $extra}]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006593 }
6594 return $tot
6595}
6596
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006597proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006598 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006599 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006600 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006601 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6602 global tagbgcolor tagfgcolor tagoutlinecolor
6603 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006604
6605 set marks {}
6606 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006607 set nheads 0
Paul Mackerras4399fe32013-01-03 10:10:31 +11006608 set singletag 0
6609 set maxtags 3
6610 set maxtagpct 25
6611 set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
6612 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
6613 set extra [expr {$delta + $lthickness + $linespc}]
6614
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006615 if {[info exists idtags($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006616 set marks $idtags($id)
6617 set ntags [llength $marks]
6618 if {$ntags > $maxtags ||
6619 [totalwidth $marks mainfont $extra] > $maxwidth} {
6620 # show just a single "n tags..." tag
6621 set singletag 1
6622 if {$ntags == 1} {
6623 set marks [list "tag..."]
6624 } else {
6625 set marks [list [format "%d tags..." $ntags]]
6626 }
6627 set ntags 1
6628 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006629 }
6630 if {[info exists idheads($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006631 set marks [concat $marks $idheads($id)]
6632 set nheads [llength $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006633 }
6634 if {[info exists idotherrefs($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07006635 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006636 }
6637 if {$marks eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07006638 return $xt
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006639 }
6640
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006641 set yt [expr {$y1 - 0.5 * $linespc}]
6642 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006643 set xvals {}
6644 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006645 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006646 foreach tag $marks {
Denton Liue2445882020-09-10 21:36:33 -07006647 incr i
6648 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
6649 set wid [font measure mainfontbold $tag]
6650 } else {
6651 set wid [font measure mainfont $tag]
6652 }
6653 lappend xvals $xt
6654 lappend wvals $wid
6655 set xt [expr {$xt + $wid + $extra}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006656 }
6657 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Denton Liue2445882020-09-10 21:36:33 -07006658 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006659 $canv lower $t
6660 foreach tag $marks x $xvals wid $wvals {
Denton Liue2445882020-09-10 21:36:33 -07006661 set tag_quoted [string map {% %%} $tag]
6662 set xl [expr {$x + $delta}]
6663 set xr [expr {$x + $delta + $wid + $lthickness}]
6664 set font mainfont
6665 if {[incr ntags -1] >= 0} {
6666 # draw a tag
6667 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6668 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
6669 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6670 -tags tag.$id]
6671 if {$singletag} {
6672 set tagclick [list showtags $id 1]
6673 } else {
6674 set tagclick [list showtag $tag_quoted 1]
6675 }
6676 $canv bind $t <1> $tagclick
6677 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
6678 } else {
6679 # draw a head or other ref
6680 if {[incr nheads -1] >= 0} {
6681 set col $headbgcolor
6682 if {$tag eq $mainhead} {
6683 set font mainfontbold
6684 }
6685 } else {
6686 set col "#ddddff"
6687 }
6688 set xl [expr {$xl - $delta/2}]
6689 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
6690 -width 1 -outline black -fill $col -tags tag.$id
6691 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
6692 set rwid [font measure mainfont $remoteprefix]
6693 set xi [expr {$x + 1}]
6694 set yti [expr {$yt + 1}]
6695 set xri [expr {$x + $rwid}]
6696 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
6697 -width 0 -fill $remotebgcolor -tags tag.$id
6698 }
6699 }
6700 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
6701 -font $font -tags [list tag.$id text]]
6702 if {$ntags >= 0} {
6703 $canv bind $t <1> $tagclick
6704 } elseif {$nheads >= 0} {
6705 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
6706 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006707 }
6708 return $xt
6709}
6710
Raphael Zimmerer36242492011-04-19 22:37:09 +02006711proc drawnotesign {xt y} {
6712 global linespc canv fgcolor
6713
6714 set orad [expr {$linespc / 3}]
6715 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
Denton Liue2445882020-09-10 21:36:33 -07006716 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6717 -fill yellow -outline $fgcolor -width 1 -tags circle]
Raphael Zimmerer36242492011-04-19 22:37:09 +02006718 set xt [expr {$xt + $orad * 3}]
6719 return $xt
6720}
6721
Paul Mackerras8d858d12005-08-05 09:52:16 +10006722proc xcoord {i level ln} {
6723 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006724
Paul Mackerras8d858d12005-08-05 09:52:16 +10006725 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6726 if {$i > 0 && $i == $level} {
Denton Liue2445882020-09-10 21:36:33 -07006727 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10006728 } elseif {$i > $level} {
Denton Liue2445882020-09-10 21:36:33 -07006729 set x [expr {$x + $xspc2 - $xspc1($ln)}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10006730 }
6731 return $x
6732}
6733
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006734proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006735 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006736
6737 clear_display
Marc Branchaud9922c5a2015-04-07 11:51:51 -04006738 set_window_title
Paul Mackerras9c311b32007-10-04 22:27:13 +10006739 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Denton Liue2445882020-09-10 21:36:33 -07006740 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006741}
6742
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006743# Don't change the text pane cursor if it is currently the hand cursor,
6744# showing that we are over a sha1 ID link.
6745proc settextcursor {c} {
6746 global ctext curtextcursor
6747
6748 if {[$ctext cget -cursor] == $curtextcursor} {
Denton Liue2445882020-09-10 21:36:33 -07006749 $ctext config -cursor $c
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006750 }
6751 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006752}
6753
Paul Mackerrasa137a902007-10-23 21:12:49 +10006754proc nowbusy {what {name {}}} {
6755 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006756
6757 if {[array names isbusy] eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07006758 . config -cursor watch
6759 settextcursor watch
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006760 }
6761 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006762 set busyname($what) $name
6763 if {$name ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07006764 $statusw conf -text $name
Paul Mackerrasa137a902007-10-23 21:12:49 +10006765 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006766}
6767
6768proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006769 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006770
Paul Mackerrasa137a902007-10-23 21:12:49 +10006771 catch {
Denton Liue2445882020-09-10 21:36:33 -07006772 unset isbusy($what)
6773 if {$busyname($what) ne {} &&
6774 [$statusw cget -text] eq $busyname($what)} {
6775 $statusw conf -text {}
6776 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10006777 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006778 if {[array names isbusy] eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07006779 . config -cursor $maincursor
6780 settextcursor $textcursor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006781 }
6782}
6783
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006784proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006785 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006786 if {$findtype == [mc "Regexp"]} {
Denton Liue2445882020-09-10 21:36:33 -07006787 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006788 } else {
Denton Liue2445882020-09-10 21:36:33 -07006789 set fs $findstring
6790 if {$findtype == [mc "IgnCase"]} {
6791 set f [string tolower $f]
6792 set fs [string tolower $fs]
6793 }
6794 set matches {}
6795 set i 0
6796 set l [string length $fs]
6797 while {[set j [string first $fs $f $i]] >= 0} {
6798 lappend matches [list $j [expr {$j+$l-1}]]
6799 set i [expr {$j + $l}]
6800 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006801 }
6802 return $matches
6803}
6804
Paul Mackerrascca5d942007-10-27 21:16:56 +10006805proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006806 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006807 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006808
Paul Mackerrascca5d942007-10-27 21:16:56 +10006809 if {[info exists find_dirn]} {
Denton Liue2445882020-09-10 21:36:33 -07006810 if {$find_dirn == $dirn} return
6811 stopfinding
Paul Mackerrascca5d942007-10-27 21:16:56 +10006812 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006813 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006814 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006815 if {$selectedline eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07006816 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006817 } else {
Denton Liue2445882020-09-10 21:36:33 -07006818 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006819 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006820 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006821 nowbusy finding [mc "Searching"]
6822 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Denton Liue2445882020-09-10 21:36:33 -07006823 after cancel do_file_hl $fh_serial
6824 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006825 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006826 set find_dirn $dirn
6827 set findallowwrap $wrap
6828 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006829}
6830
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006831proc stopfinding {} {
6832 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006833
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006834 if {[info exists find_dirn]} {
Denton Liue2445882020-09-10 21:36:33 -07006835 unset find_dirn
6836 unset findcurline
6837 notbusy finding
6838 set fprogcoord 0
6839 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006840 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006841 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006842}
6843
6844proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006845 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006846 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006847 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006848 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006849
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006850 if {![info exists find_dirn]} {
Denton Liue2445882020-09-10 21:36:33 -07006851 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006852 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006853 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006854 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006855 set moretodo 0
6856 if {$find_dirn > 0} {
Denton Liue2445882020-09-10 21:36:33 -07006857 incr l
6858 if {$l >= $numcommits} {
6859 set l 0
6860 }
6861 if {$l <= $findstartline} {
6862 set lim [expr {$findstartline + 1}]
6863 } else {
6864 set lim $numcommits
6865 set moretodo $findallowwrap
6866 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006867 } else {
Denton Liue2445882020-09-10 21:36:33 -07006868 if {$l == 0} {
6869 set l $numcommits
6870 }
6871 incr l -1
6872 if {$l >= $findstartline} {
6873 set lim [expr {$findstartline - 1}]
6874 } else {
6875 set lim -1
6876 set moretodo $findallowwrap
6877 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006878 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006879 set n [expr {($lim - $l) * $find_dirn}]
6880 if {$n > 500} {
Denton Liue2445882020-09-10 21:36:33 -07006881 set n 500
6882 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006883 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006884 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
Denton Liue2445882020-09-10 21:36:33 -07006885 update_arcrows $curview
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006886 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006887 set found 0
6888 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006889 set ai [bsearch $vrownum($curview) $l]
6890 set a [lindex $varcorder($curview) $ai]
6891 set arow [lindex $vrownum($curview) $ai]
6892 set ids [lindex $varccommits($curview,$a)]
6893 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006894 if {$gdttype eq [mc "containing:"]} {
Denton Liue2445882020-09-10 21:36:33 -07006895 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
6896 if {$l < $arow || $l >= $arowend} {
6897 incr ai $find_dirn
6898 set a [lindex $varcorder($curview) $ai]
6899 set arow [lindex $vrownum($curview) $ai]
6900 set ids [lindex $varccommits($curview,$a)]
6901 set arowend [expr {$arow + [llength $ids]}]
6902 }
6903 set id [lindex $ids [expr {$l - $arow}]]
6904 # shouldn't happen unless git log doesn't give all the commits...
6905 if {![info exists commitdata($id)] ||
6906 ![doesmatch $commitdata($id)]} {
6907 continue
6908 }
6909 if {![info exists commitinfo($id)]} {
6910 getcommit $id
6911 }
6912 set info $commitinfo($id)
6913 foreach f $info ty $fldtypes {
6914 if {$ty eq ""} continue
6915 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
6916 [doesmatch $f]} {
6917 set found 1
6918 break
6919 }
6920 }
6921 if {$found} break
6922 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006923 } else {
Denton Liue2445882020-09-10 21:36:33 -07006924 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
6925 if {$l < $arow || $l >= $arowend} {
6926 incr ai $find_dirn
6927 set a [lindex $varcorder($curview) $ai]
6928 set arow [lindex $vrownum($curview) $ai]
6929 set ids [lindex $varccommits($curview,$a)]
6930 set arowend [expr {$arow + [llength $ids]}]
6931 }
6932 set id [lindex $ids [expr {$l - $arow}]]
6933 if {![info exists fhighlights($id)]} {
6934 # this sets fhighlights($id) to -1
6935 askfilehighlight $l $id
6936 }
6937 if {$fhighlights($id) > 0} {
6938 set found $domore
6939 break
6940 }
6941 if {$fhighlights($id) < 0} {
6942 if {$domore} {
6943 set domore 0
6944 set findcurline [expr {$l - $find_dirn}]
6945 }
6946 }
6947 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006948 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006949 if {$found || ($domore && !$moretodo)} {
Denton Liue2445882020-09-10 21:36:33 -07006950 unset findcurline
6951 unset find_dirn
6952 notbusy finding
6953 set fprogcoord 0
6954 adjustprogress
6955 if {$found} {
6956 findselectline $l
6957 } else {
6958 bell
6959 }
6960 return 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006961 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006962 if {!$domore} {
Denton Liue2445882020-09-10 21:36:33 -07006963 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006964 } else {
Denton Liue2445882020-09-10 21:36:33 -07006965 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006966 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006967 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006968 if {$n < 0} {
Denton Liue2445882020-09-10 21:36:33 -07006969 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006970 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006971 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6972 adjustprogress
6973 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006974}
6975
6976proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006977 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006978
Paul Mackerras8b39e042008-12-02 09:02:46 +11006979 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006980 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006981 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006982 if {$markingmatches &&
Denton Liue2445882020-09-10 21:36:33 -07006983 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
6984 # highlight the matches in the comments
6985 set f [$ctext get 1.0 $commentend]
6986 set matches [findmatches $f]
6987 foreach match $matches {
6988 set start [lindex $match 0]
6989 set end [expr {[lindex $match 1] + 1}]
6990 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6991 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006992 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006993 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006994}
6995
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006996# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006997proc markmatches {canv l str tag matches font row} {
6998 global selectedline
6999
Paul Mackerras98f350e2005-05-15 05:56:51 +00007000 set bbox [$canv bbox $tag]
7001 set x0 [lindex $bbox 0]
7002 set y0 [lindex $bbox 1]
7003 set y1 [lindex $bbox 3]
7004 foreach match $matches {
Denton Liue2445882020-09-10 21:36:33 -07007005 set start [lindex $match 0]
7006 set end [lindex $match 1]
7007 if {$start > $end} continue
7008 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
7009 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
7010 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
7011 [expr {$x0+$xlen+2}] $y1 \
7012 -outline {} -tags [list match$l matches] -fill yellow]
7013 $canv lower $t
7014 if {$row == $selectedline} {
7015 $canv raise $t secsel
7016 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00007017 }
7018}
7019
7020proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007021 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10007022
Paul Mackerras98f350e2005-05-15 05:56:51 +00007023 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10007024 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007025 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00007026}
7027
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007028proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007029 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007030 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00007031 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00007032 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00007033 set yfrac [lindex [$canv yview] 0]
7034 set y [expr {$y + $yfrac * $ymax}]
7035 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
7036 if {$l < 0} {
Denton Liue2445882020-09-10 21:36:33 -07007037 set l 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00007038 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007039 if {$w eq $canv} {
Denton Liue2445882020-09-10 21:36:33 -07007040 set xmax [lindex [$canv cget -scrollregion] 2]
7041 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
7042 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007043 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00007044 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007045 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007046}
7047
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007048proc commit_descriptor {p} {
7049 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10007050 if {![info exists commitinfo($p)]} {
Denton Liue2445882020-09-10 21:36:33 -07007051 getcommit $p
Paul Mackerrasb0934482006-05-15 09:56:08 +10007052 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007053 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10007054 if {[llength $commitinfo($p)] > 1} {
Denton Liue2445882020-09-10 21:36:33 -07007055 set l [lindex $commitinfo($p) 0]
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007056 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007057 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007058}
7059
Paul Mackerras106288c2005-08-19 23:11:39 +10007060# append some text to the ctext widget, and make any SHA1 ID
7061# that we know about be a clickable link.
Paul Mackerras3441de52019-08-27 08:12:34 +10007062# Also look for URLs of the form "http[s]://..." and make them web links.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007063proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007064 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10007065
7066 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007067 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007068 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10007069 foreach l $links {
Denton Liue2445882020-09-10 21:36:33 -07007070 set s [lindex $l 0]
7071 set e [lindex $l 1]
7072 set linkid [string range $text $s $e]
7073 incr e
7074 $ctext tag delete link$linknum
7075 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
7076 setlink $linkid link$linknum
7077 incr linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007078 }
Paul Mackerras3441de52019-08-27 08:12:34 +10007079 set wlinks [regexp -indices -all -inline -line \
Denton Liue2445882020-09-10 21:36:33 -07007080 {https?://[^[:space:]]+} $text]
Paul Mackerras3441de52019-08-27 08:12:34 +10007081 foreach l $wlinks {
Denton Liue2445882020-09-10 21:36:33 -07007082 set s2 [lindex $l 0]
7083 set e2 [lindex $l 1]
7084 set url [string range $text $s2 $e2]
7085 incr e2
7086 $ctext tag delete link$linknum
7087 $ctext tag add link$linknum "$start + $s2 c" "$start + $e2 c"
7088 setwlink $url link$linknum
7089 incr linknum
Paul Mackerras3441de52019-08-27 08:12:34 +10007090 }
Paul Mackerras97645682007-08-23 22:24:38 +10007091}
7092
7093proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007094 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007095 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10007096
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007097 if {[string range $id 0 1] eq "-g"} {
7098 set id [string range $id 2 end]
7099 }
7100
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007101 set known 0
7102 if {[string length $id] < 40} {
Denton Liue2445882020-09-10 21:36:33 -07007103 set matches [longid $id]
7104 if {[llength $matches] > 0} {
7105 if {[llength $matches] > 1} return
7106 set known 1
7107 set id [lindex $matches 0]
7108 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007109 } else {
Denton Liue2445882020-09-10 21:36:33 -07007110 set known [commitinview $id $curview]
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007111 }
7112 if {$known} {
Denton Liue2445882020-09-10 21:36:33 -07007113 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
7114 $ctext tag bind $lk <1> [list selbyid $id]
7115 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7116 $ctext tag bind $lk <Leave> {linkcursor %W -1}
Paul Mackerras97645682007-08-23 22:24:38 +10007117 } else {
Denton Liue2445882020-09-10 21:36:33 -07007118 lappend pendinglinks($id) $lk
7119 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10007120 }
7121}
7122
Paul Mackerras3441de52019-08-27 08:12:34 +10007123proc setwlink {url lk} {
7124 global ctext
7125 global linkfgcolor
7126 global web_browser
7127
7128 if {$web_browser eq {}} return
7129 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
7130 $ctext tag bind $lk <1> [list browseweb $url]
7131 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7132 $ctext tag bind $lk <Leave> {linkcursor %W -1}
7133}
7134
Paul Mackerras6f63fc12009-04-21 22:22:31 +10007135proc appendshortlink {id {pre {}} {post {}}} {
7136 global ctext linknum
7137
7138 $ctext insert end $pre
7139 $ctext tag delete link$linknum
7140 $ctext insert end [string range $id 0 7] link$linknum
7141 $ctext insert end $post
7142 setlink $id link$linknum
7143 incr linknum
7144}
7145
Paul Mackerras97645682007-08-23 22:24:38 +10007146proc makelink {id} {
7147 global pendinglinks
7148
7149 if {![info exists pendinglinks($id)]} return
7150 foreach lk $pendinglinks($id) {
Denton Liue2445882020-09-10 21:36:33 -07007151 setlink $id $lk
Paul Mackerras97645682007-08-23 22:24:38 +10007152 }
7153 unset pendinglinks($id)
7154}
7155
7156proc linkcursor {w inc} {
7157 global linkentercount curtextcursor
7158
7159 if {[incr linkentercount $inc] > 0} {
Denton Liue2445882020-09-10 21:36:33 -07007160 $w configure -cursor hand2
Paul Mackerras97645682007-08-23 22:24:38 +10007161 } else {
Denton Liue2445882020-09-10 21:36:33 -07007162 $w configure -cursor $curtextcursor
7163 if {$linkentercount < 0} {
7164 set linkentercount 0
7165 }
Paul Mackerras97645682007-08-23 22:24:38 +10007166 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007167}
7168
Paul Mackerras3441de52019-08-27 08:12:34 +10007169proc browseweb {url} {
7170 global web_browser
7171
7172 if {$web_browser eq {}} return
7173 # Use eval here in case $web_browser is a command plus some arguments
7174 if {[catch {eval exec $web_browser [list $url] &} err]} {
Denton Liue2445882020-09-10 21:36:33 -07007175 error_popup "[mc "Error starting web browser:"] $err"
Paul Mackerras3441de52019-08-27 08:12:34 +10007176 }
7177}
7178
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007179proc viewnextline {dir} {
7180 global canv linespc
7181
7182 $canv delete hover
7183 set ymax [lindex [$canv cget -scrollregion] 3]
7184 set wnow [$canv yview]
7185 set wtop [expr {[lindex $wnow 0] * $ymax}]
7186 set newtop [expr {$wtop + $dir * $linespc}]
7187 if {$newtop < 0} {
Denton Liue2445882020-09-10 21:36:33 -07007188 set newtop 0
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007189 } elseif {$newtop > $ymax} {
Denton Liue2445882020-09-10 21:36:33 -07007190 set newtop $ymax
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007191 }
7192 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7193}
7194
Paul Mackerrasef030b82006-06-04 11:50:38 +10007195# add a list of tag or branch names at position pos
7196# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10007197proc appendrefs {pos ids var} {
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007198 global ctext linknum curview $var maxrefs visiblerefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007199
Paul Mackerrasef030b82006-06-04 11:50:38 +10007200 if {[catch {$ctext index $pos}]} {
Denton Liue2445882020-09-10 21:36:33 -07007201 return 0
Paul Mackerrasef030b82006-06-04 11:50:38 +10007202 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007203 $ctext conf -state normal
7204 $ctext delete $pos "$pos lineend"
7205 set tags {}
7206 foreach id $ids {
Denton Liue2445882020-09-10 21:36:33 -07007207 foreach tag [set $var\($id\)] {
7208 lappend tags [list $tag $id]
7209 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007210 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007211
7212 set sep {}
7213 set tags [lsort -index 0 -decreasing $tags]
7214 set nutags 0
7215
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007216 if {[llength $tags] > $maxrefs} {
Denton Liue2445882020-09-10 21:36:33 -07007217 # If we are displaying heads, and there are too many,
7218 # see if there are some important heads to display.
7219 # Currently that are the current head and heads listed in $visiblerefs option
7220 set itags {}
7221 if {$var eq "idheads"} {
7222 set utags {}
7223 foreach ti $tags {
7224 set hname [lindex $ti 0]
7225 set id [lindex $ti 1]
7226 if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
7227 [llength $itags] < $maxrefs} {
7228 lappend itags $ti
7229 } else {
7230 lappend utags $ti
7231 }
7232 }
7233 set tags $utags
7234 }
7235 if {$itags ne {}} {
7236 set str [mc "and many more"]
7237 set sep " "
7238 } else {
7239 set str [mc "many"]
7240 }
7241 $ctext insert $pos "$str ([llength $tags])"
7242 set nutags [llength $tags]
7243 set tags $itags
Paul Mackerras386befb2013-01-02 15:25:29 +11007244 }
7245
7246 foreach ti $tags {
Denton Liue2445882020-09-10 21:36:33 -07007247 set id [lindex $ti 1]
7248 set lk link$linknum
7249 incr linknum
7250 $ctext tag delete $lk
7251 $ctext insert $pos $sep
7252 $ctext insert $pos [lindex $ti 0] $lk
7253 setlink $id $lk
7254 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007255 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11007256 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007257 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11007258 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007259}
7260
7261# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10007262proc dispneartags {delay} {
7263 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007264
Paul Mackerras94b4a692008-05-20 20:51:06 +10007265 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007266 after cancel dispnexttag
7267 if {$delay} {
Denton Liue2445882020-09-10 21:36:33 -07007268 after 200 dispnexttag
7269 set tagphase -1
Paul Mackerrase11f1232007-06-16 20:29:25 +10007270 } else {
Denton Liue2445882020-09-10 21:36:33 -07007271 after idle dispnexttag
7272 set tagphase 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10007273 }
7274}
7275
7276proc dispnexttag {} {
7277 global selectedline currentid showneartags tagphase ctext
7278
Paul Mackerras94b4a692008-05-20 20:51:06 +10007279 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007280 switch -- $tagphase {
Denton Liue2445882020-09-10 21:36:33 -07007281 0 {
7282 set dtags [desctags $currentid]
7283 if {$dtags ne {}} {
7284 appendrefs precedes $dtags idtags
7285 }
7286 }
7287 1 {
7288 set atags [anctags $currentid]
7289 if {$atags ne {}} {
7290 appendrefs follows $atags idtags
7291 }
7292 }
7293 2 {
7294 set dheads [descheads $currentid]
7295 if {$dheads ne {}} {
7296 if {[appendrefs branch $dheads idheads] > 1
7297 && [$ctext get "branch -3c"] eq "h"} {
7298 # turn "Branch" into "Branches"
7299 $ctext conf -state normal
7300 $ctext insert "branch -2c" "es"
7301 $ctext conf -state disabled
7302 }
7303 }
7304 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007305 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007306 if {[incr tagphase] <= 2} {
Denton Liue2445882020-09-10 21:36:33 -07007307 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007308 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007309}
7310
Paul Mackerras28593d32008-11-13 23:01:46 +11007311proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007312 global linehtag linentag linedtag canv canv2 canv3
7313
Paul Mackerras28593d32008-11-13 23:01:46 +11007314 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007315 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007316 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Denton Liue2445882020-09-10 21:36:33 -07007317 -tags secsel -fill [$canv cget -selectbackground]]
Paul Mackerras03800812007-08-29 21:45:21 +10007318 $canv lower $t
7319 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007320 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Denton Liue2445882020-09-10 21:36:33 -07007321 -tags secsel -fill [$canv2 cget -selectbackground]]
Paul Mackerras03800812007-08-29 21:45:21 +10007322 $canv2 lower $t
7323 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007324 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Denton Liue2445882020-09-10 21:36:33 -07007325 -tags secsel -fill [$canv3 cget -selectbackground]]
Paul Mackerras03800812007-08-29 21:45:21 +10007326 $canv3 lower $t
7327}
7328
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007329proc make_idmark {id} {
7330 global linehtag canv fgcolor
7331
7332 if {![info exists linehtag($id)]} return
7333 $canv delete markid
7334 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Denton Liue2445882020-09-10 21:36:33 -07007335 -tags markid -outline $fgcolor]
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007336 $canv raise $t
7337}
7338
Max Kirillov4135d362014-04-05 23:38:50 +03007339proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007340 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007341 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007342 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007343 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007344 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007345 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007346 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007347 global autoselect autosellen jump_to_here
Thomas Rast9403bd02013-11-16 18:37:43 +01007348 global vinlinediff
Paul Mackerrasd6982062005-08-06 22:06:06 +10007349
Paul Mackerras009409f2015-05-02 20:53:36 +10007350 unset -nocomplain pending_select
Paul Mackerras84ba7342005-06-17 00:12:26 +00007351 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007352 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007353 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007354 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007355 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007356 set id [commitonrow $l]
7357 set targetid $id
7358 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007359 set selectedline $l
7360 set currentid $id
7361 if {$lastscrollrows < $numcommits} {
Denton Liue2445882020-09-10 21:36:33 -07007362 setcanvscroll
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007363 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007364
Max Kirillov4135d362014-04-05 23:38:50 +03007365 if {$cmitmode ne "patch" && $switch_to_patch} {
7366 set cmitmode "patch"
7367 }
7368
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007369 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007370 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007371 set ytop [expr {$y - $linespc - 1}]
7372 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007373 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007374 set wtop [expr {[lindex $wnow 0] * $ymax}]
7375 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007376 set wh [expr {$wbot - $wtop}]
7377 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007378 if {$ytop < $wtop} {
Denton Liue2445882020-09-10 21:36:33 -07007379 if {$ybot < $wtop} {
7380 set newtop [expr {$y - $wh / 2.0}]
7381 } else {
7382 set newtop $ytop
7383 if {$newtop > $wtop - $linespc} {
7384 set newtop [expr {$wtop - $linespc}]
7385 }
7386 }
Paul Mackerras58422152005-05-19 10:56:42 +00007387 } elseif {$ybot > $wbot} {
Denton Liue2445882020-09-10 21:36:33 -07007388 if {$ytop > $wbot} {
7389 set newtop [expr {$y - $wh / 2.0}]
7390 } else {
7391 set newtop [expr {$ybot - $wh}]
7392 if {$newtop < $wtop + $linespc} {
7393 set newtop [expr {$wtop + $linespc}]
7394 }
7395 }
Paul Mackerras58422152005-05-19 10:56:42 +00007396 }
7397 if {$newtop != $wtop} {
Denton Liue2445882020-09-10 21:36:33 -07007398 if {$newtop < 0} {
7399 set newtop 0
7400 }
7401 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7402 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007403 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007404
Paul Mackerras28593d32008-11-13 23:01:46 +11007405 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007406
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007407 if {$isnew} {
Denton Liue2445882020-09-10 21:36:33 -07007408 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007409 }
7410
Paul Mackerras98f350e2005-05-15 05:56:51 +00007411 $sha1entry delete 0 end
7412 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007413 if {$autoselect} {
Denton Liue2445882020-09-10 21:36:33 -07007414 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007415 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007416 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007417
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007418 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007419 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007420 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007421 if {![info exists commitinfo($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07007422 getcommit $id
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007423 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007424 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007425 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007426 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007427 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007428 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007429 if {[info exists idtags($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07007430 $ctext insert end [mc "Tags:"]
7431 foreach tag $idtags($id) {
7432 $ctext insert end " $tag"
7433 }
7434 $ctext insert end "\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007435 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007436
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007437 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007438 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007439 if {[llength $olds] > 1} {
Denton Liue2445882020-09-10 21:36:33 -07007440 set np 0
7441 foreach p $olds {
7442 if {$np >= $mergemax} {
7443 set tag mmax
7444 } else {
7445 set tag m$np
7446 }
7447 $ctext insert end "[mc "Parent"]: " $tag
7448 appendwithlinks [commit_descriptor $p] {}
7449 incr np
7450 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007451 } else {
Denton Liue2445882020-09-10 21:36:33 -07007452 foreach p $olds {
7453 append headers "[mc "Parent"]: [commit_descriptor $p]"
7454 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007455 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007456
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007457 foreach c $children($curview,$id) {
Denton Liue2445882020-09-10 21:36:33 -07007458 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007459 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007460
7461 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007462 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007463 if {$showneartags} {
Denton Liue2445882020-09-10 21:36:33 -07007464 if {![info exists allcommits]} {
7465 getallcommits
7466 }
7467 $ctext insert end "[mc "Branch"]: "
7468 $ctext mark set branch "end -1c"
7469 $ctext mark gravity branch left
7470 $ctext insert end "\n[mc "Follows"]: "
7471 $ctext mark set follows "end -1c"
7472 $ctext mark gravity follows left
7473 $ctext insert end "\n[mc "Precedes"]: "
7474 $ctext mark set precedes "end -1c"
7475 $ctext mark gravity precedes left
7476 $ctext insert end "\n"
7477 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007478 }
7479 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007480 set comment [lindex $info 5]
7481 if {[string first "\r" $comment] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07007482 set comment [string map {"\r" "\n "} $comment]
Paul Mackerras43c25072006-09-27 10:56:02 +10007483 }
7484 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007485
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007486 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007487 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007488 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007489
Paul Mackerras8a897742008-10-27 21:36:25 +11007490 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007491 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007492 if {$cmitmode eq "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07007493 gettree $id
Thomas Rast9403bd02013-11-16 18:37:43 +01007494 } elseif {$vinlinediff($curview) == 1} {
Denton Liue2445882020-09-10 21:36:33 -07007495 showinlinediff $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007496 } elseif {[llength $olds] <= 1} {
Denton Liue2445882020-09-10 21:36:33 -07007497 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007498 } else {
Denton Liue2445882020-09-10 21:36:33 -07007499 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007500 }
7501}
7502
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007503proc selfirstline {} {
7504 unmarkmatches
7505 selectline 0 1
7506}
7507
7508proc sellastline {} {
7509 global numcommits
7510 unmarkmatches
7511 set l [expr {$numcommits - 1}]
7512 selectline $l 1
7513}
7514
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007515proc selnextline {dir} {
7516 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007517 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007518 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007519 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007520 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007521 selectline $l 1
7522}
7523
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007524proc selnextpage {dir} {
7525 global canv linespc selectedline numcommits
7526
7527 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7528 if {$lpp < 1} {
Denton Liue2445882020-09-10 21:36:33 -07007529 set lpp 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007530 }
7531 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007532 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007533 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007534 set l [expr {$selectedline + $dir * $lpp}]
7535 if {$l < 0} {
Denton Liue2445882020-09-10 21:36:33 -07007536 set l 0
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007537 } elseif {$l >= $numcommits} {
7538 set l [expr $numcommits - 1]
7539 }
7540 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007541 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007542}
7543
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007544proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007545 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007546
Paul Mackerras94b4a692008-05-20 20:51:06 +10007547 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +10007548 unset -nocomplain currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007549 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007550 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007551}
7552
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007553proc reselectline {} {
7554 global selectedline
7555
Paul Mackerras94b4a692008-05-20 20:51:06 +10007556 if {$selectedline ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07007557 selectline $selectedline 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007558 }
7559}
7560
Paul Mackerras354af6b2008-11-23 13:14:23 +11007561proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007562 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007563
Paul Mackerras354af6b2008-11-23 13:14:23 +11007564 unset_posvars
7565 save_position
7566 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007567 if {$historyindex > 0
Denton Liue2445882020-09-10 21:36:33 -07007568 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
7569 return
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007570 }
7571
7572 if {$historyindex < [llength $history]} {
Denton Liue2445882020-09-10 21:36:33 -07007573 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007574 } else {
Denton Liue2445882020-09-10 21:36:33 -07007575 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007576 }
7577 incr historyindex
7578 if {$historyindex > 1} {
Denton Liue2445882020-09-10 21:36:33 -07007579 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007580 } else {
Denton Liue2445882020-09-10 21:36:33 -07007581 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007582 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007583 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007584}
7585
Paul Mackerras354af6b2008-11-23 13:14:23 +11007586# save the scrolling position of the diff display pane
7587proc save_position {} {
7588 global historyindex history
7589
7590 if {$historyindex < 1} return
7591 set hi [expr {$historyindex - 1}]
7592 set fn [lindex $history $hi 2]
7593 if {$fn ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07007594 lset history $hi 3 [eval $fn]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007595 }
7596}
7597
7598proc unset_posvars {} {
7599 global last_posvars
7600
7601 if {[info exists last_posvars]} {
Denton Liue2445882020-09-10 21:36:33 -07007602 foreach {var val} $last_posvars {
7603 global $var
7604 unset -nocomplain $var
7605 }
7606 unset last_posvars
Paul Mackerras354af6b2008-11-23 13:14:23 +11007607 }
7608}
7609
Paul Mackerras2516dae2006-04-21 10:35:31 +10007610proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007611 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007612
7613 set view [lindex $elt 0]
7614 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007615 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007616 if {$curview != $view} {
Denton Liue2445882020-09-10 21:36:33 -07007617 showview $view
Paul Mackerras2516dae2006-04-21 10:35:31 +10007618 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007619 unset_posvars
7620 foreach {var val} $pv {
Denton Liue2445882020-09-10 21:36:33 -07007621 global $var
7622 set $var $val
Paul Mackerras354af6b2008-11-23 13:14:23 +11007623 }
7624 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007625 eval $cmd
7626}
7627
Paul Mackerrasd6982062005-08-06 22:06:06 +10007628proc goback {} {
7629 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007630 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007631
7632 if {$historyindex > 1} {
Denton Liue2445882020-09-10 21:36:33 -07007633 save_position
7634 incr historyindex -1
7635 godo [lindex $history [expr {$historyindex - 1}]]
7636 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007637 }
7638 if {$historyindex <= 1} {
Denton Liue2445882020-09-10 21:36:33 -07007639 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007640 }
7641}
7642
7643proc goforw {} {
7644 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007645 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007646
7647 if {$historyindex < [llength $history]} {
Denton Liue2445882020-09-10 21:36:33 -07007648 save_position
7649 set cmd [lindex $history $historyindex]
7650 incr historyindex
7651 godo $cmd
7652 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007653 }
7654 if {$historyindex >= [llength $history]} {
Denton Liue2445882020-09-10 21:36:33 -07007655 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007656 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007657}
7658
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007659proc go_to_parent {i} {
7660 global parents curview targetid
7661 set ps $parents($curview,$targetid)
7662 if {[llength $ps] >= $i} {
Denton Liue2445882020-09-10 21:36:33 -07007663 selbyid [lindex $ps [expr $i - 1]]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007664 }
7665}
7666
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007667proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007668 global treefilelist treeidlist diffids diffmergeid treepending
7669 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007670
7671 set diffids $id
Paul Mackerras009409f2015-05-02 20:53:36 +10007672 unset -nocomplain diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007673 if {![info exists treefilelist($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07007674 if {![info exists treepending]} {
7675 if {$id eq $nullid} {
7676 set cmd [list | git ls-files]
7677 } elseif {$id eq $nullid2} {
7678 set cmd [list | git ls-files --stage -t]
7679 } else {
7680 set cmd [list | git ls-tree -r $id]
7681 }
7682 if {[catch {set gtf [open $cmd r]}]} {
7683 return
7684 }
7685 set treepending $id
7686 set treefilelist($id) {}
7687 set treeidlist($id) {}
7688 fconfigure $gtf -blocking 0 -encoding binary
7689 filerun $gtf [list gettreeline $gtf $id]
7690 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007691 } else {
Denton Liue2445882020-09-10 21:36:33 -07007692 setfilelist $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007693 }
7694}
7695
7696proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007697 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007698
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007699 set nl 0
7700 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07007701 if {$diffids eq $nullid} {
7702 set fname $line
7703 } else {
7704 set i [string first "\t" $line]
7705 if {$i < 0} continue
7706 set fname [string range $line [expr {$i+1}] end]
7707 set line [string range $line 0 [expr {$i-1}]]
7708 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7709 set sha1 [lindex $line 2]
7710 lappend treeidlist($id) $sha1
7711 }
7712 if {[string index $fname 0] eq "\""} {
7713 set fname [lindex $fname 0]
7714 }
7715 set fname [encoding convertfrom $fname]
7716 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007717 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007718 if {![eof $gtf]} {
Denton Liue2445882020-09-10 21:36:33 -07007719 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007720 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007721 close $gtf
7722 unset treepending
7723 if {$cmitmode ne "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07007724 if {![info exists diffmergeid]} {
7725 gettreediffs $diffids
7726 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007727 } elseif {$id ne $diffids} {
Denton Liue2445882020-09-10 21:36:33 -07007728 gettree $diffids
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007729 } else {
Denton Liue2445882020-09-10 21:36:33 -07007730 setfilelist $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007731 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007732 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007733}
7734
7735proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007736 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007737 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007738 global ctext commentend
7739
7740 set i [lsearch -exact $treefilelist($diffids) $f]
7741 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -07007742 puts "oops, $f not in list for id $diffids"
7743 return
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007744 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007745 if {$diffids eq $nullid} {
Denton Liue2445882020-09-10 21:36:33 -07007746 if {[catch {set bf [open $f r]} err]} {
7747 puts "oops, can't read $f: $err"
7748 return
7749 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007750 } else {
Denton Liue2445882020-09-10 21:36:33 -07007751 set blob [lindex $treeidlist($diffids) $i]
7752 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7753 puts "oops, error reading blob $blob: $err"
7754 return
7755 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007756 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007757 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007758 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007759 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007760 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007761 lappend ctext_file_names $f
7762 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007763 $ctext insert end "\n"
7764 $ctext insert end "$f\n" filesep
7765 $ctext config -state disabled
7766 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007767 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007768}
7769
7770proc getblobline {bf id} {
7771 global diffids cmitmode ctext
7772
7773 if {$id ne $diffids || $cmitmode ne "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07007774 catch {close $bf}
7775 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007776 }
7777 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007778 set nl 0
7779 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07007780 $ctext insert end "$line\n"
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007781 }
7782 if {[eof $bf]} {
Denton Liue2445882020-09-10 21:36:33 -07007783 global jump_to_here ctext_file_names commentend
Paul Mackerras8a897742008-10-27 21:36:25 +11007784
Denton Liue2445882020-09-10 21:36:33 -07007785 # delete last newline
7786 $ctext delete "end - 2c" "end - 1c"
7787 close $bf
7788 if {$jump_to_here ne {} &&
7789 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7790 set lnum [expr {[lindex $jump_to_here 1] +
7791 [lindex [split $commentend .] 0]}]
7792 mark_ctext_line $lnum
7793 }
7794 $ctext config -state disabled
7795 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007796 }
7797 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007798 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007799}
7800
Paul Mackerras8a897742008-10-27 21:36:25 +11007801proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007802 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007803
7804 $ctext tag delete omark
7805 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007806 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007807 $ctext see $lnum.0
7808}
7809
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007810proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007811 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007812 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007813 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007814
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007815 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007816 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007817 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007818 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007819 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007820 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007821}
7822
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007823proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007824 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007825
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007826 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007827 set diffids $ids
Paul Mackerras009409f2015-05-02 20:53:36 +10007828 unset -nocomplain diffmergeid
Paul Mackerras8f489362007-07-13 19:49:37 +10007829 if {![info exists treediffs($ids)] ||
Denton Liue2445882020-09-10 21:36:33 -07007830 [lsearch -exact $ids $nullid] >= 0 ||
7831 [lsearch -exact $ids $nullid2] >= 0} {
7832 if {![info exists treepending]} {
7833 gettreediffs $ids
7834 }
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007835 } else {
Denton Liue2445882020-09-10 21:36:33 -07007836 addtocflist $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007837 }
7838}
7839
Thomas Rast9403bd02013-11-16 18:37:43 +01007840proc showinlinediff {ids} {
7841 global commitinfo commitdata ctext
7842 global treediffs
7843
7844 set info $commitinfo($ids)
7845 set diff [lindex $info 7]
7846 set difflines [split $diff "\n"]
7847
7848 initblobdiffvars
7849 set treediff {}
7850
7851 set inhdr 0
7852 foreach line $difflines {
Denton Liue2445882020-09-10 21:36:33 -07007853 if {![string compare -length 5 "diff " $line]} {
7854 set inhdr 1
7855 } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
7856 # offset also accounts for the b/ prefix
7857 lappend treediff [string range $line 6 end]
7858 set inhdr 0
7859 }
Thomas Rast9403bd02013-11-16 18:37:43 +01007860 }
7861
7862 set treediffs($ids) $treediff
7863 add_flist $treediff
7864
7865 $ctext conf -state normal
7866 foreach line $difflines {
Denton Liue2445882020-09-10 21:36:33 -07007867 parseblobdiffline $ids $line
Thomas Rast9403bd02013-11-16 18:37:43 +01007868 }
7869 maybe_scroll_ctext 1
7870 $ctext conf -state disabled
7871}
7872
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007873# If the filename (name) is under any of the passed filter paths
7874# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007875proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007876 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007877 foreach p $filter {
Denton Liue2445882020-09-10 21:36:33 -07007878 set fq_p [file normalize $p]
7879 set fq_n [file normalize [file join $worktree $name]]
7880 if {[string match [file normalize $fq_p]* $fq_n]} {
7881 return 1
7882 }
Paul Mackerras7a39a172007-10-23 10:15:11 +10007883 }
7884 return 0
7885}
7886
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007887proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007888 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007889
Paul Mackerras74a40c72007-10-24 10:16:56 +10007890 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007891 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007892}
7893
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007894proc diffcmd {ids flags} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007895 global log_showroot nullid nullid2 git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007896
7897 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007898 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007899 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07007900 if {[llength $ids] > 1 && $j < 0} {
7901 # comparing working directory with some specific revision
7902 set cmd [concat | git diff-index $flags]
7903 if {$i == 0} {
7904 lappend cmd -R [lindex $ids 1]
7905 } else {
7906 lappend cmd [lindex $ids 0]
7907 }
7908 } else {
7909 # comparing working directory with index
7910 set cmd [concat | git diff-files $flags]
7911 if {$j == 1} {
7912 lappend cmd -R
7913 }
7914 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007915 } elseif {$j >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07007916 if {[package vcompare $git_version "1.7.2"] >= 0} {
7917 set flags "$flags --ignore-submodules=dirty"
7918 }
7919 set cmd [concat | git diff-index --cached $flags]
7920 if {[llength $ids] > 1} {
7921 # comparing index with specific revision
7922 if {$j == 0} {
7923 lappend cmd -R [lindex $ids 1]
7924 } else {
7925 lappend cmd [lindex $ids 0]
7926 }
7927 } else {
7928 # comparing index with HEAD
7929 lappend cmd HEAD
7930 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007931 } else {
Denton Liue2445882020-09-10 21:36:33 -07007932 if {$log_showroot} {
7933 lappend flags --root
7934 }
7935 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007936 }
7937 return $cmd
7938}
7939
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007940proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007941 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007942
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007943 set cmd [diffcmd $ids {--no-commit-id}]
7944 if {$limitdiffs && $vfilelimit($curview) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07007945 set cmd [concat $cmd -- $vfilelimit($curview)]
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007946 }
7947 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007948
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007949 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007950 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007951 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007952 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007953}
7954
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007955proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007956 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007957 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007958
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007959 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007960 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007961 set max 1000
7962 if {$perfile_attrs} {
Denton Liue2445882020-09-10 21:36:33 -07007963 # cache_gitattr is slow, and even slower on win32 where we
7964 # have to invoke it for only about 30 paths at a time
7965 set max 500
7966 if {[tk windowingsystem] == "win32"} {
7967 set max 120
7968 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007969 }
7970 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07007971 set i [string first "\t" $line]
7972 if {$i >= 0} {
7973 set file [string range $line [expr {$i+1}] end]
7974 if {[string index $file 0] eq "\""} {
7975 set file [lindex $file 0]
7976 }
7977 set file [encoding convertfrom $file]
7978 if {$file ne [lindex $treediff end]} {
7979 lappend treediff $file
7980 lappend sublist $file
7981 }
7982 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007983 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007984 if {$perfile_attrs} {
Denton Liue2445882020-09-10 21:36:33 -07007985 cache_gitattr encoding $sublist
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007986 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007987 if {![eof $gdtf]} {
Denton Liue2445882020-09-10 21:36:33 -07007988 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007989 }
7990 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007991 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007992 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007993 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Denton Liue2445882020-09-10 21:36:33 -07007994 gettree $diffids
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007995 } elseif {$ids != $diffids} {
Denton Liue2445882020-09-10 21:36:33 -07007996 if {![info exists diffmergeid]} {
7997 gettreediffs $diffids
7998 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007999 } else {
Denton Liue2445882020-09-10 21:36:33 -07008000 addtocflist $ids
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008001 }
8002 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00008003}
8004
Steffen Prohaska890fae72007-08-12 12:05:46 +02008005# empty string or positive integer
8006proc diffcontextvalidate {v} {
8007 return [regexp {^(|[1-9][0-9]*)$} $v]
8008}
8009
8010proc diffcontextchange {n1 n2 op} {
8011 global diffcontextstring diffcontext
8012
8013 if {[string is integer -strict $diffcontextstring]} {
Denton Liue2445882020-09-10 21:36:33 -07008014 if {$diffcontextstring >= 0} {
8015 set diffcontext $diffcontextstring
8016 reselectline
8017 }
Steffen Prohaska890fae72007-08-12 12:05:46 +02008018 }
8019}
8020
Steffen Prohaskab9b86002008-01-17 23:42:55 +01008021proc changeignorespace {} {
8022 reselectline
8023}
8024
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008025proc changeworddiff {name ix op} {
8026 reselectline
8027}
8028
Thomas Rast5de460a2013-11-16 18:37:41 +01008029proc initblobdiffvars {} {
8030 global diffencoding targetline diffnparents
8031 global diffinhdr currdiffsubmod diffseehere
8032 set targetline {}
8033 set diffnparents 0
8034 set diffinhdr 0
8035 set diffencoding [get_path_encoding {}]
8036 set currdiffsubmod ""
8037 set diffseehere -1
8038}
8039
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008040proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10008041 global blobdifffd diffids env
Thomas Rast5de460a2013-11-16 18:37:41 +01008042 global treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02008043 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01008044 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008045 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10008046 global limitdiffs vfilelimit curview
Thomas Rast5de460a2013-11-16 18:37:41 +01008047 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008048
Paul Mackerrasa8138732009-05-16 21:06:01 +10008049 set textconv {}
8050 if {[package vcompare $git_version "1.6.1"] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07008051 set textconv "--textconv"
Paul Mackerrasa8138732009-05-16 21:06:01 +10008052 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01008053 set submodule {}
8054 if {[package vcompare $git_version "1.6.6"] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07008055 set submodule "--submodule"
Jens Lehmann5c838d22009-10-28 12:40:45 +01008056 }
8057 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01008058 if {$ignorespace} {
Denton Liue2445882020-09-10 21:36:33 -07008059 append cmd " -w"
Steffen Prohaskab9b86002008-01-17 23:42:55 +01008060 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008061 if {$worddiff ne [mc "Line diff"]} {
Denton Liue2445882020-09-10 21:36:33 -07008062 append cmd " --word-diff=porcelain"
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008063 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10008064 if {$limitdiffs && $vfilelimit($curview) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008065 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10008066 }
8067 if {[catch {set bdf [open $cmd r]} err]} {
Denton Liue2445882020-09-10 21:36:33 -07008068 error_popup [mc "Error getting diffs: %s" $err]
8069 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008070 }
Pat Thoyts681c3292009-03-16 10:24:40 +00008071 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008072 set blobdifffd($ids) $bdf
Thomas Rast5de460a2013-11-16 18:37:41 +01008073 initblobdiffvars
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008074 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008075}
8076
Paul Mackerras354af6b2008-11-23 13:14:23 +11008077proc savecmitpos {} {
8078 global ctext cmitmode
8079
8080 if {$cmitmode eq "tree"} {
Denton Liue2445882020-09-10 21:36:33 -07008081 return {}
Paul Mackerras354af6b2008-11-23 13:14:23 +11008082 }
8083 return [list target_scrollpos [$ctext index @0,0]]
8084}
8085
8086proc savectextpos {} {
8087 global ctext
8088
8089 return [list target_scrollpos [$ctext index @0,0]]
8090}
8091
8092proc maybe_scroll_ctext {ateof} {
8093 global ctext target_scrollpos
8094
8095 if {![info exists target_scrollpos]} return
8096 if {!$ateof} {
Denton Liue2445882020-09-10 21:36:33 -07008097 set nlines [expr {[winfo height $ctext]
8098 / [font metrics textfont -linespace]}]
8099 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
Paul Mackerras354af6b2008-11-23 13:14:23 +11008100 }
8101 $ctext yview $target_scrollpos
8102 unset target_scrollpos
8103}
8104
Paul Mackerras89b11d32006-05-02 19:55:31 +10008105proc setinlist {var i val} {
8106 global $var
8107
8108 while {[llength [set $var]] < $i} {
Denton Liue2445882020-09-10 21:36:33 -07008109 lappend $var {}
Paul Mackerras89b11d32006-05-02 19:55:31 +10008110 }
8111 if {[llength [set $var]] == $i} {
Denton Liue2445882020-09-10 21:36:33 -07008112 lappend $var $val
Paul Mackerras89b11d32006-05-02 19:55:31 +10008113 } else {
Denton Liue2445882020-09-10 21:36:33 -07008114 lset $var $i $val
Paul Mackerras89b11d32006-05-02 19:55:31 +10008115 }
8116}
8117
Paul Mackerras9396cd32007-06-23 20:28:15 +10008118proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008119 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11008120 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10008121
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008122 set fname [encoding convertfrom $fname]
8123 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10008124 set i [lsearch -exact $treediffs($ids) $fname]
8125 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07008126 setinlist difffilestart $i $curdiffstart
Paul Mackerras9396cd32007-06-23 20:28:15 +10008127 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11008128 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10008129 set l [expr {(78 - [string length $fname]) / 2}]
8130 set pad [string range "----------------------------------------" 1 $l]
8131 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11008132 set targetline {}
8133 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
Denton Liue2445882020-09-10 21:36:33 -07008134 set targetline [lindex $jump_to_here 1]
Paul Mackerras8a897742008-10-27 21:36:25 +11008135 }
8136 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10008137}
8138
Thomas Rast5de460a2013-11-16 18:37:41 +01008139proc blobdiffmaybeseehere {ateof} {
8140 global diffseehere
8141 if {$diffseehere >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07008142 mark_ctext_line [lindex [split $diffseehere .] 0]
Thomas Rast5de460a2013-11-16 18:37:41 +01008143 }
Max Kirillov1f3c8722014-01-18 14:58:51 +02008144 maybe_scroll_ctext $ateof
Thomas Rast5de460a2013-11-16 18:37:41 +01008145}
8146
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008147proc getblobdiffline {bdf ids} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008148 global diffids blobdifffd
8149 global ctext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008150
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008151 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008152 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008153 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07008154 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
8155 # Older diff read. Abort it.
8156 catch {close $bdf}
8157 if {$ids != $diffids} {
8158 array unset blobdifffd $ids
8159 }
8160 return 0
8161 }
8162 parseblobdiffline $ids $line
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008163 }
8164 $ctext conf -state disabled
Thomas Rast5de460a2013-11-16 18:37:41 +01008165 blobdiffmaybeseehere [eof $bdf]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008166 if {[eof $bdf]} {
Denton Liue2445882020-09-10 21:36:33 -07008167 catch {close $bdf}
8168 array unset blobdifffd $ids
8169 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008170 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008171 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008172}
8173
Thomas Rast5de460a2013-11-16 18:37:41 +01008174proc parseblobdiffline {ids line} {
8175 global ctext curdiffstart
8176 global diffnexthead diffnextnote difffilestart
8177 global ctext_file_names ctext_file_lines
8178 global diffinhdr treediffs mergemax diffnparents
8179 global diffencoding jump_to_here targetline diffline currdiffsubmod
8180 global worddiff diffseehere
8181
8182 if {![string compare -length 5 "diff " $line]} {
Denton Liue2445882020-09-10 21:36:33 -07008183 if {![regexp {^diff (--cc|--git) } $line m type]} {
8184 set line [encoding convertfrom $line]
8185 $ctext insert end "$line\n" hunksep
8186 continue
8187 }
8188 # start of a new file
8189 set diffinhdr 1
8190 set currdiffsubmod ""
Роман Донченкоf177c492019-11-02 02:34:27 +03008191
Denton Liue2445882020-09-10 21:36:33 -07008192 $ctext insert end "\n"
8193 set curdiffstart [$ctext index "end - 1c"]
8194 lappend ctext_file_names ""
8195 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8196 $ctext insert end "\n" filesep
Thomas Rast5de460a2013-11-16 18:37:41 +01008197
Denton Liue2445882020-09-10 21:36:33 -07008198 if {$type eq "--cc"} {
8199 # start of a new file in a merge diff
8200 set fname [string range $line 10 end]
8201 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
8202 lappend treediffs($ids) $fname
8203 add_flist [list $fname]
8204 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008205
Denton Liue2445882020-09-10 21:36:33 -07008206 } else {
8207 set line [string range $line 11 end]
8208 # If the name hasn't changed the length will be odd,
8209 # the middle char will be a space, and the two bits either
8210 # side will be a/name and b/name, or "a/name" and "b/name".
8211 # If the name has changed we'll get "rename from" and
8212 # "rename to" or "copy from" and "copy to" lines following
8213 # this, and we'll use them to get the filenames.
8214 # This complexity is necessary because spaces in the
8215 # filename(s) don't get escaped.
8216 set l [string length $line]
8217 set i [expr {$l / 2}]
8218 if {!(($l & 1) && [string index $line $i] eq " " &&
8219 [string range $line 2 [expr {$i - 1}]] eq \
8220 [string range $line [expr {$i + 3}] end])} {
8221 return
8222 }
8223 # unescape if quoted and chop off the a/ from the front
8224 if {[string index $line 0] eq "\""} {
8225 set fname [string range [lindex $line 0] 2 end]
8226 } else {
8227 set fname [string range $line 2 [expr {$i - 1}]]
8228 }
8229 }
8230 makediffhdr $fname $ids
Thomas Rast5de460a2013-11-16 18:37:41 +01008231
8232 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
Denton Liue2445882020-09-10 21:36:33 -07008233 set fname [encoding convertfrom [string range $line 16 end]]
8234 $ctext insert end "\n"
8235 set curdiffstart [$ctext index "end - 1c"]
8236 lappend ctext_file_names $fname
8237 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8238 $ctext insert end "$line\n" filesep
8239 set i [lsearch -exact $treediffs($ids) $fname]
8240 if {$i >= 0} {
8241 setinlist difffilestart $i $curdiffstart
8242 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008243
8244 } elseif {![string compare -length 2 "@@" $line]} {
Denton Liue2445882020-09-10 21:36:33 -07008245 regexp {^@@+} $line ats
8246 set line [encoding convertfrom $diffencoding $line]
8247 $ctext insert end "$line\n" hunksep
8248 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8249 set diffline $nl
8250 }
8251 set diffnparents [expr {[string length $ats] - 1}]
8252 set diffinhdr 0
Thomas Rast5de460a2013-11-16 18:37:41 +01008253
8254 } elseif {![string compare -length 10 "Submodule " $line]} {
Denton Liue2445882020-09-10 21:36:33 -07008255 # start of a new submodule
8256 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
8257 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
8258 } else {
8259 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
8260 }
8261 if {$currdiffsubmod != $fname} {
8262 $ctext insert end "\n"; # Add newline after commit message
8263 }
8264 if {$currdiffsubmod != $fname} {
8265 set curdiffstart [$ctext index "end - 1c"]
8266 lappend ctext_file_names ""
8267 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8268 makediffhdr $fname $ids
8269 set currdiffsubmod $fname
8270 $ctext insert end "\n$line\n" filesep
8271 } else {
8272 $ctext insert end "$line\n" filesep
8273 }
Gabriele Mazzotta9ea831a2019-03-23 18:00:36 +01008274 } elseif {$currdiffsubmod != "" && ![string compare -length 3 " >" $line]} {
Denton Liue2445882020-09-10 21:36:33 -07008275 set line [encoding convertfrom $diffencoding $line]
8276 $ctext insert end "$line\n" dresult
Gabriele Mazzotta9ea831a2019-03-23 18:00:36 +01008277 } elseif {$currdiffsubmod != "" && ![string compare -length 3 " <" $line]} {
Denton Liue2445882020-09-10 21:36:33 -07008278 set line [encoding convertfrom $diffencoding $line]
8279 $ctext insert end "$line\n" d0
Thomas Rast5de460a2013-11-16 18:37:41 +01008280 } elseif {$diffinhdr} {
Denton Liue2445882020-09-10 21:36:33 -07008281 if {![string compare -length 12 "rename from " $line]} {
8282 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8283 if {[string index $fname 0] eq "\""} {
8284 set fname [lindex $fname 0]
8285 }
8286 set fname [encoding convertfrom $fname]
8287 set i [lsearch -exact $treediffs($ids) $fname]
8288 if {$i >= 0} {
8289 setinlist difffilestart $i $curdiffstart
8290 }
8291 } elseif {![string compare -length 10 $line "rename to "] ||
8292 ![string compare -length 8 $line "copy to "]} {
8293 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8294 if {[string index $fname 0] eq "\""} {
8295 set fname [lindex $fname 0]
8296 }
8297 makediffhdr $fname $ids
8298 } elseif {[string compare -length 3 $line "---"] == 0} {
8299 # do nothing
8300 return
8301 } elseif {[string compare -length 3 $line "+++"] == 0} {
8302 set diffinhdr 0
8303 return
8304 }
8305 $ctext insert end "$line\n" filesep
Thomas Rast5de460a2013-11-16 18:37:41 +01008306
8307 } else {
Denton Liue2445882020-09-10 21:36:33 -07008308 set line [string map {\x1A ^Z} \
8309 [encoding convertfrom $diffencoding $line]]
8310 # parse the prefix - one ' ', '-' or '+' for each parent
8311 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8312 set tag [expr {$diffnparents > 1? "m": "d"}]
8313 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8314 set words_pre_markup ""
8315 set words_post_markup ""
8316 if {[string trim $prefix " -+"] eq {}} {
8317 # prefix only has " ", "-" and "+" in it: normal diff line
8318 set num [string first "-" $prefix]
8319 if {$dowords} {
8320 set line [string range $line 1 end]
8321 }
8322 if {$num >= 0} {
8323 # removed line, first parent with line is $num
8324 if {$num >= $mergemax} {
8325 set num "max"
8326 }
8327 if {$dowords && $worddiff eq [mc "Markup words"]} {
8328 $ctext insert end "\[-$line-\]" $tag$num
8329 } else {
8330 $ctext insert end "$line" $tag$num
8331 }
8332 if {!$dowords} {
8333 $ctext insert end "\n" $tag$num
8334 }
8335 } else {
8336 set tags {}
8337 if {[string first "+" $prefix] >= 0} {
8338 # added line
8339 lappend tags ${tag}result
8340 if {$diffnparents > 1} {
8341 set num [string first " " $prefix]
8342 if {$num >= 0} {
8343 if {$num >= $mergemax} {
8344 set num "max"
8345 }
8346 lappend tags m$num
8347 }
8348 }
8349 set words_pre_markup "{+"
8350 set words_post_markup "+}"
8351 }
8352 if {$targetline ne {}} {
8353 if {$diffline == $targetline} {
8354 set diffseehere [$ctext index "end - 1 chars"]
8355 set targetline {}
8356 } else {
8357 incr diffline
8358 }
8359 }
8360 if {$dowords && $worddiff eq [mc "Markup words"]} {
8361 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8362 } else {
8363 $ctext insert end "$line" $tags
8364 }
8365 if {!$dowords} {
8366 $ctext insert end "\n" $tags
8367 }
8368 }
8369 } elseif {$dowords && $prefix eq "~"} {
8370 $ctext insert end "\n" {}
8371 } else {
8372 # "\ No newline at end of file",
8373 # or something else we don't recognize
8374 $ctext insert end "$line\n" hunksep
8375 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008376 }
8377}
8378
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008379proc changediffdisp {} {
8380 global ctext diffelide
8381
8382 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008383 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008384}
8385
Stefan Hallerb9671352012-09-19 20:17:27 +02008386proc highlightfile {cline} {
8387 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008388
Stefan Hallerce837c92012-10-04 22:50:16 +02008389 if {![info exists cflist_top]} return
8390
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008391 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8392 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8393 $cflist see $cline.0
8394 set cflist_top $cline
8395}
8396
Stefan Hallerb9671352012-09-19 20:17:27 +02008397proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008398 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008399
Stefan Haller978904b2012-10-04 22:50:17 +02008400 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008401 if {![info exists difffilestart]} return
8402
8403 set top [lindex [split $topidx .] 0]
8404 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
Denton Liue2445882020-09-10 21:36:33 -07008405 highlightfile 0
Stefan Hallerb9671352012-09-19 20:17:27 +02008406 } else {
Denton Liue2445882020-09-10 21:36:33 -07008407 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
Stefan Hallerb9671352012-09-19 20:17:27 +02008408 }
8409}
8410
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008411proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008412 global difffilestart ctext cmitmode
8413
8414 if {$cmitmode eq "tree"} return
8415 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008416 set here [$ctext index @0,0]
8417 foreach loc $difffilestart {
Denton Liue2445882020-09-10 21:36:33 -07008418 if {[$ctext compare $loc >= $here]} {
8419 $ctext yview $prev
8420 return
8421 }
8422 set prev $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008423 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008424 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008425}
8426
Paul Mackerras39ad8572005-05-19 12:35:53 +00008427proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008428 global difffilestart ctext cmitmode
8429
8430 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008431 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008432 foreach loc $difffilestart {
Denton Liue2445882020-09-10 21:36:33 -07008433 if {[$ctext compare $loc > $here]} {
8434 $ctext yview $loc
8435 return
8436 }
Paul Mackerras39ad8572005-05-19 12:35:53 +00008437 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008438}
8439
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008440proc clear_ctext {{first 1.0}} {
8441 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008442 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008443 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008444
Paul Mackerras1902c272006-05-25 21:25:13 +10008445 set l [lindex [split $first .] 0]
8446 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
Denton Liue2445882020-09-10 21:36:33 -07008447 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008448 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008449 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
Denton Liue2445882020-09-10 21:36:33 -07008450 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008451 }
8452 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008453 if {$first eq "1.0"} {
Denton Liue2445882020-09-10 21:36:33 -07008454 unset -nocomplain pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10008455 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008456 set ctext_file_names {}
8457 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008458}
8459
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008460proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008461 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008462
8463 if {$firstab ne {} && $have_tk85} {
Denton Liue2445882020-09-10 21:36:33 -07008464 set firsttabstop $firstab
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008465 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008466 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008467 if {$firsttabstop != 0} {
Denton Liue2445882020-09-10 21:36:33 -07008468 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8469 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008470 } elseif {$have_tk85 || $tabstop != 8} {
Denton Liue2445882020-09-10 21:36:33 -07008471 $ctext conf -tabs [expr {$tabstop * $w}]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008472 } else {
Denton Liue2445882020-09-10 21:36:33 -07008473 $ctext conf -tabs {}
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008474 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008475}
8476
8477proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008478 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008479
Paul Mackerras1902c272006-05-25 21:25:13 +10008480 if {[catch {$ctext index anchor}]} {
Denton Liue2445882020-09-10 21:36:33 -07008481 # no anchor set, use start of selection, or of visible area
8482 set sel [$ctext tag ranges sel]
8483 if {$sel ne {}} {
8484 $ctext mark set anchor [lindex $sel 0]
8485 } elseif {$searchdirn eq "-forwards"} {
8486 $ctext mark set anchor @0,0
8487 } else {
8488 $ctext mark set anchor @0,[winfo height $ctext]
8489 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008490 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008491 if {$searchstring ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008492 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
8493 if {$here ne {}} {
8494 $ctext see $here
8495 set mend "$here + $mlen c"
8496 $ctext tag remove sel 1.0 end
8497 $ctext tag add sel $here $mend
8498 suppress_highlighting_file_for_current_scrollpos
8499 highlightfile_for_scrollpos $here
8500 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008501 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008502 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008503}
8504
8505proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008506 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008507
8508 focus $sstring
8509 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008510 set searchdirn -forwards
8511 if {$searchstring ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008512 set sel [$ctext tag ranges sel]
8513 if {$sel ne {}} {
8514 set start "[lindex $sel 0] + 1c"
8515 } elseif {[catch {set start [$ctext index anchor]}]} {
8516 set start "@0,0"
8517 }
8518 set match [$ctext search -count mlen -- $searchstring $start]
8519 $ctext tag remove sel 1.0 end
8520 if {$match eq {}} {
8521 bell
8522 return
8523 }
8524 $ctext see $match
8525 suppress_highlighting_file_for_current_scrollpos
8526 highlightfile_for_scrollpos $match
8527 set mend "$match + $mlen c"
8528 $ctext tag add sel $match $mend
8529 $ctext mark unset anchor
8530 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008531 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008532}
8533
8534proc dosearchback {} {
8535 global sstring ctext searchstring searchdirn
8536
8537 focus $sstring
8538 $sstring icursor end
8539 set searchdirn -backwards
8540 if {$searchstring ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008541 set sel [$ctext tag ranges sel]
8542 if {$sel ne {}} {
8543 set start [lindex $sel 0]
8544 } elseif {[catch {set start [$ctext index anchor]}]} {
8545 set start @0,[winfo height $ctext]
8546 }
8547 set match [$ctext search -backwards -count ml -- $searchstring $start]
8548 $ctext tag remove sel 1.0 end
8549 if {$match eq {}} {
8550 bell
8551 return
8552 }
8553 $ctext see $match
8554 suppress_highlighting_file_for_current_scrollpos
8555 highlightfile_for_scrollpos $match
8556 set mend "$match + $ml c"
8557 $ctext tag add sel $match $mend
8558 $ctext mark unset anchor
8559 rehighlight_search_results
Stefan Hallerc4614992012-09-22 09:40:24 +02008560 }
8561}
8562
8563proc rehighlight_search_results {} {
8564 global ctext searchstring
8565
8566 $ctext tag remove found 1.0 end
8567 $ctext tag remove currentsearchhit 1.0 end
8568
8569 if {$searchstring ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008570 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008571 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008572}
8573
8574proc searchmark {first last} {
8575 global ctext searchstring
8576
Stefan Hallerc4614992012-09-22 09:40:24 +02008577 set sel [$ctext tag ranges sel]
8578
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008579 set mend $first.0
8580 while {1} {
Denton Liue2445882020-09-10 21:36:33 -07008581 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8582 if {$match eq {}} break
8583 set mend "$match + $mlen c"
8584 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8585 $ctext tag add currentsearchhit $match $mend
8586 } else {
8587 $ctext tag add found $match $mend
8588 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008589 }
8590}
8591
8592proc searchmarkvisible {doall} {
8593 global ctext smarktop smarkbot
8594
8595 set topline [lindex [split [$ctext index @0,0] .] 0]
8596 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8597 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
Denton Liue2445882020-09-10 21:36:33 -07008598 # no overlap with previous
8599 searchmark $topline $botline
8600 set smarktop $topline
8601 set smarkbot $botline
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008602 } else {
Denton Liue2445882020-09-10 21:36:33 -07008603 if {$topline < $smarktop} {
8604 searchmark $topline [expr {$smarktop-1}]
8605 set smarktop $topline
8606 }
8607 if {$botline > $smarkbot} {
8608 searchmark [expr {$smarkbot+1}] $botline
8609 set smarkbot $botline
8610 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008611 }
8612}
8613
Stefan Hallerb9671352012-09-19 20:17:27 +02008614proc suppress_highlighting_file_for_current_scrollpos {} {
8615 global ctext suppress_highlighting_file_for_this_scrollpos
8616
8617 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8618}
8619
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008620proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008621 global searchstring cmitmode ctext
8622 global suppress_highlighting_file_for_this_scrollpos
8623
Stefan Haller978904b2012-10-04 22:50:17 +02008624 set topidx [$ctext index @0,0]
8625 if {![info exists suppress_highlighting_file_for_this_scrollpos]
Denton Liue2445882020-09-10 21:36:33 -07008626 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8627 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008628 }
8629
Paul Mackerras009409f2015-05-02 20:53:36 +10008630 unset -nocomplain suppress_highlighting_file_for_this_scrollpos
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008631
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008632 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008633 if {$searchstring ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008634 searchmarkvisible 0
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008635 }
8636}
8637
Paul Mackerras1d10f362005-05-15 12:55:47 +00008638proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008639 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008640 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008641
Paul Mackerras9c311b32007-10-04 22:27:13 +10008642 set linespc [font metrics mainfont -linespace]
8643 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008644 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8645 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008646 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008647 set xspc1(0) $linespc
8648 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008649}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008650
Paul Mackerras1d10f362005-05-15 12:55:47 +00008651proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008652 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008653 global selectedline
8654
8655 set ymax [lindex [$canv cget -scrollregion] 3]
8656 if {$ymax eq {} || $ymax == 0} return
8657 set span [$canv yview]
8658 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008659 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008660 allcanvs yview moveto [lindex $span 0]
8661 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008662 if {$selectedline ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008663 selectline $selectedline 0
8664 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008665 }
8666}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008667
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008668proc parsefont {f n} {
8669 global fontattr
8670
8671 set fontattr($f,family) [lindex $n 0]
8672 set s [lindex $n 1]
8673 if {$s eq {} || $s == 0} {
Denton Liue2445882020-09-10 21:36:33 -07008674 set s 10
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008675 } elseif {$s < 0} {
Denton Liue2445882020-09-10 21:36:33 -07008676 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008677 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008678 set fontattr($f,size) $s
8679 set fontattr($f,weight) normal
8680 set fontattr($f,slant) roman
8681 foreach style [lrange $n 2 end] {
Denton Liue2445882020-09-10 21:36:33 -07008682 switch -- $style {
8683 "normal" -
8684 "bold" {set fontattr($f,weight) $style}
8685 "roman" -
8686 "italic" {set fontattr($f,slant) $style}
8687 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008688 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008689}
8690
8691proc fontflags {f {isbold 0}} {
8692 global fontattr
8693
8694 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
Denton Liue2445882020-09-10 21:36:33 -07008695 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8696 -slant $fontattr($f,slant)]
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008697}
8698
8699proc fontname {f} {
8700 global fontattr
8701
8702 set n [list $fontattr($f,family) $fontattr($f,size)]
8703 if {$fontattr($f,weight) eq "bold"} {
Denton Liue2445882020-09-10 21:36:33 -07008704 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008705 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008706 if {$fontattr($f,slant) eq "italic"} {
Denton Liue2445882020-09-10 21:36:33 -07008707 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008708 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008709 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008710}
8711
Paul Mackerras1d10f362005-05-15 12:55:47 +00008712proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008713 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008714 global stopped entries fontattr
8715
Paul Mackerras1d10f362005-05-15 12:55:47 +00008716 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008717 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008718 incr s $inc
8719 if {$s < 1} {
Denton Liue2445882020-09-10 21:36:33 -07008720 set s 1
Paul Mackerras9c311b32007-10-04 22:27:13 +10008721 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008722 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008723 font config mainfont -size $s
8724 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008725 set mainfont [fontname mainfont]
8726 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008727 incr s $inc
8728 if {$s < 1} {
Denton Liue2445882020-09-10 21:36:33 -07008729 set s 1
Paul Mackerras9c311b32007-10-04 22:27:13 +10008730 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008731 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008732 font config textfont -size $s
8733 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008734 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008735 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008736 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008737 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008738}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008739
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008740proc clearsha1 {} {
8741 global sha1entry sha1string
8742 if {[string length $sha1string] == 40} {
Denton Liue2445882020-09-10 21:36:33 -07008743 $sha1entry delete 0 end
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008744 }
8745}
8746
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008747proc sha1change {n1 n2 op} {
8748 global sha1string currentid sha1but
8749 if {$sha1string == {}
Denton Liue2445882020-09-10 21:36:33 -07008750 || ([info exists currentid] && $sha1string == $currentid)} {
8751 set state disabled
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008752 } else {
Denton Liue2445882020-09-10 21:36:33 -07008753 set state normal
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008754 }
8755 if {[$sha1but cget -state] == $state} return
8756 if {$state == "normal"} {
Denton Liue2445882020-09-10 21:36:33 -07008757 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008758 } else {
Denton Liue2445882020-09-10 21:36:33 -07008759 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008760 }
8761}
8762
8763proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008764 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008765
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008766 if {$sha1string == {}
Denton Liue2445882020-09-10 21:36:33 -07008767 || ([info exists currentid] && $sha1string == $currentid)} return
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008768 if {[info exists tagids($sha1string)]} {
Denton Liue2445882020-09-10 21:36:33 -07008769 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008770 } elseif {[info exists headids($sha1string)]} {
Denton Liue2445882020-09-10 21:36:33 -07008771 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008772 } else {
Denton Liue2445882020-09-10 21:36:33 -07008773 set id [string tolower $sha1string]
8774 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
8775 set matches [longid $id]
8776 if {$matches ne {}} {
8777 if {[llength $matches] > 1} {
8778 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
8779 return
8780 }
8781 set id [lindex $matches 0]
8782 }
8783 } else {
8784 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8785 error_popup [mc "Revision %s is not known" $sha1string]
8786 return
8787 }
8788 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008789 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008790 if {[commitinview $id $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07008791 selectline [rowofcommit $id] 1
8792 return
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008793 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008794 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Denton Liue2445882020-09-10 21:36:33 -07008795 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008796 } else {
Denton Liue2445882020-09-10 21:36:33 -07008797 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008798 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008799 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008800}
8801
Paul Mackerras84ba7342005-06-17 00:12:26 +00008802proc lineenter {x y id} {
8803 global hoverx hovery hoverid hovertimer
8804 global commitinfo canv
8805
Paul Mackerras8ed16482006-03-02 22:56:44 +11008806 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008807 set hoverx $x
8808 set hovery $y
8809 set hoverid $id
8810 if {[info exists hovertimer]} {
Denton Liue2445882020-09-10 21:36:33 -07008811 after cancel $hovertimer
Paul Mackerras84ba7342005-06-17 00:12:26 +00008812 }
8813 set hovertimer [after 500 linehover]
8814 $canv delete hover
8815}
8816
8817proc linemotion {x y id} {
8818 global hoverx hovery hoverid hovertimer
8819
8820 if {[info exists hoverid] && $id == $hoverid} {
Denton Liue2445882020-09-10 21:36:33 -07008821 set hoverx $x
8822 set hovery $y
8823 if {[info exists hovertimer]} {
8824 after cancel $hovertimer
8825 }
8826 set hovertimer [after 500 linehover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008827 }
8828}
8829
8830proc lineleave {id} {
8831 global hoverid hovertimer canv
8832
8833 if {[info exists hoverid] && $id == $hoverid} {
Denton Liue2445882020-09-10 21:36:33 -07008834 $canv delete hover
8835 if {[info exists hovertimer]} {
8836 after cancel $hovertimer
8837 unset hovertimer
8838 }
8839 unset hoverid
Paul Mackerras84ba7342005-06-17 00:12:26 +00008840 }
8841}
8842
8843proc linehover {} {
8844 global hoverx hovery hoverid hovertimer
8845 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008846 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8847
Paul Mackerras9c311b32007-10-04 22:27:13 +10008848 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008849
8850 set text [lindex $commitinfo($hoverid) 0]
8851 set ymax [lindex [$canv cget -scrollregion] 3]
8852 if {$ymax == {}} return
8853 set yfrac [lindex [$canv yview] 0]
8854 set x [expr {$hoverx + 2 * $linespc}]
8855 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8856 set x0 [expr {$x - 2 * $lthickness}]
8857 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008858 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008859 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8860 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Denton Liue2445882020-09-10 21:36:33 -07008861 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8862 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008863 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008864 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Denton Liue2445882020-09-10 21:36:33 -07008865 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008866 $canv raise $t
8867}
8868
Paul Mackerras9843c302005-08-30 10:57:11 +10008869proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008870 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008871
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008872 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008873 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008874 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008875 for {set i 1} {$i < $n} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07008876 set row [lindex $ranges $i]
8877 if {abs([yc $row] - $y) < $thresh} {
8878 return $i
8879 }
Paul Mackerras9843c302005-08-30 10:57:11 +10008880 }
8881 return {}
8882}
8883
Paul Mackerrasf6342482006-02-28 10:02:03 +11008884proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008885 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008886
Paul Mackerrasf6342482006-02-28 10:02:03 +11008887 # 1 <-> 2, 3 <-> 4, etc...
8888 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008889 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008890 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008891 set ymax [lindex [$canv cget -scrollregion] 3]
8892 if {$ymax eq {} || $ymax <= 0} return
8893 set view [$canv yview]
8894 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8895 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8896 if {$yfrac < 0} {
Denton Liue2445882020-09-10 21:36:33 -07008897 set yfrac 0
Paul Mackerras9843c302005-08-30 10:57:11 +10008898 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008899 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008900}
8901
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008902proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008903 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008904
Paul Mackerras8ed16482006-03-02 22:56:44 +11008905 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008906 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008907 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008908 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008909 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008910 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008911 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008912 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008913 if {$isnew} {
Denton Liue2445882020-09-10 21:36:33 -07008914 set ymax [lindex [$canv cget -scrollregion] 3]
8915 if {$ymax eq {}} return
8916 set yfrac [lindex [$canv yview] 0]
8917 set y [expr {$y + $yfrac * $ymax}]
Paul Mackerras9843c302005-08-30 10:57:11 +10008918 }
8919 set dirn [clickisonarrow $id $y]
8920 if {$dirn ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008921 arrowjump $id $dirn $y
8922 return
Paul Mackerras9843c302005-08-30 10:57:11 +10008923 }
8924
8925 if {$isnew} {
Denton Liue2445882020-09-10 21:36:33 -07008926 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008927 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008928 # fill the details pane with info about this line
8929 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008930 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008931 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008932 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008933 $ctext insert end $id link0
8934 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008935 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008936 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008937 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008938 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008939 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008940 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008941 if {$kids ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07008942 $ctext insert end "\n[mc "Children"]:"
8943 set i 0
8944 foreach child $kids {
8945 incr i
8946 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
8947 set info $commitinfo($child)
8948 $ctext insert end "\n\t"
8949 $ctext insert end $child link$i
8950 setlink $child link$i
8951 $ctext insert end "\n\t[lindex $info 0]"
8952 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
8953 set date [formatdate [lindex $info 2]]
8954 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
8955 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008956 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008957 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008958 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008959 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008960}
8961
Paul Mackerras9843c302005-08-30 10:57:11 +10008962proc normalline {} {
8963 global thickerline
8964 if {[info exists thickerline]} {
Denton Liue2445882020-09-10 21:36:33 -07008965 set id $thickerline
8966 unset thickerline
8967 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008968 }
8969}
8970
Paul Mackerras354af6b2008-11-23 13:14:23 +11008971proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008972 global curview
8973 if {[commitinview $id $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07008974 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008975 }
8976}
8977
8978proc mstime {} {
8979 global startmstime
8980 if {![info exists startmstime]} {
Denton Liue2445882020-09-10 21:36:33 -07008981 set startmstime [clock clicks -milliseconds]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008982 }
8983 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8984}
8985
8986proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008987 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008988 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008989
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008990 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008991 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008992 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Denton Liue2445882020-09-10 21:36:33 -07008993 set state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008994 } else {
Denton Liue2445882020-09-10 21:36:33 -07008995 set state normal
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008996 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008997 if {[info exists markedid] && $markedid ne $id} {
Denton Liue2445882020-09-10 21:36:33 -07008998 set mstate normal
Paul Mackerras6febded2012-03-23 22:07:27 +11008999 } else {
Denton Liue2445882020-09-10 21:36:33 -07009000 set mstate disabled
Paul Mackerras6febded2012-03-23 22:07:27 +11009001 }
Paul Mackerras8f489362007-07-13 19:49:37 +10009002 if {$id ne $nullid && $id ne $nullid2} {
Denton Liue2445882020-09-10 21:36:33 -07009003 set menu $rowctxmenu
9004 if {$mainhead ne {}} {
9005 $menu entryconfigure 8 -label [mc "Reset %s branch to here" $mainhead] -state normal
9006 } else {
9007 $menu entryconfigure 8 -label [mc "Detached head: can't reset" $mainhead] -state disabled
9008 }
9009 $menu entryconfigure 10 -state $mstate
9010 $menu entryconfigure 11 -state $mstate
9011 $menu entryconfigure 12 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009012 } else {
Denton Liue2445882020-09-10 21:36:33 -07009013 set menu $fakerowmenu
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009014 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11009015 $menu entryconfigure [mca "Diff this -> selected"] -state $state
9016 $menu entryconfigure [mca "Diff selected -> this"] -state $state
9017 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11009018 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
9019 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009020 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009021}
9022
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009023proc markhere {} {
9024 global rowmenuid markedid canv
9025
9026 set markedid $rowmenuid
9027 make_idmark $markedid
9028}
9029
9030proc gotomark {} {
9031 global markedid
9032
9033 if {[info exists markedid]} {
Denton Liue2445882020-09-10 21:36:33 -07009034 selbyid $markedid
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009035 }
9036}
9037
9038proc replace_by_kids {l r} {
9039 global curview children
9040
9041 set id [commitonrow $r]
9042 set l [lreplace $l 0 0]
9043 foreach kid $children($curview,$id) {
Denton Liue2445882020-09-10 21:36:33 -07009044 lappend l [rowofcommit $kid]
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009045 }
9046 return [lsort -integer -decreasing -unique $l]
9047}
9048
9049proc find_common_desc {} {
9050 global markedid rowmenuid curview children
9051
9052 if {![info exists markedid]} return
9053 if {![commitinview $markedid $curview] ||
Denton Liue2445882020-09-10 21:36:33 -07009054 ![commitinview $rowmenuid $curview]} return
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009055 #set t1 [clock clicks -milliseconds]
9056 set l1 [list [rowofcommit $markedid]]
9057 set l2 [list [rowofcommit $rowmenuid]]
9058 while 1 {
Denton Liue2445882020-09-10 21:36:33 -07009059 set r1 [lindex $l1 0]
9060 set r2 [lindex $l2 0]
9061 if {$r1 eq {} || $r2 eq {}} break
9062 if {$r1 == $r2} {
9063 selectline $r1 1
9064 break
9065 }
9066 if {$r1 > $r2} {
9067 set l1 [replace_by_kids $l1 $r1]
9068 } else {
9069 set l2 [replace_by_kids $l2 $r2]
9070 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009071 }
9072 #set t2 [clock clicks -milliseconds]
9073 #puts "took [expr {$t2-$t1}]ms"
9074}
9075
Paul Mackerras010509f2009-04-09 22:10:20 +10009076proc compare_commits {} {
9077 global markedid rowmenuid curview children
9078
9079 if {![info exists markedid]} return
9080 if {![commitinview $markedid $curview]} return
9081 addtohistory [list do_cmp_commits $markedid $rowmenuid]
9082 do_cmp_commits $markedid $rowmenuid
9083}
9084
9085proc getpatchid {id} {
9086 global patchids
9087
9088 if {![info exists patchids($id)]} {
Denton Liue2445882020-09-10 21:36:33 -07009089 set cmd [diffcmd [list $id] {-p --root}]
9090 # trim off the initial "|"
9091 set cmd [lrange $cmd 1 end]
9092 if {[catch {
9093 set x [eval exec $cmd | git patch-id]
9094 set patchids($id) [lindex $x 0]
9095 }]} {
9096 set patchids($id) "error"
9097 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009098 }
9099 return $patchids($id)
9100}
9101
9102proc do_cmp_commits {a b} {
9103 global ctext curview parents children patchids commitinfo
9104
9105 $ctext conf -state normal
9106 clear_ctext
9107 init_flist {}
9108 for {set i 0} {$i < 100} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -07009109 set skipa 0
9110 set skipb 0
9111 if {[llength $parents($curview,$a)] > 1} {
9112 appendshortlink $a [mc "Skipping merge commit "] "\n"
9113 set skipa 1
9114 } else {
9115 set patcha [getpatchid $a]
9116 }
9117 if {[llength $parents($curview,$b)] > 1} {
9118 appendshortlink $b [mc "Skipping merge commit "] "\n"
9119 set skipb 1
9120 } else {
9121 set patchb [getpatchid $b]
9122 }
9123 if {!$skipa && !$skipb} {
9124 set heada [lindex $commitinfo($a) 0]
9125 set headb [lindex $commitinfo($b) 0]
9126 if {$patcha eq "error"} {
9127 appendshortlink $a [mc "Error getting patch ID for "] \
9128 [mc " - stopping\n"]
9129 break
9130 }
9131 if {$patchb eq "error"} {
9132 appendshortlink $b [mc "Error getting patch ID for "] \
9133 [mc " - stopping\n"]
9134 break
9135 }
9136 if {$patcha eq $patchb} {
9137 if {$heada eq $headb} {
9138 appendshortlink $a [mc "Commit "]
9139 appendshortlink $b " == " " $heada\n"
9140 } else {
9141 appendshortlink $a [mc "Commit "] " $heada\n"
9142 appendshortlink $b [mc " is the same patch as\n "] \
9143 " $headb\n"
9144 }
9145 set skipa 1
9146 set skipb 1
9147 } else {
9148 $ctext insert end "\n"
9149 appendshortlink $a [mc "Commit "] " $heada\n"
9150 appendshortlink $b [mc " differs from\n "] \
9151 " $headb\n"
9152 $ctext insert end [mc "Diff of commits:\n\n"]
9153 $ctext conf -state disabled
9154 update
9155 diffcommits $a $b
9156 return
9157 }
9158 }
9159 if {$skipa} {
9160 set kids [real_children $curview,$a]
9161 if {[llength $kids] != 1} {
9162 $ctext insert end "\n"
9163 appendshortlink $a [mc "Commit "] \
9164 [mc " has %s children - stopping\n" [llength $kids]]
9165 break
9166 }
9167 set a [lindex $kids 0]
9168 }
9169 if {$skipb} {
9170 set kids [real_children $curview,$b]
9171 if {[llength $kids] != 1} {
9172 appendshortlink $b [mc "Commit "] \
9173 [mc " has %s children - stopping\n" [llength $kids]]
9174 break
9175 }
9176 set b [lindex $kids 0]
9177 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009178 }
9179 $ctext conf -state disabled
9180}
9181
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009182proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009183 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009184
9185 set tmpdir [gitknewtmpdir]
9186 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
9187 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
9188 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07009189 exec git diff-tree -p --pretty $a >$fna
9190 exec git diff-tree -p --pretty $b >$fnb
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009191 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07009192 error_popup [mc "Error writing commit to file: %s" $err]
9193 return
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009194 }
9195 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07009196 set fd [open "| diff -U$diffcontext $fna $fnb" r]
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009197 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07009198 error_popup [mc "Error diffing commits: %s" $err]
9199 return
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009200 }
9201 set diffids [list commits $a $b]
9202 set blobdifffd($diffids) $fd
9203 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009204 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009205 filerun $fd [list getblobdiffline $fd $diffids]
9206}
9207
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009208proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009209 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009210
Paul Mackerras94b4a692008-05-20 20:51:06 +10009211 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009212 if {$dirn} {
Denton Liue2445882020-09-10 21:36:33 -07009213 set oldid [commitonrow $selectedline]
9214 set newid $rowmenuid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009215 } else {
Denton Liue2445882020-09-10 21:36:33 -07009216 set oldid $rowmenuid
9217 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009218 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11009219 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009220 doseldiff $oldid $newid
9221}
9222
Paul Mackerras6febded2012-03-23 22:07:27 +11009223proc diffvsmark {dirn} {
9224 global rowmenuid markedid
9225
9226 if {![info exists markedid]} return
9227 if {$dirn} {
Denton Liue2445882020-09-10 21:36:33 -07009228 set oldid $markedid
9229 set newid $rowmenuid
Paul Mackerras6febded2012-03-23 22:07:27 +11009230 } else {
Denton Liue2445882020-09-10 21:36:33 -07009231 set oldid $rowmenuid
9232 set newid $markedid
Paul Mackerras6febded2012-03-23 22:07:27 +11009233 }
9234 addtohistory [list doseldiff $oldid $newid] savectextpos
9235 doseldiff $oldid $newid
9236}
9237
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009238proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009239 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009240 global commitinfo
9241
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009242 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009243 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01009244 init_flist [mc "Top"]
9245 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009246 $ctext insert end $oldid link0
9247 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009248 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009249 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009250 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009251 $ctext insert end $newid link1
9252 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009253 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009254 $ctext insert end [lindex $commitinfo($newid) 0]
9255 $ctext insert end "\n"
9256 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009257 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11009258 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009259}
9260
Paul Mackerras74daedb2005-06-27 19:27:32 +10009261proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009262 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10009263
9264 if {![info exists currentid]} return
9265 set oldid $currentid
9266 set oldhead [lindex $commitinfo($oldid) 0]
9267 set newid $rowmenuid
9268 set newhead [lindex $commitinfo($newid) 0]
9269 set top .patch
9270 set patchtop $top
9271 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009272 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009273 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009274 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009275 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009276 ${NS}::label $top.from -text [mc "From:"]
9277 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009278 $top.fromsha1 insert 0 $oldid
9279 $top.fromsha1 conf -state readonly
9280 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009281 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009282 $top.fromhead insert 0 $oldhead
9283 $top.fromhead conf -state readonly
9284 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009285 ${NS}::label $top.to -text [mc "To:"]
9286 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009287 $top.tosha1 insert 0 $newid
9288 $top.tosha1 conf -state readonly
9289 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009290 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009291 $top.tohead insert 0 $newhead
9292 $top.tohead conf -state readonly
9293 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009294 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
9295 grid $top.rev x -pady 10 -padx 5
9296 ${NS}::label $top.flab -text [mc "Output file:"]
9297 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009298 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
9299 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009300 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009301 ${NS}::frame $top.buts
9302 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
9303 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009304 bind $top <Key-Return> mkpatchgo
9305 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10009306 grid $top.buts.gen $top.buts.can
9307 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9308 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9309 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009310 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10009311}
9312
9313proc mkpatchrev {} {
9314 global patchtop
9315
9316 set oldid [$patchtop.fromsha1 get]
9317 set oldhead [$patchtop.fromhead get]
9318 set newid [$patchtop.tosha1 get]
9319 set newhead [$patchtop.tohead get]
9320 foreach e [list fromsha1 fromhead tosha1 tohead] \
Denton Liue2445882020-09-10 21:36:33 -07009321 v [list $newid $newhead $oldid $oldhead] {
9322 $patchtop.$e conf -state normal
9323 $patchtop.$e delete 0 end
9324 $patchtop.$e insert 0 $v
9325 $patchtop.$e conf -state readonly
Paul Mackerras74daedb2005-06-27 19:27:32 +10009326 }
9327}
9328
9329proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10009330 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10009331
9332 set oldid [$patchtop.fromsha1 get]
9333 set newid [$patchtop.tosha1 get]
9334 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10009335 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10009336 # trim off the initial "|"
9337 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009338 lappend cmd >$fname &
9339 if {[catch {eval exec $cmd} err]} {
Denton Liue2445882020-09-10 21:36:33 -07009340 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009341 }
9342 catch {destroy $patchtop}
9343 unset patchtop
9344}
9345
9346proc mkpatchcan {} {
9347 global patchtop
9348
9349 catch {destroy $patchtop}
9350 unset patchtop
9351}
9352
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009353proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009354 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009355
9356 set top .maketag
9357 set mktagtop $top
9358 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009359 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009360 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009361 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009362 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009363 ${NS}::label $top.id -text [mc "ID:"]
9364 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009365 $top.sha1 insert 0 $rowmenuid
9366 $top.sha1 conf -state readonly
9367 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009368 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009369 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9370 $top.head conf -state readonly
9371 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009372 ${NS}::label $top.tlab -text [mc "Tag name:"]
9373 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009374 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009375 ${NS}::label $top.op -text [mc "Tag message is optional"]
9376 grid $top.op -columnspan 2 -sticky we
9377 ${NS}::label $top.mlab -text [mc "Tag message:"]
9378 ${NS}::entry $top.msg -width 60
9379 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009380 ${NS}::frame $top.buts
9381 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9382 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009383 bind $top <Key-Return> mktaggo
9384 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009385 grid $top.buts.gen $top.buts.can
9386 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9387 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9388 grid $top.buts - -pady 10 -sticky ew
9389 focus $top.tag
9390}
9391
9392proc domktag {} {
9393 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009394
9395 set id [$mktagtop.sha1 get]
9396 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009397 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009398 if {$tag == {}} {
Denton Liue2445882020-09-10 21:36:33 -07009399 error_popup [mc "No tag name specified"] $mktagtop
9400 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009401 }
9402 if {[info exists tagids($tag)]} {
Denton Liue2445882020-09-10 21:36:33 -07009403 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9404 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009405 }
9406 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07009407 if {$msg != {}} {
9408 exec git tag -a -m $msg $tag $id
9409 } else {
9410 exec git tag $tag $id
9411 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009412 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07009413 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9414 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009415 }
9416
9417 set tagids($tag) $id
9418 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009419 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009420 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009421 dispneartags 0
9422 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009423 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009424}
9425
9426proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009427 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009428 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009429 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009430
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009431 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009432 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009433 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009434 if {$id eq $mainheadid} {
Denton Liue2445882020-09-10 21:36:33 -07009435 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009436 } else {
Denton Liue2445882020-09-10 21:36:33 -07009437 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009438 }
9439 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009440 $canv delete tag.$id
9441 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009442 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9443 set text [$canv itemcget $linehtag($id) -text]
9444 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009445 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009446 if {$xr > $canvxmax} {
Denton Liue2445882020-09-10 21:36:33 -07009447 set canvxmax $xr
9448 setcanvscroll
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009449 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009450 if {[info exists currentid] && $currentid == $id} {
Denton Liue2445882020-09-10 21:36:33 -07009451 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009452 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009453 if {[info exists markedid] && $markedid eq $id} {
Denton Liue2445882020-09-10 21:36:33 -07009454 make_idmark $id
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009455 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009456}
9457
9458proc mktagcan {} {
9459 global mktagtop
9460
9461 catch {destroy $mktagtop}
9462 unset mktagtop
9463}
9464
9465proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009466 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009467 mktagcan
9468}
9469
Beat Bollib8b60952019-12-12 16:44:50 -08009470proc copyreference {} {
Beat Bollid835dbb2015-07-18 13:15:39 +02009471 global rowmenuid autosellen
9472
9473 set format "%h (\"%s\", %ad)"
9474 set cmd [list git show -s --pretty=format:$format --date=short]
9475 if {$autosellen < 40} {
9476 lappend cmd --abbrev=$autosellen
9477 }
Beat Bollib8b60952019-12-12 16:44:50 -08009478 set reference [eval exec $cmd $rowmenuid]
Beat Bollid835dbb2015-07-18 13:15:39 +02009479
9480 clipboard clear
Beat Bollib8b60952019-12-12 16:44:50 -08009481 clipboard append $reference
Beat Bollid835dbb2015-07-18 13:15:39 +02009482}
9483
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009484proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009485 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009486
9487 set top .writecommit
9488 set wrcomtop $top
9489 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009490 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009491 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009492 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009493 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009494 ${NS}::label $top.id -text [mc "ID:"]
9495 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009496 $top.sha1 insert 0 $rowmenuid
9497 $top.sha1 conf -state readonly
9498 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009499 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009500 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9501 $top.head conf -state readonly
9502 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009503 ${NS}::label $top.clab -text [mc "Command:"]
9504 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009505 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009506 ${NS}::label $top.flab -text [mc "Output file:"]
9507 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009508 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9509 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009510 ${NS}::frame $top.buts
9511 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9512 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009513 bind $top <Key-Return> wrcomgo
9514 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009515 grid $top.buts.gen $top.buts.can
9516 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9517 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9518 grid $top.buts - -pady 10 -sticky ew
9519 focus $top.fname
9520}
9521
9522proc wrcomgo {} {
9523 global wrcomtop
9524
9525 set id [$wrcomtop.sha1 get]
9526 set cmd "echo $id | [$wrcomtop.cmd get]"
9527 set fname [$wrcomtop.fname get]
9528 if {[catch {exec sh -c $cmd >$fname &} err]} {
Denton Liue2445882020-09-10 21:36:33 -07009529 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009530 }
9531 catch {destroy $wrcomtop}
9532 unset wrcomtop
9533}
9534
9535proc wrcomcan {} {
9536 global wrcomtop
9537
9538 catch {destroy $wrcomtop}
9539 unset wrcomtop
9540}
9541
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009542proc mkbranch {} {
Rogier Goossens5a046c52016-03-19 19:32:16 +01009543 global NS rowmenuid
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009544
Rogier Goossens5a046c52016-03-19 19:32:16 +01009545 set top .branchdialog
9546
9547 set val(name) ""
9548 set val(id) $rowmenuid
9549 set val(command) [list mkbrgo $top]
9550
9551 set ui(title) [mc "Create branch"]
9552 set ui(accept) [mc "Create"]
9553
9554 branchdia $top val ui
9555}
9556
9557proc mvbranch {} {
9558 global NS
9559 global headmenuid headmenuhead
9560
9561 set top .branchdialog
9562
9563 set val(name) $headmenuhead
9564 set val(id) $headmenuid
9565 set val(command) [list mvbrgo $top $headmenuhead]
9566
9567 set ui(title) [mc "Rename branch %s" $headmenuhead]
9568 set ui(accept) [mc "Rename"]
9569
9570 branchdia $top val ui
9571}
9572
9573proc branchdia {top valvar uivar} {
Rogier Goossens7f00f4c2016-03-27 09:21:01 +02009574 global NS commitinfo
Rogier Goossens5a046c52016-03-19 19:32:16 +01009575 upvar $valvar val $uivar ui
9576
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009577 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009578 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009579 make_transient $top .
Rogier Goossens5a046c52016-03-19 19:32:16 +01009580 ${NS}::label $top.title -text $ui(title)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009581 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009582 ${NS}::label $top.id -text [mc "ID:"]
9583 ${NS}::entry $top.sha1 -width 40
Rogier Goossens5a046c52016-03-19 19:32:16 +01009584 $top.sha1 insert 0 $val(id)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009585 $top.sha1 conf -state readonly
9586 grid $top.id $top.sha1 -sticky w
Rogier Goossens7f00f4c2016-03-27 09:21:01 +02009587 ${NS}::entry $top.head -width 60
9588 $top.head insert 0 [lindex $commitinfo($val(id)) 0]
9589 $top.head conf -state readonly
9590 grid x $top.head -sticky ew
9591 grid columnconfigure $top 1 -weight 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01009592 ${NS}::label $top.nlab -text [mc "Name:"]
9593 ${NS}::entry $top.name -width 40
Rogier Goossens5a046c52016-03-19 19:32:16 +01009594 $top.name insert 0 $val(name)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009595 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009596 ${NS}::frame $top.buts
Rogier Goossens5a046c52016-03-19 19:32:16 +01009597 ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)
Pat Thoytsd93f1712009-04-17 01:24:35 +01009598 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Rogier Goossens5a046c52016-03-19 19:32:16 +01009599 bind $top <Key-Return> $val(command)
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009600 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009601 grid $top.buts.go $top.buts.can
9602 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9603 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9604 grid $top.buts - -pady 10 -sticky ew
9605 focus $top.name
9606}
9607
9608proc mkbrgo {top} {
9609 global headids idheads
9610
9611 set name [$top.name get]
9612 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009613 set cmdargs {}
9614 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009615 if {$name eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07009616 error_popup [mc "Please specify a name for the new branch"] $top
9617 return
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009618 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009619 if {[info exists headids($name)]} {
Denton Liue2445882020-09-10 21:36:33 -07009620 if {![confirm_popup [mc \
9621 "Branch '%s' already exists. Overwrite?" $name] $top]} {
9622 return
9623 }
9624 set old_id $headids($name)
9625 lappend cmdargs -f
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009626 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009627 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009628 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009629 nowbusy newbranch
9630 update
9631 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07009632 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009633 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07009634 notbusy newbranch
9635 error_popup $err
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009636 } else {
Denton Liue2445882020-09-10 21:36:33 -07009637 notbusy newbranch
9638 if {$old_id ne {}} {
9639 movehead $id $name
9640 movedhead $id $name
9641 redrawtags $old_id
9642 redrawtags $id
9643 } else {
9644 set headids($name) $id
9645 lappend idheads($id) $name
9646 addedhead $id $name
9647 redrawtags $id
9648 }
9649 dispneartags 0
9650 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009651 }
9652}
9653
Rogier Goossens5a046c52016-03-19 19:32:16 +01009654proc mvbrgo {top prevname} {
9655 global headids idheads mainhead mainheadid
9656
9657 set name [$top.name get]
9658 set id [$top.sha1 get]
9659 set cmdargs {}
9660 if {$name eq $prevname} {
Denton Liue2445882020-09-10 21:36:33 -07009661 catch {destroy $top}
9662 return
Rogier Goossens5a046c52016-03-19 19:32:16 +01009663 }
9664 if {$name eq {}} {
Denton Liue2445882020-09-10 21:36:33 -07009665 error_popup [mc "Please specify a new name for the branch"] $top
9666 return
Rogier Goossens5a046c52016-03-19 19:32:16 +01009667 }
9668 catch {destroy $top}
9669 lappend cmdargs -m $prevname $name
9670 nowbusy renamebranch
9671 update
9672 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07009673 eval exec git branch $cmdargs
Rogier Goossens5a046c52016-03-19 19:32:16 +01009674 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07009675 notbusy renamebranch
9676 error_popup $err
Rogier Goossens5a046c52016-03-19 19:32:16 +01009677 } else {
Denton Liue2445882020-09-10 21:36:33 -07009678 notbusy renamebranch
9679 removehead $id $prevname
9680 removedhead $id $prevname
9681 set headids($name) $id
9682 lappend idheads($id) $name
9683 addedhead $id $name
9684 if {$prevname eq $mainhead} {
9685 set mainhead $name
9686 set mainheadid $id
9687 }
9688 redrawtags $id
9689 dispneartags 0
9690 run refill_reflist
Rogier Goossens5a046c52016-03-19 19:32:16 +01009691 }
9692}
9693
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009694proc exec_citool {tool_args {baseid {}}} {
9695 global commitinfo env
9696
9697 set save_env [array get env GIT_AUTHOR_*]
9698
9699 if {$baseid ne {}} {
Denton Liue2445882020-09-10 21:36:33 -07009700 if {![info exists commitinfo($baseid)]} {
9701 getcommit $baseid
9702 }
9703 set author [lindex $commitinfo($baseid) 1]
9704 set date [lindex $commitinfo($baseid) 2]
9705 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9706 $author author name email]
9707 && $date ne {}} {
9708 set env(GIT_AUTHOR_NAME) $name
9709 set env(GIT_AUTHOR_EMAIL) $email
9710 set env(GIT_AUTHOR_DATE) $date
9711 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009712 }
9713
9714 eval exec git citool $tool_args &
9715
9716 array unset env GIT_AUTHOR_*
9717 array set env $save_env
9718}
9719
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009720proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009721 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009722 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009723 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009724
Paul Mackerrase11f1232007-06-16 20:29:25 +10009725 set oldhead [exec git rev-parse HEAD]
9726 set dheads [descheads $rowmenuid]
9727 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07009728 set ok [confirm_popup [mc "Commit %s is already\
9729 included in branch %s -- really re-apply it?" \
9730 [string range $rowmenuid 0 7] $mainhead]]
9731 if {!$ok} return
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009732 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009733 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009734 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009735 # Unfortunately git-cherry-pick writes stuff to stderr even when
9736 # no error occurs, and exec takes that as an indication of error...
9737 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
Denton Liue2445882020-09-10 21:36:33 -07009738 notbusy cherrypick
9739 if {[regexp -line \
9740 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9741 $err msg fname]} {
9742 error_popup [mc "Cherry-pick failed because of local changes\
9743 to file '%s'.\nPlease commit, reset or stash\
9744 your changes and try again." $fname]
9745 } elseif {[regexp -line \
9746 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
9747 $err]} {
9748 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9749 conflict.\nDo you wish to run git citool to\
9750 resolve it?"]]} {
9751 # Force citool to read MERGE_MSG
9752 file delete [file join $gitdir "GITGUI_MSG"]
9753 exec_citool {} $rowmenuid
9754 }
9755 } else {
9756 error_popup $err
9757 }
9758 run updatecommits
9759 return
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009760 }
9761 set newhead [exec git rev-parse HEAD]
9762 if {$newhead eq $oldhead} {
Denton Liue2445882020-09-10 21:36:33 -07009763 notbusy cherrypick
9764 error_popup [mc "No changes committed"]
9765 return
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009766 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009767 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009768 if {[commitinview $oldhead $curview]} {
Denton Liue2445882020-09-10 21:36:33 -07009769 # XXX this isn't right if we have a path limit...
9770 insertrow $newhead $oldhead $curview
9771 if {$mainhead ne {}} {
9772 movehead $newhead $mainhead
9773 movedhead $newhead $mainhead
9774 }
9775 set mainheadid $newhead
9776 redrawtags $oldhead
9777 redrawtags $newhead
9778 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009779 }
9780 notbusy cherrypick
9781}
9782
Knut Franke8f3ff932013-04-27 16:36:13 +02009783proc revert {} {
9784 global rowmenuid curview
9785 global mainhead mainheadid
9786 global gitdir
9787
9788 set oldhead [exec git rev-parse HEAD]
9789 set dheads [descheads $rowmenuid]
9790 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9791 set ok [confirm_popup [mc "Commit %s is not\
9792 included in branch %s -- really revert it?" \
9793 [string range $rowmenuid 0 7] $mainhead]]
9794 if {!$ok} return
9795 }
9796 nowbusy revert [mc "Reverting"]
9797 update
9798
9799 if [catch {exec git revert --no-edit $rowmenuid} err] {
9800 notbusy revert
9801 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9802 $err match files] {
9803 regsub {\n( |\t)+} $files "\n" files
9804 error_popup [mc "Revert failed because of local changes to\
9805 the following files:%s Please commit, reset or stash \
9806 your changes and try again." $files]
9807 } elseif [regexp {error: could not revert} $err] {
9808 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9809 Do you wish to run git citool to resolve it?"]] {
9810 # Force citool to read MERGE_MSG
9811 file delete [file join $gitdir "GITGUI_MSG"]
9812 exec_citool {} $rowmenuid
9813 }
9814 } else { error_popup $err }
9815 run updatecommits
9816 return
9817 }
9818
9819 set newhead [exec git rev-parse HEAD]
9820 if { $newhead eq $oldhead } {
9821 notbusy revert
9822 error_popup [mc "No changes committed"]
9823 return
9824 }
9825
9826 addnewchild $newhead $oldhead
9827
9828 if [commitinview $oldhead $curview] {
9829 # XXX this isn't right if we have a path limit...
9830 insertrow $newhead $oldhead $curview
9831 if {$mainhead ne {}} {
9832 movehead $newhead $mainhead
9833 movedhead $newhead $mainhead
9834 }
9835 set mainheadid $newhead
9836 redrawtags $oldhead
9837 redrawtags $newhead
9838 selbyid $newhead
9839 }
9840
9841 notbusy revert
9842}
9843
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009844proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009845 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009846
9847 set confirm_ok 0
9848 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009849 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009850 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009851 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009852 ${NS}::label $w.m -text \
Denton Liue2445882020-09-10 21:36:33 -07009853 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009854 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009855 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009856 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009857 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Denton Liue2445882020-09-10 21:36:33 -07009858 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009859 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009860 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Denton Liue2445882020-09-10 21:36:33 -07009861 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009862 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009863 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Denton Liue2445882020-09-10 21:36:33 -07009864 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009865 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009866 pack $w.f -side top -fill x -padx 4
9867 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009868 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009869 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009870 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009871 pack $w.cancel -side right -fill x -padx 20 -pady 20
9872 bind $w <Visibility> "grab $w; focus $w"
9873 tkwait window $w
9874 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009875 if {[catch {set fd [open \
Denton Liue2445882020-09-10 21:36:33 -07009876 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
9877 error_popup $err
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009878 } else {
Denton Liue2445882020-09-10 21:36:33 -07009879 dohidelocalchanges
9880 filerun $fd [list readresetstat $fd]
9881 nowbusy reset [mc "Resetting"]
9882 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009883 }
9884}
9885
Paul Mackerrasa137a902007-10-23 21:12:49 +10009886proc readresetstat {fd} {
9887 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009888
9889 if {[gets $fd line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07009890 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9891 set rprogcoord [expr {1.0 * $m / $n}]
9892 adjustprogress
9893 }
9894 return 1
Paul Mackerras706d6c32007-06-26 11:09:49 +10009895 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009896 set rprogcoord 0
9897 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009898 notbusy reset
9899 if {[catch {close $fd} err]} {
Denton Liue2445882020-09-10 21:36:33 -07009900 error_popup $err
Paul Mackerras706d6c32007-06-26 11:09:49 +10009901 }
9902 set oldhead $mainheadid
9903 set newhead [exec git rev-parse HEAD]
9904 if {$newhead ne $oldhead} {
Denton Liue2445882020-09-10 21:36:33 -07009905 movehead $newhead $mainhead
9906 movedhead $newhead $mainhead
9907 set mainheadid $newhead
9908 redrawtags $oldhead
9909 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009910 }
9911 if {$showlocalchanges} {
Denton Liue2445882020-09-10 21:36:33 -07009912 doshowlocalchanges
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009913 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009914 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009915}
9916
Paul Mackerras10299152006-08-02 09:52:01 +10009917# context menu for a head
9918proc headmenu {x y id head} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009919 global headmenuid headmenuhead headctxmenu mainhead headids
Paul Mackerras10299152006-08-02 09:52:01 +10009920
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009921 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009922 set headmenuid $id
9923 set headmenuhead $head
Rogier Goossens5a046c52016-03-19 19:32:16 +01009924 array set state {0 normal 1 normal 2 normal}
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309925 if {[string match "remotes/*" $head]} {
Denton Liue2445882020-09-10 21:36:33 -07009926 set localhead [string range $head [expr [string last / $head] + 1] end]
9927 if {[info exists headids($localhead)]} {
9928 set state(0) disabled
9929 }
9930 array set state {1 disabled 2 disabled}
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309931 }
Paul Mackerras00609462007-06-17 17:08:35 +10009932 if {$head eq $mainhead} {
Denton Liue2445882020-09-10 21:36:33 -07009933 array set state {0 disabled 2 disabled}
Paul Mackerras00609462007-06-17 17:08:35 +10009934 }
Rogier Goossens5a046c52016-03-19 19:32:16 +01009935 foreach i {0 1 2} {
Denton Liue2445882020-09-10 21:36:33 -07009936 $headctxmenu entryconfigure $i -state $state($i)
Rogier Goossens5a046c52016-03-19 19:32:16 +01009937 }
Paul Mackerras10299152006-08-02 09:52:01 +10009938 tk_popup $headctxmenu $x $y
9939}
9940
9941proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009942 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009943 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009944
9945 # check the tree is clean first??
Rogier Goossens02e6a062016-03-19 19:33:03 +01009946 set newhead $headmenuhead
9947 set command [list | git checkout]
9948 if {[string match "remotes/*" $newhead]} {
Denton Liue2445882020-09-10 21:36:33 -07009949 set remote $newhead
9950 set newhead [string range $newhead [expr [string last / $newhead] + 1] end]
9951 # The following check is redundant - the menu option should
9952 # be disabled to begin with...
9953 if {[info exists headids($newhead)]} {
9954 error_popup [mc "A local branch named %s exists already" $newhead]
9955 return
9956 }
9957 lappend command -b $newhead --track $remote
Rogier Goossens02e6a062016-03-19 19:33:03 +01009958 } else {
Denton Liue2445882020-09-10 21:36:33 -07009959 lappend command $newhead
Rogier Goossens02e6a062016-03-19 19:33:03 +01009960 }
9961 lappend command 2>@1
Christian Stimmingd990ced2007-11-07 18:42:55 +01009962 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009963 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009964 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009965 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -07009966 set fd [open $command r]
Paul Mackerras10299152006-08-02 09:52:01 +10009967 } err]} {
Denton Liue2445882020-09-10 21:36:33 -07009968 notbusy checkout
9969 error_popup $err
9970 if {$showlocalchanges} {
9971 dodiffindex
9972 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009973 } else {
Denton Liue2445882020-09-10 21:36:33 -07009974 filerun $fd [list readcheckoutstat $fd $newhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009975 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009976}
9977
9978proc readcheckoutstat {fd newhead newheadid} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009979 global mainhead mainheadid headids idheads showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009980 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009981
9982 if {[gets $fd line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -07009983 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9984 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9985 adjustprogress
9986 }
9987 return 1
Paul Mackerras08ba8202008-05-12 10:18:38 +10009988 }
9989 set progresscoords {0 0}
9990 adjustprogress
9991 notbusy checkout
9992 if {[catch {close $fd} err]} {
Denton Liue2445882020-09-10 21:36:33 -07009993 error_popup $err
9994 return
Paul Mackerras08ba8202008-05-12 10:18:38 +10009995 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009996 set oldmainid $mainheadid
Rogier Goossens02e6a062016-03-19 19:33:03 +01009997 if {! [info exists headids($newhead)]} {
Denton Liue2445882020-09-10 21:36:33 -07009998 set headids($newhead) $newheadid
9999 lappend idheads($newheadid) $newhead
10000 addedhead $newheadid $newhead
Rogier Goossens02e6a062016-03-19 19:33:03 +010010001 }
Paul Mackerras08ba8202008-05-12 10:18:38 +100010002 set mainhead $newhead
10003 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +110010004 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010005 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +100010006 redrawtags $newheadid
10007 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +100010008 if {$showlocalchanges} {
Denton Liue2445882020-09-10 21:36:33 -070010009 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +100010010 }
10011}
10012
10013proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010014 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +100010015 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +100010016
10017 set head $headmenuhead
10018 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +100010019 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +100010020 if {$head eq $mainhead} {
Denton Liue2445882020-09-10 21:36:33 -070010021 error_popup [mc "Cannot delete the currently checked-out branch"]
10022 return
Paul Mackerras10299152006-08-02 09:52:01 +100010023 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010024 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +100010025 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Denton Liue2445882020-09-10 21:36:33 -070010026 # the stuff on this branch isn't on any other branch
10027 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
10028 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +100010029 }
10030 nowbusy rmbranch
10031 update
10032 if {[catch {exec git branch -D $head} err]} {
Denton Liue2445882020-09-10 21:36:33 -070010033 notbusy rmbranch
10034 error_popup $err
10035 return
Paul Mackerras10299152006-08-02 09:52:01 +100010036 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010037 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010038 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +100010039 redrawtags $id
10040 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +100010041 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +100010042 run refill_reflist
10043}
10044
10045# Display a list of tags and heads
10046proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010010047 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +100010048 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +100010049
10050 set top .showrefs
10051 set showrefstop $top
10052 if {[winfo exists $top]} {
Denton Liue2445882020-09-10 21:36:33 -070010053 raise $top
10054 refill_reflist
10055 return
Paul Mackerras887c9962007-08-20 19:36:20 +100010056 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010010057 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010010058 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010059 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +100010060 text $top.list -background $bgcolor -foreground $fgcolor \
Denton Liue2445882020-09-10 21:36:33 -070010061 -selectbackground $selectbgcolor -font mainfont \
10062 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
10063 -width 30 -height 20 -cursor $maincursor \
10064 -spacing1 1 -spacing3 1 -state disabled
Paul Mackerras887c9962007-08-20 19:36:20 +100010065 $top.list tag configure highlight -background $selectbgcolor
Paul Mackerraseb859df2015-05-03 15:11:29 +100010066 if {![lsearch -exact $bglist $top.list]} {
Denton Liue2445882020-09-10 21:36:33 -070010067 lappend bglist $top.list
10068 lappend fglist $top.list
Paul Mackerraseb859df2015-05-03 15:11:29 +100010069 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010010070 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
10071 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +100010072 grid $top.list $top.ysb -sticky nsew
10073 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010010074 ${NS}::frame $top.f
10075 ${NS}::label $top.f.l -text "[mc "Filter"]: "
10076 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +100010077 set reflistfilter "*"
10078 trace add variable reflistfilter write reflistfilter_change
10079 pack $top.f.e -side right -fill x -expand 1
10080 pack $top.f.l -side left
10081 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +010010082 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010083 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +100010084 grid $top.close -
10085 grid columnconfigure $top 0 -weight 1
10086 grid rowconfigure $top 0 -weight 1
10087 bind $top.list <1> {break}
10088 bind $top.list <B1-Motion> {break}
10089 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
10090 set reflist {}
10091 refill_reflist
10092}
10093
10094proc sel_reflist {w x y} {
10095 global showrefstop reflist headids tagids otherrefids
10096
10097 if {![winfo exists $showrefstop]} return
10098 set l [lindex [split [$w index "@$x,$y"] "."] 0]
10099 set ref [lindex $reflist [expr {$l-1}]]
10100 set n [lindex $ref 0]
10101 switch -- [lindex $ref 1] {
Denton Liue2445882020-09-10 21:36:33 -070010102 "H" {selbyid $headids($n)}
10103 "R" {selbyid $headids($n)}
10104 "T" {selbyid $tagids($n)}
10105 "o" {selbyid $otherrefids($n)}
Paul Mackerras887c9962007-08-20 19:36:20 +100010106 }
10107 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
10108}
10109
10110proc unsel_reflist {} {
10111 global showrefstop
10112
10113 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
10114 $showrefstop.list tag remove highlight 0.0 end
10115}
10116
10117proc reflistfilter_change {n1 n2 op} {
10118 global reflistfilter
10119
10120 after cancel refill_reflist
10121 after 200 refill_reflist
10122}
10123
10124proc refill_reflist {} {
10125 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010126 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +100010127
10128 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
10129 set refs {}
10130 foreach n [array names headids] {
Denton Liue2445882020-09-10 21:36:33 -070010131 if {[string match $reflistfilter $n]} {
10132 if {[commitinview $headids($n) $curview]} {
10133 if {[string match "remotes/*" $n]} {
10134 lappend refs [list $n R]
10135 } else {
10136 lappend refs [list $n H]
10137 }
10138 } else {
10139 interestedin $headids($n) {run refill_reflist}
10140 }
10141 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010142 }
10143 foreach n [array names tagids] {
Denton Liue2445882020-09-10 21:36:33 -070010144 if {[string match $reflistfilter $n]} {
10145 if {[commitinview $tagids($n) $curview]} {
10146 lappend refs [list $n T]
10147 } else {
10148 interestedin $tagids($n) {run refill_reflist}
10149 }
10150 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010151 }
10152 foreach n [array names otherrefids] {
Denton Liue2445882020-09-10 21:36:33 -070010153 if {[string match $reflistfilter $n]} {
10154 if {[commitinview $otherrefids($n) $curview]} {
10155 lappend refs [list $n o]
10156 } else {
10157 interestedin $otherrefids($n) {run refill_reflist}
10158 }
10159 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010160 }
10161 set refs [lsort -index 0 $refs]
10162 if {$refs eq $reflist} return
10163
10164 # Update the contents of $showrefstop.list according to the
10165 # differences between $reflist (old) and $refs (new)
10166 $showrefstop.list conf -state normal
10167 $showrefstop.list insert end "\n"
10168 set i 0
10169 set j 0
10170 while {$i < [llength $reflist] || $j < [llength $refs]} {
Denton Liue2445882020-09-10 21:36:33 -070010171 if {$i < [llength $reflist]} {
10172 if {$j < [llength $refs]} {
10173 set cmp [string compare [lindex $reflist $i 0] \
10174 [lindex $refs $j 0]]
10175 if {$cmp == 0} {
10176 set cmp [string compare [lindex $reflist $i 1] \
10177 [lindex $refs $j 1]]
10178 }
10179 } else {
10180 set cmp -1
10181 }
10182 } else {
10183 set cmp 1
10184 }
10185 switch -- $cmp {
10186 -1 {
10187 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
10188 incr i
10189 }
10190 0 {
10191 incr i
10192 incr j
10193 }
10194 1 {
10195 set l [expr {$j + 1}]
10196 $showrefstop.list image create $l.0 -align baseline \
10197 -image reficon-[lindex $refs $j 1] -padx 2
10198 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
10199 incr j
10200 }
10201 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010202 }
10203 set reflist $refs
10204 # delete last newline
10205 $showrefstop.list delete end-2c end-1c
10206 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +100010207}
10208
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010209# Stuff for finding nearby tags
10210proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010211 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
10212 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010213 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010214
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010215 if {![info exists allcommits]} {
Denton Liue2445882020-09-10 21:36:33 -070010216 set nextarc 0
10217 set allcommits 0
10218 set seeds {}
10219 set allcwait 0
10220 set cachedarcs 0
10221 set allccache [file join $gitdir "gitk.cache"]
10222 if {![catch {
10223 set f [open $allccache r]
10224 set allcwait 1
10225 getcache $f
10226 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010227 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010228
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010229 if {$allcwait} {
Denton Liue2445882020-09-10 21:36:33 -070010230 return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010231 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010232 set cmd [list | git rev-list --parents]
10233 set allcupdate [expr {$seeds ne {}}]
10234 if {!$allcupdate} {
Denton Liue2445882020-09-10 21:36:33 -070010235 set ids "--all"
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010236 } else {
Denton Liue2445882020-09-10 21:36:33 -070010237 set refs [concat [array names idheads] [array names idtags] \
10238 [array names idotherrefs]]
10239 set ids {}
10240 set tagobjs {}
10241 foreach name [array names tagobjid] {
10242 lappend tagobjs $tagobjid($name)
10243 }
10244 foreach id [lsort -unique $refs] {
10245 if {![info exists allparents($id)] &&
10246 [lsearch -exact $tagobjs $id] < 0} {
10247 lappend ids $id
10248 }
10249 }
10250 if {$ids ne {}} {
10251 foreach id $seeds {
10252 lappend ids "^$id"
10253 }
Johannes Schindelinbb5cb232023-01-24 11:23:16 +000010254 lappend ids "--"
Denton Liue2445882020-09-10 21:36:33 -070010255 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010256 }
10257 if {$ids ne {}} {
Johannes Schindelinbb5cb232023-01-24 11:23:16 +000010258 if {$ids eq "--all"} {
10259 set cmd [concat $cmd "--all"]
10260 } else {
10261 set cmd [concat $cmd --stdin "<<[join $ids "\\n"]"]
10262 }
10263 set fd [open $cmd r]
Denton Liue2445882020-09-10 21:36:33 -070010264 fconfigure $fd -blocking 0
10265 incr allcommits
10266 nowbusy allcommits
10267 filerun $fd [list getallclines $fd]
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010268 } else {
Denton Liue2445882020-09-10 21:36:33 -070010269 dispneartags 0
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010270 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010271}
10272
Paul Mackerrase11f1232007-06-16 20:29:25 +100010273# Since most commits have 1 parent and 1 child, we group strings of
10274# such commits into "arcs" joining branch/merge points (BMPs), which
10275# are commits that either don't have 1 parent or don't have 1 child.
10276#
10277# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
10278# arcout(id) - outgoing arcs for BMP
10279# arcids(a) - list of IDs on arc including end but not start
10280# arcstart(a) - BMP ID at start of arc
10281# arcend(a) - BMP ID at end of arc
10282# growing(a) - arc a is still growing
10283# arctags(a) - IDs out of arcids (excluding end) that have tags
10284# archeads(a) - IDs out of arcids (excluding end) that have heads
10285# The start of an arc is at the descendent end, so "incoming" means
10286# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010287
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010288proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010289 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010290 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010291 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +010010292
Paul Mackerrase11f1232007-06-16 20:29:25 +100010293 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010294 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Denton Liue2445882020-09-10 21:36:33 -070010295 set id [lindex $line 0]
10296 if {[info exists allparents($id)]} {
10297 # seen it already
10298 continue
10299 }
10300 set cachedarcs 0
10301 set olds [lrange $line 1 end]
10302 set allparents($id) $olds
10303 if {![info exists allchildren($id)]} {
10304 set allchildren($id) {}
10305 set arcnos($id) {}
10306 lappend seeds $id
10307 } else {
10308 set a $arcnos($id)
10309 if {[llength $olds] == 1 && [llength $a] == 1} {
10310 lappend arcids($a) $id
10311 if {[info exists idtags($id)]} {
10312 lappend arctags($a) $id
10313 }
10314 if {[info exists idheads($id)]} {
10315 lappend archeads($a) $id
10316 }
10317 if {[info exists allparents($olds)]} {
10318 # seen parent already
10319 if {![info exists arcout($olds)]} {
10320 splitarc $olds
10321 }
10322 lappend arcids($a) $olds
10323 set arcend($a) $olds
10324 unset growing($a)
10325 }
10326 lappend allchildren($olds) $id
10327 lappend arcnos($olds) $a
10328 continue
10329 }
10330 }
10331 foreach a $arcnos($id) {
10332 lappend arcids($a) $id
10333 set arcend($a) $id
10334 unset growing($a)
10335 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010336
Denton Liue2445882020-09-10 21:36:33 -070010337 set ao {}
10338 foreach p $olds {
10339 lappend allchildren($p) $id
10340 set a [incr nextarc]
10341 set arcstart($a) $id
10342 set archeads($a) {}
10343 set arctags($a) {}
10344 set archeads($a) {}
10345 set arcids($a) {}
10346 lappend ao $a
10347 set growing($a) 1
10348 if {[info exists allparents($p)]} {
10349 # seen it already, may need to make a new branch
10350 if {![info exists arcout($p)]} {
10351 splitarc $p
10352 }
10353 lappend arcids($a) $p
10354 set arcend($a) $p
10355 unset growing($a)
10356 }
10357 lappend arcnos($p) $a
10358 }
10359 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010360 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010361 if {$nid > 0} {
Denton Liue2445882020-09-10 21:36:33 -070010362 global cached_dheads cached_dtags cached_atags
10363 unset -nocomplain cached_dheads
10364 unset -nocomplain cached_dtags
10365 unset -nocomplain cached_atags
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010366 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010367 if {![eof $fd]} {
Denton Liue2445882020-09-10 21:36:33 -070010368 return [expr {$nid >= 1000? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010369 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010370 set cacheok 1
10371 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -070010372 fconfigure $fd -blocking 1
10373 close $fd
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010374 } err]} {
Denton Liue2445882020-09-10 21:36:33 -070010375 # got an error reading the list of commits
10376 # if we were updating, try rereading the whole thing again
10377 if {$allcupdate} {
10378 incr allcommits -1
10379 dropcache $err
10380 return
10381 }
10382 error_popup "[mc "Error reading commit topology information;\
10383 branch and preceding/following tag information\
10384 will be incomplete."]\n($err)"
10385 set cacheok 0
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010386 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010387 if {[incr allcommits -1] == 0} {
Denton Liue2445882020-09-10 21:36:33 -070010388 notbusy allcommits
10389 if {$cacheok} {
10390 run savecache
10391 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010392 }
10393 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010394 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010395}
10396
10397proc recalcarc {a} {
10398 global arctags archeads arcids idtags idheads
10399
10400 set at {}
10401 set ah {}
10402 foreach id [lrange $arcids($a) 0 end-1] {
Denton Liue2445882020-09-10 21:36:33 -070010403 if {[info exists idtags($id)]} {
10404 lappend at $id
10405 }
10406 if {[info exists idheads($id)]} {
10407 lappend ah $id
10408 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010409 }
10410 set arctags($a) $at
10411 set archeads($a) $ah
10412}
10413
10414proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010415 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +100010416 global arcstart arcend arcout allparents growing
10417
10418 set a $arcnos($p)
10419 if {[llength $a] != 1} {
Denton Liue2445882020-09-10 21:36:33 -070010420 puts "oops splitarc called but [llength $a] arcs already"
10421 return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010422 }
10423 set a [lindex $a 0]
10424 set i [lsearch -exact $arcids($a) $p]
10425 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -070010426 puts "oops splitarc $p not in arc $a"
10427 return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010428 }
10429 set na [incr nextarc]
10430 if {[info exists arcend($a)]} {
Denton Liue2445882020-09-10 21:36:33 -070010431 set arcend($na) $arcend($a)
Paul Mackerrase11f1232007-06-16 20:29:25 +100010432 } else {
Denton Liue2445882020-09-10 21:36:33 -070010433 set l [lindex $allparents([lindex $arcids($a) end]) 0]
10434 set j [lsearch -exact $arcnos($l) $a]
10435 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010436 }
10437 set tail [lrange $arcids($a) [expr {$i+1}] end]
10438 set arcids($a) [lrange $arcids($a) 0 $i]
10439 set arcend($a) $p
10440 set arcstart($na) $p
10441 set arcout($p) $na
10442 set arcids($na) $tail
10443 if {[info exists growing($a)]} {
Denton Liue2445882020-09-10 21:36:33 -070010444 set growing($na) 1
10445 unset growing($a)
Paul Mackerrase11f1232007-06-16 20:29:25 +100010446 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010447
10448 foreach id $tail {
Denton Liue2445882020-09-10 21:36:33 -070010449 if {[llength $arcnos($id)] == 1} {
10450 set arcnos($id) $na
10451 } else {
10452 set j [lsearch -exact $arcnos($id) $a]
10453 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
10454 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010455 }
10456
10457 # reconstruct tags and heads lists
10458 if {$arctags($a) ne {} || $archeads($a) ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070010459 recalcarc $a
10460 recalcarc $na
Paul Mackerrase11f1232007-06-16 20:29:25 +100010461 } else {
Denton Liue2445882020-09-10 21:36:33 -070010462 set arctags($na) {}
10463 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010464 }
10465}
10466
Paul Mackerrase11f1232007-06-16 20:29:25 +100010467# Update things for a new commit added that is a child of one
10468# existing commit. Used when cherry-picking.
10469proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010470 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010471 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010472 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010473
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010474 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010475 set allparents($id) [list $p]
10476 set allchildren($id) {}
10477 set arcnos($id) {}
10478 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010479 lappend allchildren($p) $id
10480 set a [incr nextarc]
10481 set arcstart($a) $id
10482 set archeads($a) {}
10483 set arctags($a) {}
10484 set arcids($a) [list $p]
10485 set arcend($a) $p
10486 if {![info exists arcout($p)]} {
Denton Liue2445882020-09-10 21:36:33 -070010487 splitarc $p
Paul Mackerrase11f1232007-06-16 20:29:25 +100010488 }
10489 lappend arcnos($p) $a
10490 set arcout($id) [list $a]
10491}
10492
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010493# This implements a cache for the topology information.
10494# The cache saves, for each arc, the start and end of the arc,
10495# the ids on the arc, and the outgoing arcs from the end.
10496proc readcache {f} {
10497 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10498 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10499 global allcwait
10500
10501 set a $nextarc
10502 set lim $cachedarcs
10503 if {$lim - $a > 500} {
Denton Liue2445882020-09-10 21:36:33 -070010504 set lim [expr {$a + 500}]
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010505 }
10506 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -070010507 if {$a == $lim} {
10508 # finish reading the cache and setting up arctags, etc.
10509 set line [gets $f]
10510 if {$line ne "1"} {error "bad final version"}
10511 close $f
10512 foreach id [array names idtags] {
10513 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10514 [llength $allparents($id)] == 1} {
10515 set a [lindex $arcnos($id) 0]
10516 if {$arctags($a) eq {}} {
10517 recalcarc $a
10518 }
10519 }
10520 }
10521 foreach id [array names idheads] {
10522 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10523 [llength $allparents($id)] == 1} {
10524 set a [lindex $arcnos($id) 0]
10525 if {$archeads($a) eq {}} {
10526 recalcarc $a
10527 }
10528 }
10529 }
10530 foreach id [lsort -unique $possible_seeds] {
10531 if {$arcnos($id) eq {}} {
10532 lappend seeds $id
10533 }
10534 }
10535 set allcwait 0
10536 } else {
10537 while {[incr a] <= $lim} {
10538 set line [gets $f]
10539 if {[llength $line] != 3} {error "bad line"}
10540 set s [lindex $line 0]
10541 set arcstart($a) $s
10542 lappend arcout($s) $a
10543 if {![info exists arcnos($s)]} {
10544 lappend possible_seeds $s
10545 set arcnos($s) {}
10546 }
10547 set e [lindex $line 1]
10548 if {$e eq {}} {
10549 set growing($a) 1
10550 } else {
10551 set arcend($a) $e
10552 if {![info exists arcout($e)]} {
10553 set arcout($e) {}
10554 }
10555 }
10556 set arcids($a) [lindex $line 2]
10557 foreach id $arcids($a) {
10558 lappend allparents($s) $id
10559 set s $id
10560 lappend arcnos($id) $a
10561 }
10562 if {![info exists allparents($s)]} {
10563 set allparents($s) {}
10564 }
10565 set arctags($a) {}
10566 set archeads($a) {}
10567 }
10568 set nextarc [expr {$a - 1}]
10569 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010570 } err]} {
Denton Liue2445882020-09-10 21:36:33 -070010571 dropcache $err
10572 return 0
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010573 }
10574 if {!$allcwait} {
Denton Liue2445882020-09-10 21:36:33 -070010575 getallcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010576 }
10577 return $allcwait
10578}
10579
10580proc getcache {f} {
10581 global nextarc cachedarcs possible_seeds
10582
10583 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -070010584 set line [gets $f]
10585 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10586 # make sure it's an integer
10587 set cachedarcs [expr {int([lindex $line 1])}]
10588 if {$cachedarcs < 0} {error "bad number of arcs"}
10589 set nextarc 0
10590 set possible_seeds {}
10591 run readcache $f
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010592 } err]} {
Denton Liue2445882020-09-10 21:36:33 -070010593 dropcache $err
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010594 }
10595 return 0
10596}
10597
10598proc dropcache {err} {
10599 global allcwait nextarc cachedarcs seeds
10600
10601 #puts "dropping cache ($err)"
10602 foreach v {arcnos arcout arcids arcstart arcend growing \
Denton Liue2445882020-09-10 21:36:33 -070010603 arctags archeads allparents allchildren} {
10604 global $v
10605 unset -nocomplain $v
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010606 }
10607 set allcwait 0
10608 set nextarc 0
10609 set cachedarcs 0
10610 set seeds {}
10611 getallcommits
10612}
10613
10614proc writecache {f} {
10615 global cachearc cachedarcs allccache
10616 global arcstart arcend arcnos arcids arcout
10617
10618 set a $cachearc
10619 set lim $cachedarcs
10620 if {$lim - $a > 1000} {
Denton Liue2445882020-09-10 21:36:33 -070010621 set lim [expr {$a + 1000}]
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010622 }
10623 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -070010624 while {[incr a] <= $lim} {
10625 if {[info exists arcend($a)]} {
10626 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10627 } else {
10628 puts $f [list $arcstart($a) {} $arcids($a)]
10629 }
10630 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010631 } err]} {
Denton Liue2445882020-09-10 21:36:33 -070010632 catch {close $f}
10633 catch {file delete $allccache}
10634 #puts "writing cache failed ($err)"
10635 return 0
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010636 }
10637 set cachearc [expr {$a - 1}]
10638 if {$a > $cachedarcs} {
Denton Liue2445882020-09-10 21:36:33 -070010639 puts $f "1"
10640 close $f
10641 return 0
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010642 }
10643 return 1
10644}
10645
10646proc savecache {} {
10647 global nextarc cachedarcs cachearc allccache
10648
10649 if {$nextarc == $cachedarcs} return
10650 set cachearc 0
10651 set cachedarcs $nextarc
10652 catch {
Denton Liue2445882020-09-10 21:36:33 -070010653 set f [open $allccache w]
10654 puts $f [list 1 $cachedarcs]
10655 run writecache $f
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010656 }
10657}
10658
Paul Mackerrase11f1232007-06-16 20:29:25 +100010659# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10660# or 0 if neither is true.
10661proc anc_or_desc {a b} {
10662 global arcout arcstart arcend arcnos cached_isanc
10663
10664 if {$arcnos($a) eq $arcnos($b)} {
Denton Liue2445882020-09-10 21:36:33 -070010665 # Both are on the same arc(s); either both are the same BMP,
10666 # or if one is not a BMP, the other is also not a BMP or is
10667 # the BMP at end of the arc (and it only has 1 incoming arc).
10668 # Or both can be BMPs with no incoming arcs.
10669 if {$a eq $b || $arcnos($a) eq {}} {
10670 return 0
10671 }
10672 # assert {[llength $arcnos($a)] == 1}
10673 set arc [lindex $arcnos($a) 0]
10674 set i [lsearch -exact $arcids($arc) $a]
10675 set j [lsearch -exact $arcids($arc) $b]
10676 if {$i < 0 || $i > $j} {
10677 return 1
10678 } else {
10679 return -1
10680 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010681 }
10682
10683 if {![info exists arcout($a)]} {
Denton Liue2445882020-09-10 21:36:33 -070010684 set arc [lindex $arcnos($a) 0]
10685 if {[info exists arcend($arc)]} {
10686 set aend $arcend($arc)
10687 } else {
10688 set aend {}
10689 }
10690 set a $arcstart($arc)
Paul Mackerrase11f1232007-06-16 20:29:25 +100010691 } else {
Denton Liue2445882020-09-10 21:36:33 -070010692 set aend $a
Paul Mackerrase11f1232007-06-16 20:29:25 +100010693 }
10694 if {![info exists arcout($b)]} {
Denton Liue2445882020-09-10 21:36:33 -070010695 set arc [lindex $arcnos($b) 0]
10696 if {[info exists arcend($arc)]} {
10697 set bend $arcend($arc)
10698 } else {
10699 set bend {}
10700 }
10701 set b $arcstart($arc)
Paul Mackerrase11f1232007-06-16 20:29:25 +100010702 } else {
Denton Liue2445882020-09-10 21:36:33 -070010703 set bend $b
Paul Mackerrase11f1232007-06-16 20:29:25 +100010704 }
10705 if {$a eq $bend} {
Denton Liue2445882020-09-10 21:36:33 -070010706 return 1
Paul Mackerrase11f1232007-06-16 20:29:25 +100010707 }
10708 if {$b eq $aend} {
Denton Liue2445882020-09-10 21:36:33 -070010709 return -1
Paul Mackerrase11f1232007-06-16 20:29:25 +100010710 }
10711 if {[info exists cached_isanc($a,$bend)]} {
Denton Liue2445882020-09-10 21:36:33 -070010712 if {$cached_isanc($a,$bend)} {
10713 return 1
10714 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010715 }
10716 if {[info exists cached_isanc($b,$aend)]} {
Denton Liue2445882020-09-10 21:36:33 -070010717 if {$cached_isanc($b,$aend)} {
10718 return -1
10719 }
10720 if {[info exists cached_isanc($a,$bend)]} {
10721 return 0
10722 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010723 }
10724
10725 set todo [list $a $b]
10726 set anc($a) a
10727 set anc($b) b
10728 for {set i 0} {$i < [llength $todo]} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070010729 set x [lindex $todo $i]
10730 if {$anc($x) eq {}} {
10731 continue
10732 }
10733 foreach arc $arcnos($x) {
10734 set xd $arcstart($arc)
10735 if {$xd eq $bend} {
10736 set cached_isanc($a,$bend) 1
10737 set cached_isanc($b,$aend) 0
10738 return 1
10739 } elseif {$xd eq $aend} {
10740 set cached_isanc($b,$aend) 1
10741 set cached_isanc($a,$bend) 0
10742 return -1
10743 }
10744 if {![info exists anc($xd)]} {
10745 set anc($xd) $anc($x)
10746 lappend todo $xd
10747 } elseif {$anc($xd) ne $anc($x)} {
10748 set anc($xd) {}
10749 }
10750 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010751 }
10752 set cached_isanc($a,$bend) 0
10753 set cached_isanc($b,$aend) 0
10754 return 0
10755}
10756
10757# This identifies whether $desc has an ancestor that is
10758# a growing tip of the graph and which is not an ancestor of $anc
10759# and returns 0 if so and 1 if not.
10760# If we subsequently discover a tag on such a growing tip, and that
10761# turns out to be a descendent of $anc (which it could, since we
10762# don't necessarily see children before parents), then $desc
10763# isn't a good choice to display as a descendent tag of
10764# $anc (since it is the descendent of another tag which is
10765# a descendent of $anc). Similarly, $anc isn't a good choice to
10766# display as a ancestor tag of $desc.
10767#
10768proc is_certain {desc anc} {
10769 global arcnos arcout arcstart arcend growing problems
10770
10771 set certain {}
10772 if {[llength $arcnos($anc)] == 1} {
Denton Liue2445882020-09-10 21:36:33 -070010773 # tags on the same arc are certain
10774 if {$arcnos($desc) eq $arcnos($anc)} {
10775 return 1
10776 }
10777 if {![info exists arcout($anc)]} {
10778 # if $anc is partway along an arc, use the start of the arc instead
10779 set a [lindex $arcnos($anc) 0]
10780 set anc $arcstart($a)
10781 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010782 }
10783 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
Denton Liue2445882020-09-10 21:36:33 -070010784 set x $desc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010785 } else {
Denton Liue2445882020-09-10 21:36:33 -070010786 set a [lindex $arcnos($desc) 0]
10787 set x $arcend($a)
Paul Mackerrase11f1232007-06-16 20:29:25 +100010788 }
10789 if {$x == $anc} {
Denton Liue2445882020-09-10 21:36:33 -070010790 return 1
Paul Mackerrase11f1232007-06-16 20:29:25 +100010791 }
10792 set anclist [list $x]
10793 set dl($x) 1
10794 set nnh 1
10795 set ngrowanc 0
10796 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070010797 set x [lindex $anclist $i]
10798 if {$dl($x)} {
10799 incr nnh -1
10800 }
10801 set done($x) 1
10802 foreach a $arcout($x) {
10803 if {[info exists growing($a)]} {
10804 if {![info exists growanc($x)] && $dl($x)} {
10805 set growanc($x) 1
10806 incr ngrowanc
10807 }
10808 } else {
10809 set y $arcend($a)
10810 if {[info exists dl($y)]} {
10811 if {$dl($y)} {
10812 if {!$dl($x)} {
10813 set dl($y) 0
10814 if {![info exists done($y)]} {
10815 incr nnh -1
10816 }
10817 if {[info exists growanc($x)]} {
10818 incr ngrowanc -1
10819 }
10820 set xl [list $y]
10821 for {set k 0} {$k < [llength $xl]} {incr k} {
10822 set z [lindex $xl $k]
10823 foreach c $arcout($z) {
10824 if {[info exists arcend($c)]} {
10825 set v $arcend($c)
10826 if {[info exists dl($v)] && $dl($v)} {
10827 set dl($v) 0
10828 if {![info exists done($v)]} {
10829 incr nnh -1
10830 }
10831 if {[info exists growanc($v)]} {
10832 incr ngrowanc -1
10833 }
10834 lappend xl $v
10835 }
10836 }
10837 }
10838 }
10839 }
10840 }
10841 } elseif {$y eq $anc || !$dl($x)} {
10842 set dl($y) 0
10843 lappend anclist $y
10844 } else {
10845 set dl($y) 1
10846 lappend anclist $y
10847 incr nnh
10848 }
10849 }
10850 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010851 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010852 foreach x [array names growanc] {
Denton Liue2445882020-09-10 21:36:33 -070010853 if {$dl($x)} {
10854 return 0
10855 }
10856 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010857 }
10858 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010859}
10860
Paul Mackerrase11f1232007-06-16 20:29:25 +100010861proc validate_arctags {a} {
10862 global arctags idtags
10863
10864 set i -1
10865 set na $arctags($a)
10866 foreach id $arctags($a) {
Denton Liue2445882020-09-10 21:36:33 -070010867 incr i
10868 if {![info exists idtags($id)]} {
10869 set na [lreplace $na $i $i]
10870 incr i -1
10871 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010872 }
10873 set arctags($a) $na
10874}
10875
10876proc validate_archeads {a} {
10877 global archeads idheads
10878
10879 set i -1
10880 set na $archeads($a)
10881 foreach id $archeads($a) {
Denton Liue2445882020-09-10 21:36:33 -070010882 incr i
10883 if {![info exists idheads($id)]} {
10884 set na [lreplace $na $i $i]
10885 incr i -1
10886 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010887 }
10888 set archeads($a) $na
10889}
10890
10891# Return the list of IDs that have tags that are descendents of id,
10892# ignoring IDs that are descendents of IDs already reported.
10893proc desctags {id} {
10894 global arcnos arcstart arcids arctags idtags allparents
10895 global growing cached_dtags
10896
10897 if {![info exists allparents($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070010898 return {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010899 }
10900 set t1 [clock clicks -milliseconds]
10901 set argid $id
10902 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
Denton Liue2445882020-09-10 21:36:33 -070010903 # part-way along an arc; check that arc first
10904 set a [lindex $arcnos($id) 0]
10905 if {$arctags($a) ne {}} {
10906 validate_arctags $a
10907 set i [lsearch -exact $arcids($a) $id]
10908 set tid {}
10909 foreach t $arctags($a) {
10910 set j [lsearch -exact $arcids($a) $t]
10911 if {$j >= $i} break
10912 set tid $t
10913 }
10914 if {$tid ne {}} {
10915 return $tid
10916 }
10917 }
10918 set id $arcstart($a)
10919 if {[info exists idtags($id)]} {
10920 return $id
10921 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010922 }
10923 if {[info exists cached_dtags($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070010924 return $cached_dtags($id)
Paul Mackerrase11f1232007-06-16 20:29:25 +100010925 }
10926
10927 set origid $id
10928 set todo [list $id]
10929 set queued($id) 1
10930 set nc 1
10931 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070010932 set id [lindex $todo $i]
10933 set done($id) 1
10934 set ta [info exists hastaggedancestor($id)]
10935 if {!$ta} {
10936 incr nc -1
10937 }
10938 # ignore tags on starting node
10939 if {!$ta && $i > 0} {
10940 if {[info exists idtags($id)]} {
10941 set tagloc($id) $id
10942 set ta 1
10943 } elseif {[info exists cached_dtags($id)]} {
10944 set tagloc($id) $cached_dtags($id)
10945 set ta 1
10946 }
10947 }
10948 foreach a $arcnos($id) {
10949 set d $arcstart($a)
10950 if {!$ta && $arctags($a) ne {}} {
10951 validate_arctags $a
10952 if {$arctags($a) ne {}} {
10953 lappend tagloc($id) [lindex $arctags($a) end]
10954 }
10955 }
10956 if {$ta || $arctags($a) ne {}} {
10957 set tomark [list $d]
10958 for {set j 0} {$j < [llength $tomark]} {incr j} {
10959 set dd [lindex $tomark $j]
10960 if {![info exists hastaggedancestor($dd)]} {
10961 if {[info exists done($dd)]} {
10962 foreach b $arcnos($dd) {
10963 lappend tomark $arcstart($b)
10964 }
10965 if {[info exists tagloc($dd)]} {
10966 unset tagloc($dd)
10967 }
10968 } elseif {[info exists queued($dd)]} {
10969 incr nc -1
10970 }
10971 set hastaggedancestor($dd) 1
10972 }
10973 }
10974 }
10975 if {![info exists queued($d)]} {
10976 lappend todo $d
10977 set queued($d) 1
10978 if {![info exists hastaggedancestor($d)]} {
10979 incr nc
10980 }
10981 }
10982 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010983 }
10984 set tags {}
10985 foreach id [array names tagloc] {
Denton Liue2445882020-09-10 21:36:33 -070010986 if {![info exists hastaggedancestor($id)]} {
10987 foreach t $tagloc($id) {
10988 if {[lsearch -exact $tags $t] < 0} {
10989 lappend tags $t
10990 }
10991 }
10992 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010993 }
10994 set t2 [clock clicks -milliseconds]
10995 set loopix $i
10996
10997 # remove tags that are descendents of other tags
10998 for {set i 0} {$i < [llength $tags]} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070010999 set a [lindex $tags $i]
11000 for {set j 0} {$j < $i} {incr j} {
11001 set b [lindex $tags $j]
11002 set r [anc_or_desc $a $b]
11003 if {$r == 1} {
11004 set tags [lreplace $tags $j $j]
11005 incr j -1
11006 incr i -1
11007 } elseif {$r == -1} {
11008 set tags [lreplace $tags $i $i]
11009 incr i -1
11010 break
11011 }
11012 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011013 }
11014
11015 if {[array names growing] ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070011016 # graph isn't finished, need to check if any tag could get
11017 # eclipsed by another tag coming later. Simply ignore any
11018 # tags that could later get eclipsed.
11019 set ctags {}
11020 foreach t $tags {
11021 if {[is_certain $t $origid]} {
11022 lappend ctags $t
11023 }
11024 }
11025 if {$tags eq $ctags} {
11026 set cached_dtags($origid) $tags
11027 } else {
11028 set tags $ctags
11029 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011030 } else {
Denton Liue2445882020-09-10 21:36:33 -070011031 set cached_dtags($origid) $tags
Paul Mackerrase11f1232007-06-16 20:29:25 +100011032 }
11033 set t3 [clock clicks -milliseconds]
11034 if {0 && $t3 - $t1 >= 100} {
Denton Liue2445882020-09-10 21:36:33 -070011035 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
11036 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
Paul Mackerrase11f1232007-06-16 20:29:25 +100011037 }
11038 return $tags
11039}
11040
11041proc anctags {id} {
11042 global arcnos arcids arcout arcend arctags idtags allparents
11043 global growing cached_atags
11044
11045 if {![info exists allparents($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011046 return {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011047 }
11048 set t1 [clock clicks -milliseconds]
11049 set argid $id
11050 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
Denton Liue2445882020-09-10 21:36:33 -070011051 # part-way along an arc; check that arc first
11052 set a [lindex $arcnos($id) 0]
11053 if {$arctags($a) ne {}} {
11054 validate_arctags $a
11055 set i [lsearch -exact $arcids($a) $id]
11056 foreach t $arctags($a) {
11057 set j [lsearch -exact $arcids($a) $t]
11058 if {$j > $i} {
11059 return $t
11060 }
11061 }
11062 }
11063 if {![info exists arcend($a)]} {
11064 return {}
11065 }
11066 set id $arcend($a)
11067 if {[info exists idtags($id)]} {
11068 return $id
11069 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011070 }
11071 if {[info exists cached_atags($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011072 return $cached_atags($id)
Paul Mackerrase11f1232007-06-16 20:29:25 +100011073 }
11074
11075 set origid $id
11076 set todo [list $id]
11077 set queued($id) 1
11078 set taglist {}
11079 set nc 1
11080 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070011081 set id [lindex $todo $i]
11082 set done($id) 1
11083 set td [info exists hastaggeddescendent($id)]
11084 if {!$td} {
11085 incr nc -1
11086 }
11087 # ignore tags on starting node
11088 if {!$td && $i > 0} {
11089 if {[info exists idtags($id)]} {
11090 set tagloc($id) $id
11091 set td 1
11092 } elseif {[info exists cached_atags($id)]} {
11093 set tagloc($id) $cached_atags($id)
11094 set td 1
11095 }
11096 }
11097 foreach a $arcout($id) {
11098 if {!$td && $arctags($a) ne {}} {
11099 validate_arctags $a
11100 if {$arctags($a) ne {}} {
11101 lappend tagloc($id) [lindex $arctags($a) 0]
11102 }
11103 }
11104 if {![info exists arcend($a)]} continue
11105 set d $arcend($a)
11106 if {$td || $arctags($a) ne {}} {
11107 set tomark [list $d]
11108 for {set j 0} {$j < [llength $tomark]} {incr j} {
11109 set dd [lindex $tomark $j]
11110 if {![info exists hastaggeddescendent($dd)]} {
11111 if {[info exists done($dd)]} {
11112 foreach b $arcout($dd) {
11113 if {[info exists arcend($b)]} {
11114 lappend tomark $arcend($b)
11115 }
11116 }
11117 if {[info exists tagloc($dd)]} {
11118 unset tagloc($dd)
11119 }
11120 } elseif {[info exists queued($dd)]} {
11121 incr nc -1
11122 }
11123 set hastaggeddescendent($dd) 1
11124 }
11125 }
11126 }
11127 if {![info exists queued($d)]} {
11128 lappend todo $d
11129 set queued($d) 1
11130 if {![info exists hastaggeddescendent($d)]} {
11131 incr nc
11132 }
11133 }
11134 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011135 }
11136 set t2 [clock clicks -milliseconds]
11137 set loopix $i
11138 set tags {}
11139 foreach id [array names tagloc] {
Denton Liue2445882020-09-10 21:36:33 -070011140 if {![info exists hastaggeddescendent($id)]} {
11141 foreach t $tagloc($id) {
11142 if {[lsearch -exact $tags $t] < 0} {
11143 lappend tags $t
11144 }
11145 }
11146 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011147 }
11148
11149 # remove tags that are ancestors of other tags
11150 for {set i 0} {$i < [llength $tags]} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070011151 set a [lindex $tags $i]
11152 for {set j 0} {$j < $i} {incr j} {
11153 set b [lindex $tags $j]
11154 set r [anc_or_desc $a $b]
11155 if {$r == -1} {
11156 set tags [lreplace $tags $j $j]
11157 incr j -1
11158 incr i -1
11159 } elseif {$r == 1} {
11160 set tags [lreplace $tags $i $i]
11161 incr i -1
11162 break
11163 }
11164 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011165 }
11166
11167 if {[array names growing] ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070011168 # graph isn't finished, need to check if any tag could get
11169 # eclipsed by another tag coming later. Simply ignore any
11170 # tags that could later get eclipsed.
11171 set ctags {}
11172 foreach t $tags {
11173 if {[is_certain $origid $t]} {
11174 lappend ctags $t
11175 }
11176 }
11177 if {$tags eq $ctags} {
11178 set cached_atags($origid) $tags
11179 } else {
11180 set tags $ctags
11181 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011182 } else {
Denton Liue2445882020-09-10 21:36:33 -070011183 set cached_atags($origid) $tags
Paul Mackerrase11f1232007-06-16 20:29:25 +100011184 }
11185 set t3 [clock clicks -milliseconds]
11186 if {0 && $t3 - $t1 >= 100} {
Denton Liue2445882020-09-10 21:36:33 -070011187 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
11188 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
Paul Mackerrase11f1232007-06-16 20:29:25 +100011189 }
11190 return $tags
11191}
11192
11193# Return the list of IDs that have heads that are descendents of id,
11194# including id itself if it has a head.
11195proc descheads {id} {
11196 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011197 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100011198
11199 if {![info exists allparents($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011200 return {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011201 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011202 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011203 if {![info exists arcout($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011204 # part-way along an arc; check it first
11205 set a [lindex $arcnos($id) 0]
11206 if {$archeads($a) ne {}} {
11207 validate_archeads $a
11208 set i [lsearch -exact $arcids($a) $id]
11209 foreach t $archeads($a) {
11210 set j [lsearch -exact $arcids($a) $t]
11211 if {$j > $i} break
11212 lappend aret $t
11213 }
11214 }
11215 set id $arcstart($a)
Paul Mackerrase11f1232007-06-16 20:29:25 +100011216 }
11217 set origid $id
11218 set todo [list $id]
11219 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011220 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011221 for {set i 0} {$i < [llength $todo]} {incr i} {
Denton Liue2445882020-09-10 21:36:33 -070011222 set id [lindex $todo $i]
11223 if {[info exists cached_dheads($id)]} {
11224 set ret [concat $ret $cached_dheads($id)]
11225 } else {
11226 if {[info exists idheads($id)]} {
11227 lappend ret $id
11228 }
11229 foreach a $arcnos($id) {
11230 if {$archeads($a) ne {}} {
11231 validate_archeads $a
11232 if {$archeads($a) ne {}} {
11233 set ret [concat $ret $archeads($a)]
11234 }
11235 }
11236 set d $arcstart($a)
11237 if {![info exists seen($d)]} {
11238 lappend todo $d
11239 set seen($d) 1
11240 }
11241 }
11242 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011243 }
11244 set ret [lsort -unique $ret]
11245 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011246 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100011247}
11248
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011249proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011250 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011251
Paul Mackerrase11f1232007-06-16 20:29:25 +100011252 if {![info exists arcnos($id)]} return
11253 if {![info exists arcout($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011254 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011255 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011256 unset -nocomplain cached_dtags
11257 unset -nocomplain cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011258}
11259
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011260proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011261 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011262
Paul Mackerrase11f1232007-06-16 20:29:25 +100011263 if {![info exists arcnos($hid)]} return
11264 if {![info exists arcout($hid)]} {
Denton Liue2445882020-09-10 21:36:33 -070011265 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011266 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011267 unset -nocomplain cached_dheads
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011268}
11269
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011270proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011271 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011272
Paul Mackerras009409f2015-05-02 20:53:36 +100011273 unset -nocomplain cached_dheads
Paul Mackerras10299152006-08-02 09:52:01 +100011274}
11275
Paul Mackerrase11f1232007-06-16 20:29:25 +100011276proc movedhead {hid head} {
11277 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011278
Paul Mackerrase11f1232007-06-16 20:29:25 +100011279 if {![info exists arcnos($hid)]} return
11280 if {![info exists arcout($hid)]} {
Denton Liue2445882020-09-10 21:36:33 -070011281 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011282 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011283 unset -nocomplain cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011284}
11285
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011286proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070011287 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100011288 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011289
Paul Mackerrase11f1232007-06-16 20:29:25 +100011290 foreach id [concat [array names idheads] [array names idtags]] {
Denton Liue2445882020-09-10 21:36:33 -070011291 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
11292 set a [lindex $arcnos($id) 0]
11293 if {![info exists donearc($a)]} {
11294 recalcarc $a
11295 set donearc($a) 1
11296 }
11297 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011298 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011299 unset -nocomplain cached_tagcontent
11300 unset -nocomplain cached_dtags
11301 unset -nocomplain cached_atags
11302 unset -nocomplain cached_dheads
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011303}
11304
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011305proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011306 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011307
11308 set refids [concat [array names idtags] \
Denton Liue2445882020-09-10 21:36:33 -070011309 [array names idheads] [array names idotherrefs]]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011310 foreach id $refids {
Denton Liue2445882020-09-10 21:36:33 -070011311 if {![info exists ref($id)]} {
11312 set ref($id) [listrefs $id]
11313 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011314 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011315 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011316 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011317 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011318 set refids [lsort -unique [concat $refids [array names idtags] \
Denton Liue2445882020-09-10 21:36:33 -070011319 [array names idheads] [array names idotherrefs]]]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011320 foreach id $refids {
Denton Liue2445882020-09-10 21:36:33 -070011321 set v [listrefs $id]
11322 if {![info exists ref($id)] || $ref($id) != $v} {
11323 redrawtags $id
11324 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011325 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011326 if {$oldmainhead ne $mainheadid} {
Denton Liue2445882020-09-10 21:36:33 -070011327 redrawtags $oldmainhead
11328 redrawtags $mainheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011329 }
Paul Mackerras887c9962007-08-20 19:36:20 +100011330 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011331}
11332
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011333proc listrefs {id} {
11334 global idtags idheads idotherrefs
11335
11336 set x {}
11337 if {[info exists idtags($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011338 set x $idtags($id)
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011339 }
11340 set y {}
11341 if {[info exists idheads($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011342 set y $idheads($id)
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011343 }
11344 set z {}
11345 if {[info exists idotherrefs($id)]} {
Denton Liue2445882020-09-10 21:36:33 -070011346 set z $idotherrefs($id)
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011347 }
11348 return [list $x $y $z]
11349}
11350
Paul Mackerras4399fe32013-01-03 10:10:31 +110011351proc add_tag_ctext {tag} {
11352 global ctext cached_tagcontent tagids
11353
11354 if {![info exists cached_tagcontent($tag)]} {
Denton Liue2445882020-09-10 21:36:33 -070011355 catch {
11356 set cached_tagcontent($tag) [exec git cat-file -p $tag]
11357 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011358 }
11359 $ctext insert end "[mc "Tag"]: $tag\n" bold
11360 if {[info exists cached_tagcontent($tag)]} {
Denton Liue2445882020-09-10 21:36:33 -070011361 set text $cached_tagcontent($tag)
Paul Mackerras4399fe32013-01-03 10:10:31 +110011362 } else {
Denton Liue2445882020-09-10 21:36:33 -070011363 set text "[mc "Id"]: $tagids($tag)"
Paul Mackerras4399fe32013-01-03 10:10:31 +110011364 }
11365 appendwithlinks $text {}
11366}
11367
Paul Mackerras106288c2005-08-19 23:11:39 +100011368proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070011369 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100011370
11371 if {$isnew} {
Denton Liue2445882020-09-10 21:36:33 -070011372 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100011373 }
11374 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100011375 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011376 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100011377 set linknum 0
Paul Mackerras4399fe32013-01-03 10:10:31 +110011378 add_tag_ctext $tag
11379 maybe_scroll_ctext 1
11380 $ctext conf -state disabled
11381 init_flist {}
11382}
11383
11384proc showtags {id isnew} {
11385 global idtags ctext linknum
11386
11387 if {$isnew} {
Denton Liue2445882020-09-10 21:36:33 -070011388 addtohistory [list showtags $id 0] savectextpos
Paul Mackerras62d3ea62006-09-11 10:36:53 +100011389 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011390 $ctext conf -state normal
11391 clear_ctext
11392 settabs 0
11393 set linknum 0
11394 set sep {}
11395 foreach tag $idtags($id) {
Denton Liue2445882020-09-10 21:36:33 -070011396 $ctext insert end $sep
11397 add_tag_ctext $tag
11398 set sep "\n\n"
Paul Mackerras106288c2005-08-19 23:11:39 +100011399 }
Pat Thoytsa80e82f2009-11-14 13:21:09 +000011400 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100011401 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100011402 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100011403}
11404
Paul Mackerras1d10f362005-05-15 12:55:47 +000011405proc doquit {} {
11406 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010011407 global gitktmpdir
11408
Paul Mackerras1d10f362005-05-15 12:55:47 +000011409 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050011410 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000011411 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010011412
11413 if {[info exists gitktmpdir]} {
Denton Liue2445882020-09-10 21:36:33 -070011414 catch {file delete -force $gitktmpdir}
Thomas Arcila314f5de2008-03-24 12:55:36 +010011415 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000011416}
11417
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011418proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011419 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011420
11421 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011422 ${NS}::button $top.${font}but -text $which \
Denton Liue2445882020-09-10 21:36:33 -070011423 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011424 ${NS}::label $top.$font -relief flat -font $font \
Denton Liue2445882020-09-10 21:36:33 -070011425 -text $fontattr($font,family) -justify left
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011426 grid x $top.${font}but $top.$font -sticky w
11427}
11428
11429proc choosefont {font which} {
11430 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010011431 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011432
11433 set fontparam(which) $which
11434 set fontparam(font) $font
11435 set fontparam(family) [font actual $font -family]
11436 set fontparam(size) $fontattr($font,size)
11437 set fontparam(weight) $fontattr($font,weight)
11438 set fontparam(slant) $fontattr($font,slant)
11439 set top .gitkfont
11440 set fonttop $top
11441 if {![winfo exists $top]} {
Denton Liue2445882020-09-10 21:36:33 -070011442 font create sample
11443 eval font config sample [font actual $font]
11444 ttk_toplevel $top
11445 make_transient $top $prefstop
11446 wm title $top [mc "Gitk font chooser"]
11447 ${NS}::label $top.l -textvariable fontparam(which)
11448 pack $top.l -side top
11449 set fontlist [lsort [font families]]
11450 ${NS}::frame $top.f
11451 listbox $top.f.fam -listvariable fontlist \
11452 -yscrollcommand [list $top.f.sb set]
11453 bind $top.f.fam <<ListboxSelect>> selfontfam
11454 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
11455 pack $top.f.sb -side right -fill y
11456 pack $top.f.fam -side left -fill both -expand 1
11457 pack $top.f -side top -fill both -expand 1
11458 ${NS}::frame $top.g
11459 spinbox $top.g.size -from 4 -to 40 -width 4 \
11460 -textvariable fontparam(size) \
11461 -validatecommand {string is integer -strict %s}
11462 checkbutton $top.g.bold -padx 5 \
11463 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
11464 -variable fontparam(weight) -onvalue bold -offvalue normal
11465 checkbutton $top.g.ital -padx 5 \
11466 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
11467 -variable fontparam(slant) -onvalue italic -offvalue roman
11468 pack $top.g.size $top.g.bold $top.g.ital -side left
11469 pack $top.g -side top
11470 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
11471 -background white
11472 $top.c create text 100 25 -anchor center -text $which -font sample \
11473 -fill black -tags text
11474 bind $top.c <Configure> [list centertext $top.c]
11475 pack $top.c -side top -fill x
11476 ${NS}::frame $top.buts
11477 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
11478 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
11479 bind $top <Key-Return> fontok
11480 bind $top <Key-Escape> fontcan
11481 grid $top.buts.ok $top.buts.can
11482 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11483 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11484 pack $top.buts -side bottom -fill x
11485 trace add variable fontparam write chg_fontparam
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011486 } else {
Denton Liue2445882020-09-10 21:36:33 -070011487 raise $top
11488 $top.c itemconf text -text $which
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011489 }
11490 set i [lsearch -exact $fontlist $fontparam(family)]
11491 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -070011492 $top.f.fam selection set $i
11493 $top.f.fam see $i
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011494 }
11495}
11496
11497proc centertext {w} {
11498 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11499}
11500
11501proc fontok {} {
11502 global fontparam fontpref prefstop
11503
11504 set f $fontparam(font)
11505 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11506 if {$fontparam(weight) eq "bold"} {
Denton Liue2445882020-09-10 21:36:33 -070011507 lappend fontpref($f) "bold"
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011508 }
11509 if {$fontparam(slant) eq "italic"} {
Denton Liue2445882020-09-10 21:36:33 -070011510 lappend fontpref($f) "italic"
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011511 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011512 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011513 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011514
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011515 fontcan
11516}
11517
11518proc fontcan {} {
11519 global fonttop fontparam
11520
11521 if {[info exists fonttop]} {
Denton Liue2445882020-09-10 21:36:33 -070011522 catch {destroy $fonttop}
11523 catch {font delete sample}
11524 unset fonttop
11525 unset fontparam
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011526 }
11527}
11528
Pat Thoytsd93f1712009-04-17 01:24:35 +010011529if {[package vsatisfies [package provide Tk] 8.6]} {
11530 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11531 # function to make use of it.
11532 proc choosefont {font which} {
Denton Liue2445882020-09-10 21:36:33 -070011533 tk fontchooser configure -title $which -font $font \
11534 -command [list on_choosefont $font $which]
11535 tk fontchooser show
Pat Thoytsd93f1712009-04-17 01:24:35 +010011536 }
11537 proc on_choosefont {font which newfont} {
Denton Liue2445882020-09-10 21:36:33 -070011538 global fontparam
11539 puts stderr "$font $newfont"
11540 array set f [font actual $newfont]
11541 set fontparam(which) $which
11542 set fontparam(font) $font
11543 set fontparam(family) $f(-family)
11544 set fontparam(size) $f(-size)
11545 set fontparam(weight) $f(-weight)
11546 set fontparam(slant) $f(-slant)
11547 fontok
Pat Thoytsd93f1712009-04-17 01:24:35 +010011548 }
11549}
11550
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011551proc selfontfam {} {
11552 global fonttop fontparam
11553
11554 set i [$fonttop.f.fam curselection]
11555 if {$i ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070011556 set fontparam(family) [$fonttop.f.fam get $i]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011557 }
11558}
11559
11560proc chg_fontparam {v sub op} {
11561 global fontparam
11562
11563 font config sample -$sub $fontparam($sub)
11564}
11565
Pat Thoyts44acce02011-12-13 14:56:49 +000011566# Create a property sheet tab page
11567proc create_prefs_page {w} {
11568 global NS
11569 set parent [join [lrange [split $w .] 0 end-1] .]
11570 if {[winfo class $parent] eq "TNotebook"} {
Denton Liue2445882020-09-10 21:36:33 -070011571 ${NS}::frame $w
Pat Thoyts44acce02011-12-13 14:56:49 +000011572 } else {
Denton Liue2445882020-09-10 21:36:33 -070011573 ${NS}::labelframe $w
Pat Thoyts44acce02011-12-13 14:56:49 +000011574 }
11575}
11576
11577proc prefspage_general {notebook} {
11578 global NS maxwidth maxgraphpct showneartags showlocalchanges
11579 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras3441de52019-08-27 08:12:34 +100011580 global hideremotes want_ttk have_ttk maxrefs web_browser
Pat Thoyts44acce02011-12-13 14:56:49 +000011581
11582 set page [create_prefs_page $notebook.general]
11583
11584 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11585 grid $page.ldisp - -sticky w -pady 10
11586 ${NS}::label $page.spacer -text " "
11587 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11588 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11589 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
Alex Henrie8a1692f2015-01-22 01:19:39 -070011590 #xgettext:no-tcl-format
Pat Thoyts44acce02011-12-13 14:56:49 +000011591 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11592 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11593 grid x $page.maxpctl $page.maxpct -sticky w
11594 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
Denton Liue2445882020-09-10 21:36:33 -070011595 -variable showlocalchanges
Pat Thoyts44acce02011-12-13 14:56:49 +000011596 grid x $page.showlocal -sticky w
11597 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
Denton Liue2445882020-09-10 21:36:33 -070011598 -variable autoselect
Pat Thoyts44acce02011-12-13 14:56:49 +000011599 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11600 grid x $page.autoselect $page.autosellen -sticky w
11601 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
Denton Liue2445882020-09-10 21:36:33 -070011602 -variable hideremotes
Pat Thoyts44acce02011-12-13 14:56:49 +000011603 grid x $page.hideremotes -sticky w
11604
11605 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11606 grid $page.ddisp - -sticky w -pady 10
11607 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11608 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11609 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011610 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Denton Liue2445882020-09-10 21:36:33 -070011611 -variable showneartags
Pat Thoyts44acce02011-12-13 14:56:49 +000011612 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011613 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11614 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11615 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011616 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
Denton Liue2445882020-09-10 21:36:33 -070011617 -variable limitdiffs
Pat Thoyts44acce02011-12-13 14:56:49 +000011618 grid x $page.ldiff -sticky w
11619 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
Denton Liue2445882020-09-10 21:36:33 -070011620 -variable perfile_attrs
Pat Thoyts44acce02011-12-13 14:56:49 +000011621 grid x $page.lattr -sticky w
11622
11623 ${NS}::entry $page.extdifft -textvariable extdifftool
11624 ${NS}::frame $page.extdifff
11625 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11626 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11627 pack $page.extdifff.l $page.extdifff.b -side left
11628 pack configure $page.extdifff.l -padx 10
11629 grid x $page.extdifff $page.extdifft -sticky ew
11630
Paul Mackerras3441de52019-08-27 08:12:34 +100011631 ${NS}::entry $page.webbrowser -textvariable web_browser
11632 ${NS}::frame $page.webbrowserf
11633 ${NS}::label $page.webbrowserf.l -text [mc "Web browser" ]
11634 pack $page.webbrowserf.l -side left
11635 pack configure $page.webbrowserf.l -padx 10
11636 grid x $page.webbrowserf $page.webbrowser -sticky ew
11637
Pat Thoyts44acce02011-12-13 14:56:49 +000011638 ${NS}::label $page.lgen -text [mc "General options"]
11639 grid $page.lgen - -sticky w -pady 10
11640 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
Denton Liue2445882020-09-10 21:36:33 -070011641 -text [mc "Use themed widgets"]
Pat Thoyts44acce02011-12-13 14:56:49 +000011642 if {$have_ttk} {
Denton Liue2445882020-09-10 21:36:33 -070011643 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
Pat Thoyts44acce02011-12-13 14:56:49 +000011644 } else {
Denton Liue2445882020-09-10 21:36:33 -070011645 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
Pat Thoyts44acce02011-12-13 14:56:49 +000011646 }
11647 grid x $page.want_ttk $page.ttk_note -sticky w
11648 return $page
11649}
11650
11651proc prefspage_colors {notebook} {
11652 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Stefan Dotterweich113ce122020-02-11 22:24:48 +010011653 global diffbgcolors
Pat Thoyts44acce02011-12-13 14:56:49 +000011654
11655 set page [create_prefs_page $notebook.colors]
11656
11657 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11658 grid $page.cdisp - -sticky w -pady 10
11659 label $page.ui -padx 40 -relief sunk -background $uicolor
11660 ${NS}::button $page.uibut -text [mc "Interface"] \
11661 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11662 grid x $page.uibut $page.ui -sticky w
11663 label $page.bg -padx 40 -relief sunk -background $bgcolor
11664 ${NS}::button $page.bgbut -text [mc "Background"] \
Denton Liue2445882020-09-10 21:36:33 -070011665 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
Pat Thoyts44acce02011-12-13 14:56:49 +000011666 grid x $page.bgbut $page.bg -sticky w
11667 label $page.fg -padx 40 -relief sunk -background $fgcolor
11668 ${NS}::button $page.fgbut -text [mc "Foreground"] \
Denton Liue2445882020-09-10 21:36:33 -070011669 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
Pat Thoyts44acce02011-12-13 14:56:49 +000011670 grid x $page.fgbut $page.fg -sticky w
11671 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11672 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
Denton Liue2445882020-09-10 21:36:33 -070011673 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11674 [list $ctext tag conf d0 -foreground]]
Pat Thoyts44acce02011-12-13 14:56:49 +000011675 grid x $page.diffoldbut $page.diffold -sticky w
Stefan Dotterweich113ce122020-02-11 22:24:48 +010011676 label $page.diffoldbg -padx 40 -relief sunk -background [lindex $diffbgcolors 0]
11677 ${NS}::button $page.diffoldbgbut -text [mc "Diff: old lines bg"] \
Denton Liue2445882020-09-10 21:36:33 -070011678 -command [list choosecolor diffbgcolors 0 $page.diffoldbg \
11679 [mc "diff old lines bg"] \
11680 [list $ctext tag conf d0 -background]]
Stefan Dotterweich113ce122020-02-11 22:24:48 +010011681 grid x $page.diffoldbgbut $page.diffoldbg -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011682 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11683 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
Denton Liue2445882020-09-10 21:36:33 -070011684 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11685 [list $ctext tag conf dresult -foreground]]
Pat Thoyts44acce02011-12-13 14:56:49 +000011686 grid x $page.diffnewbut $page.diffnew -sticky w
Stefan Dotterweich113ce122020-02-11 22:24:48 +010011687 label $page.diffnewbg -padx 40 -relief sunk -background [lindex $diffbgcolors 1]
11688 ${NS}::button $page.diffnewbgbut -text [mc "Diff: new lines bg"] \
Denton Liue2445882020-09-10 21:36:33 -070011689 -command [list choosecolor diffbgcolors 1 $page.diffnewbg \
11690 [mc "diff new lines bg"] \
11691 [list $ctext tag conf dresult -background]]
Stefan Dotterweich113ce122020-02-11 22:24:48 +010011692 grid x $page.diffnewbgbut $page.diffnewbg -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011693 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11694 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
Denton Liue2445882020-09-10 21:36:33 -070011695 -command [list choosecolor diffcolors 2 $page.hunksep \
11696 [mc "diff hunk header"] \
11697 [list $ctext tag conf hunksep -foreground]]
Pat Thoyts44acce02011-12-13 14:56:49 +000011698 grid x $page.hunksepbut $page.hunksep -sticky w
11699 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11700 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
Denton Liue2445882020-09-10 21:36:33 -070011701 -command [list choosecolor markbgcolor {} $page.markbgsep \
11702 [mc "marked line background"] \
11703 [list $ctext tag conf omark -background]]
Pat Thoyts44acce02011-12-13 14:56:49 +000011704 grid x $page.markbgbut $page.markbgsep -sticky w
11705 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11706 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
Denton Liue2445882020-09-10 21:36:33 -070011707 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
Pat Thoyts44acce02011-12-13 14:56:49 +000011708 grid x $page.selbgbut $page.selbgsep -sticky w
11709 return $page
11710}
11711
11712proc prefspage_fonts {notebook} {
11713 global NS
11714 set page [create_prefs_page $notebook.fonts]
11715 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11716 grid $page.cfont - -sticky w -pady 10
11717 mkfontdisp mainfont $page [mc "Main font"]
11718 mkfontdisp textfont $page [mc "Diff display font"]
11719 mkfontdisp uifont $page [mc "User interface font"]
11720 return $page
11721}
11722
Paul Mackerras712fcc02005-11-30 09:28:16 +110011723proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011724 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011725 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011726 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011727 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011728 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011729
Paul Mackerras712fcc02005-11-30 09:28:16 +110011730 set top .gitkprefs
11731 set prefstop $top
11732 if {[winfo exists $top]} {
Denton Liue2445882020-09-10 21:36:33 -070011733 raise $top
11734 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011735 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011736 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Denton Liue2445882020-09-10 21:36:33 -070011737 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
11738 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011739 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011740 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011741 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011742 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011743
Pat Thoyts44acce02011-12-13 14:56:49 +000011744 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
Denton Liue2445882020-09-10 21:36:33 -070011745 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011746 } else {
Denton Liue2445882020-09-10 21:36:33 -070011747 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011748 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011749
Pat Thoyts44acce02011-12-13 14:56:49 +000011750 lappend pages [prefspage_general $notebook] [mc "General"]
11751 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11752 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011753 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011754 foreach {page title} $pages {
Denton Liue2445882020-09-10 21:36:33 -070011755 if {$use_notebook} {
11756 $notebook add $page -text $title
11757 } else {
11758 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11759 -text $title -command [list raise $page]]
11760 $page configure -text $title
11761 grid $btn -row 0 -column [incr col] -sticky w
11762 grid $page -row 1 -column 0 -sticky news -columnspan 100
11763 }
Pat Thoyts44acce02011-12-13 14:56:49 +000011764 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011765
Pat Thoyts44acce02011-12-13 14:56:49 +000011766 if {!$use_notebook} {
Denton Liue2445882020-09-10 21:36:33 -070011767 grid columnconfigure $notebook 0 -weight 1
11768 grid rowconfigure $notebook 1 -weight 1
11769 raise [lindex $pages 0]
Pat Thoyts44acce02011-12-13 14:56:49 +000011770 }
11771
11772 grid $notebook -sticky news -padx 2 -pady 2
11773 grid rowconfigure $top 0 -weight 1
11774 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011775
Pat Thoytsd93f1712009-04-17 01:24:35 +010011776 ${NS}::frame $top.buts
11777 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11778 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011779 bind $top <Key-Return> prefsok
11780 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011781 grid $top.buts.ok $top.buts.can
11782 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11783 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11784 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011785 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011786 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011787}
11788
Thomas Arcila314f5de2008-03-24 12:55:36 +010011789proc choose_extdiff {} {
11790 global extdifftool
11791
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011792 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011793 if {$prog ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070011794 set extdifftool $prog
Thomas Arcila314f5de2008-03-24 12:55:36 +010011795 }
11796}
11797
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011798proc choosecolor {v vi w x cmd} {
11799 global $v
11800
11801 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Denton Liue2445882020-09-10 21:36:33 -070011802 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011803 if {$c eq {}} return
11804 $w conf -background $c
11805 lset $v $vi $c
11806 eval $cmd $c
11807}
11808
Mark Levedahl60378c02007-05-20 12:12:48 -040011809proc setselbg {c} {
11810 global bglist cflist
11811 foreach w $bglist {
Denton Liue2445882020-09-10 21:36:33 -070011812 if {[winfo exists $w]} {
11813 $w configure -selectbackground $c
11814 }
Mark Levedahl60378c02007-05-20 12:12:48 -040011815 }
11816 $cflist tag configure highlight \
Denton Liue2445882020-09-10 21:36:33 -070011817 -background [$cflist cget -selectbackground]
Mark Levedahl60378c02007-05-20 12:12:48 -040011818 allcanvs itemconf secsel -fill $c
11819}
11820
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011821# This sets the background color and the color scheme for the whole UI.
11822# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11823# if we don't specify one ourselves, which makes the checkbuttons and
11824# radiobuttons look bad. This chooses white for selectColor if the
11825# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011826proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011827 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011828 set bg [winfo rgb . $c]
11829 set selc black
11830 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
Denton Liue2445882020-09-10 21:36:33 -070011831 set selc white
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011832 }
11833 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011834}
11835
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011836proc setbg {c} {
11837 global bglist
11838
11839 foreach w $bglist {
Denton Liue2445882020-09-10 21:36:33 -070011840 if {[winfo exists $w]} {
11841 $w conf -background $c
11842 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011843 }
11844}
11845
11846proc setfg {c} {
11847 global fglist canv
11848
11849 foreach w $fglist {
Denton Liue2445882020-09-10 21:36:33 -070011850 if {[winfo exists $w]} {
11851 $w conf -foreground $c
11852 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011853 }
11854 allcanvs itemconf text -fill $c
11855 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011856 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011857}
11858
Paul Mackerras712fcc02005-11-30 09:28:16 +110011859proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011860 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011861
Paul Mackerras3de07112007-10-23 22:40:50 +100011862 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Denton Liue2445882020-09-10 21:36:33 -070011863 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
11864 global $v
11865 set $v $oldprefs($v)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011866 }
11867 catch {destroy $prefstop}
11868 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011869 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011870}
11871
11872proc prefsok {} {
11873 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011874 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011875 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011876 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011877 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011878
11879 catch {destroy $prefstop}
11880 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011881 fontcan
11882 set fontchanged 0
11883 if {$mainfont ne $fontpref(mainfont)} {
Denton Liue2445882020-09-10 21:36:33 -070011884 set mainfont $fontpref(mainfont)
11885 parsefont mainfont $mainfont
11886 eval font configure mainfont [fontflags mainfont]
11887 eval font configure mainfontbold [fontflags mainfont 1]
11888 setcoords
11889 set fontchanged 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011890 }
11891 if {$textfont ne $fontpref(textfont)} {
Denton Liue2445882020-09-10 21:36:33 -070011892 set textfont $fontpref(textfont)
11893 parsefont textfont $textfont
11894 eval font configure textfont [fontflags textfont]
11895 eval font configure textfontbold [fontflags textfont 1]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011896 }
11897 if {$uifont ne $fontpref(uifont)} {
Denton Liue2445882020-09-10 21:36:33 -070011898 set uifont $fontpref(uifont)
11899 parsefont uifont $uifont
11900 eval font configure uifont [fontflags uifont]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011901 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011902 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011903 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
Denton Liue2445882020-09-10 21:36:33 -070011904 if {$showlocalchanges} {
11905 doshowlocalchanges
11906 } else {
11907 dohidelocalchanges
11908 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011909 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011910 if {$limitdiffs != $oldprefs(limitdiffs) ||
Denton Liue2445882020-09-10 21:36:33 -070011911 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11912 # treediffs elements are limited by path;
11913 # won't have encodings cached if perfile_attrs was just turned on
11914 unset -nocomplain treediffs
Paul Mackerras74a40c72007-10-24 10:16:56 +100011915 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011916 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Denton Liue2445882020-09-10 21:36:33 -070011917 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11918 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011919 } elseif {$showneartags != $oldprefs(showneartags) ||
Denton Liue2445882020-09-10 21:36:33 -070011920 $limitdiffs != $oldprefs(limitdiffs)} {
11921 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011922 }
Thomas Rastffe15292009-08-03 23:53:36 +020011923 if {$hideremotes != $oldprefs(hideremotes)} {
Denton Liue2445882020-09-10 21:36:33 -070011924 rereadrefs
Thomas Rastffe15292009-08-03 23:53:36 +020011925 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011926}
11927
11928proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011929 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011930 if {$d ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070011931 # If $datetimeformat includes a timezone, display in the
11932 # timezone of the argument. Otherwise, display in local time.
11933 if {[string match {*%[zZ]*} $datetimeformat]} {
11934 if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
11935 # Tcl < 8.5 does not support -timezone. Emulate it by
11936 # setting TZ (e.g. TZ=<-0430>+04:30).
11937 global env
11938 if {[info exists env(TZ)]} {
11939 set savedTZ $env(TZ)
11940 }
11941 set zone [lindex $d 1]
11942 set sign [string map {+ - - +} [string index $zone 0]]
11943 set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
11944 set d [clock format [lindex $d 0] -format $datetimeformat]
11945 if {[info exists savedTZ]} {
11946 set env(TZ) $savedTZ
11947 } else {
11948 unset env(TZ)
11949 }
11950 }
11951 } else {
11952 set d [clock format [lindex $d 0] -format $datetimeformat]
11953 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011954 }
11955 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011956}
11957
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011958# This list of encoding names and aliases is distilled from
11959# http://www.iana.org/assignments/character-sets.
11960# Not all of them are supported by Tcl.
11961set encoding_aliases {
11962 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11963 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11964 { ISO-10646-UTF-1 csISO10646UTF1 }
11965 { ISO_646.basic:1983 ref csISO646basic1983 }
11966 { INVARIANT csINVARIANT }
11967 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11968 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11969 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11970 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11971 { NATS-DANO iso-ir-9-1 csNATSDANO }
11972 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11973 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11974 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11975 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11976 { ISO-2022-KR csISO2022KR }
11977 { EUC-KR csEUCKR }
11978 { ISO-2022-JP csISO2022JP }
11979 { ISO-2022-JP-2 csISO2022JP2 }
11980 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11981 csISO13JISC6220jp }
11982 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11983 { IT iso-ir-15 ISO646-IT csISO15Italian }
11984 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11985 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11986 { greek7-old iso-ir-18 csISO18Greek7Old }
11987 { latin-greek iso-ir-19 csISO19LatinGreek }
11988 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11989 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11990 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11991 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11992 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11993 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11994 { INIS iso-ir-49 csISO49INIS }
11995 { INIS-8 iso-ir-50 csISO50INIS8 }
11996 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11997 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11998 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11999 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
12000 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
12001 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
12002 csISO60Norwegian1 }
12003 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
12004 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
12005 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
12006 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
12007 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
12008 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
12009 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
12010 { greek7 iso-ir-88 csISO88Greek7 }
12011 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
12012 { iso-ir-90 csISO90 }
12013 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
12014 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
12015 csISO92JISC62991984b }
12016 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
12017 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
12018 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
12019 csISO95JIS62291984handadd }
12020 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
12021 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
12022 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
12023 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
12024 CP819 csISOLatin1 }
12025 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
12026 { T.61-7bit iso-ir-102 csISO102T617bit }
12027 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
12028 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
12029 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
12030 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
12031 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
12032 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
12033 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
12034 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
12035 arabic csISOLatinArabic }
12036 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
12037 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
12038 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
12039 greek greek8 csISOLatinGreek }
12040 { T.101-G2 iso-ir-128 csISO128T101G2 }
12041 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
12042 csISOLatinHebrew }
12043 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
12044 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
12045 { CSN_369103 iso-ir-139 csISO139CSN369103 }
12046 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
12047 { ISO_6937-2-add iso-ir-142 csISOTextComm }
12048 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
12049 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
12050 csISOLatinCyrillic }
12051 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
12052 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
12053 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
12054 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
12055 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
12056 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
12057 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
12058 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
12059 { ISO_10367-box iso-ir-155 csISO10367Box }
12060 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
12061 { latin-lap lap iso-ir-158 csISO158Lap }
12062 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
12063 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
12064 { us-dk csUSDK }
12065 { dk-us csDKUS }
12066 { JIS_X0201 X0201 csHalfWidthKatakana }
12067 { KSC5636 ISO646-KR csKSC5636 }
12068 { ISO-10646-UCS-2 csUnicode }
12069 { ISO-10646-UCS-4 csUCS4 }
12070 { DEC-MCS dec csDECMCS }
12071 { hp-roman8 roman8 r8 csHPRoman8 }
12072 { macintosh mac csMacintosh }
12073 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
12074 csIBM037 }
12075 { IBM038 EBCDIC-INT cp038 csIBM038 }
12076 { IBM273 CP273 csIBM273 }
12077 { IBM274 EBCDIC-BE CP274 csIBM274 }
12078 { IBM275 EBCDIC-BR cp275 csIBM275 }
12079 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
12080 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
12081 { IBM280 CP280 ebcdic-cp-it csIBM280 }
12082 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
12083 { IBM284 CP284 ebcdic-cp-es csIBM284 }
12084 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
12085 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
12086 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
12087 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
12088 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
12089 { IBM424 cp424 ebcdic-cp-he csIBM424 }
12090 { IBM437 cp437 437 csPC8CodePage437 }
12091 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
12092 { IBM775 cp775 csPC775Baltic }
12093 { IBM850 cp850 850 csPC850Multilingual }
12094 { IBM851 cp851 851 csIBM851 }
12095 { IBM852 cp852 852 csPCp852 }
12096 { IBM855 cp855 855 csIBM855 }
12097 { IBM857 cp857 857 csIBM857 }
12098 { IBM860 cp860 860 csIBM860 }
12099 { IBM861 cp861 861 cp-is csIBM861 }
12100 { IBM862 cp862 862 csPC862LatinHebrew }
12101 { IBM863 cp863 863 csIBM863 }
12102 { IBM864 cp864 csIBM864 }
12103 { IBM865 cp865 865 csIBM865 }
12104 { IBM866 cp866 866 csIBM866 }
12105 { IBM868 CP868 cp-ar csIBM868 }
12106 { IBM869 cp869 869 cp-gr csIBM869 }
12107 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
12108 { IBM871 CP871 ebcdic-cp-is csIBM871 }
12109 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
12110 { IBM891 cp891 csIBM891 }
12111 { IBM903 cp903 csIBM903 }
12112 { IBM904 cp904 904 csIBBM904 }
12113 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
12114 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
12115 { IBM1026 CP1026 csIBM1026 }
12116 { EBCDIC-AT-DE csIBMEBCDICATDE }
12117 { EBCDIC-AT-DE-A csEBCDICATDEA }
12118 { EBCDIC-CA-FR csEBCDICCAFR }
12119 { EBCDIC-DK-NO csEBCDICDKNO }
12120 { EBCDIC-DK-NO-A csEBCDICDKNOA }
12121 { EBCDIC-FI-SE csEBCDICFISE }
12122 { EBCDIC-FI-SE-A csEBCDICFISEA }
12123 { EBCDIC-FR csEBCDICFR }
12124 { EBCDIC-IT csEBCDICIT }
12125 { EBCDIC-PT csEBCDICPT }
12126 { EBCDIC-ES csEBCDICES }
12127 { EBCDIC-ES-A csEBCDICESA }
12128 { EBCDIC-ES-S csEBCDICESS }
12129 { EBCDIC-UK csEBCDICUK }
12130 { EBCDIC-US csEBCDICUS }
12131 { UNKNOWN-8BIT csUnknown8BiT }
12132 { MNEMONIC csMnemonic }
12133 { MNEM csMnem }
12134 { VISCII csVISCII }
12135 { VIQR csVIQR }
12136 { KOI8-R csKOI8R }
12137 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
12138 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
12139 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
12140 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
12141 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
12142 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
12143 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
12144 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
12145 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
12146 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
12147 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
12148 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
12149 { IBM1047 IBM-1047 }
12150 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
12151 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
12152 { UNICODE-1-1 csUnicode11 }
12153 { CESU-8 csCESU-8 }
12154 { BOCU-1 csBOCU-1 }
12155 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
12156 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
12157 l8 }
12158 { ISO-8859-15 ISO_8859-15 Latin-9 }
12159 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
12160 { GBK CP936 MS936 windows-936 }
12161 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012162 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012163 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
12164 EUC-JP }
12165 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
12166 { ISO-10646-UCS-Basic csUnicodeASCII }
12167 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
12168 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
12169 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
12170 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
12171 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
12172 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
12173 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
12174 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
12175 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
12176 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
12177 { Adobe-Standard-Encoding csAdobeStandardEncoding }
12178 { Ventura-US csVenturaUS }
12179 { Ventura-International csVenturaInternational }
12180 { PC8-Danish-Norwegian csPC8DanishNorwegian }
12181 { PC8-Turkish csPC8Turkish }
12182 { IBM-Symbols csIBMSymbols }
12183 { IBM-Thai csIBMThai }
12184 { HP-Legal csHPLegal }
12185 { HP-Pi-font csHPPiFont }
12186 { HP-Math8 csHPMath8 }
12187 { Adobe-Symbol-Encoding csHPPSMath }
12188 { HP-DeskTop csHPDesktop }
12189 { Ventura-Math csVenturaMath }
12190 { Microsoft-Publishing csMicrosoftPublishing }
12191 { Windows-31J csWindows31J }
12192 { GB2312 csGB2312 }
12193 { Big5 csBig5 }
12194}
12195
12196proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012197 global encoding_aliases tcl_encoding_cache
12198 if {[info exists tcl_encoding_cache($enc)]} {
Denton Liue2445882020-09-10 21:36:33 -070012199 return $tcl_encoding_cache($enc)
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012200 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012201 set names [encoding names]
12202 set lcnames [string tolower $names]
12203 set enc [string tolower $enc]
12204 set i [lsearch -exact $lcnames $enc]
12205 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -070012206 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
12207 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
12208 set i [lsearch -exact $lcnames $encx]
12209 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012210 }
12211 if {$i < 0} {
Denton Liue2445882020-09-10 21:36:33 -070012212 foreach l $encoding_aliases {
12213 set ll [string tolower $l]
12214 if {[lsearch -exact $ll $enc] < 0} continue
12215 # look through the aliases for one that tcl knows about
12216 foreach e $ll {
12217 set i [lsearch -exact $lcnames $e]
12218 if {$i < 0} {
12219 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
12220 set i [lsearch -exact $lcnames $ex]
12221 }
12222 }
12223 if {$i >= 0} break
12224 }
12225 break
12226 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012227 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012228 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012229 if {$i >= 0} {
Denton Liue2445882020-09-10 21:36:33 -070012230 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012231 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012232 set tcl_encoding_cache($enc) $tclenc
12233 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012234}
12235
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012236proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012237 global path_attr_cache
12238 if {[info exists path_attr_cache($attr,$path)]} {
Denton Liue2445882020-09-10 21:36:33 -070012239 set r $path_attr_cache($attr,$path)
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012240 } else {
Denton Liue2445882020-09-10 21:36:33 -070012241 set r "unspecified"
12242 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
12243 regexp "(.*): $attr: (.*)" $line m f r
12244 }
12245 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012246 }
12247 if {$r eq "unspecified"} {
Denton Liue2445882020-09-10 21:36:33 -070012248 return $default
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012249 }
12250 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012251}
12252
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012253proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012254 global path_attr_cache
12255 set newlist {}
12256 foreach path $pathlist {
Denton Liue2445882020-09-10 21:36:33 -070012257 if {![info exists path_attr_cache($attr,$path)]} {
12258 lappend newlist $path
12259 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012260 }
12261 set lim 1000
12262 if {[tk windowingsystem] == "win32"} {
Denton Liue2445882020-09-10 21:36:33 -070012263 # windows has a 32k limit on the arguments to a command...
12264 set lim 30
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012265 }
12266 while {$newlist ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070012267 set head [lrange $newlist 0 [expr {$lim - 1}]]
12268 set newlist [lrange $newlist $lim end]
12269 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
12270 foreach row [split $rlist "\n"] {
12271 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
12272 if {[string index $path 0] eq "\""} {
12273 set path [encoding convertfrom [lindex $path 0]]
12274 }
12275 set path_attr_cache($attr,$path) $value
12276 }
12277 }
12278 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012279 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012280}
12281
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012282proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012283 global gui_encoding perfile_attrs
12284 set tcl_enc $gui_encoding
12285 if {$path ne {} && $perfile_attrs} {
Denton Liue2445882020-09-10 21:36:33 -070012286 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
12287 if {$enc2 ne {}} {
12288 set tcl_enc $enc2
12289 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012290 }
12291 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012292}
12293
Alex Henrieef87a482015-05-11 13:26:41 -060012294## For msgcat loading, first locate the installation location.
12295if { [info exists ::env(GITK_MSGSDIR)] } {
12296 ## Msgsdir was manually set in the environment.
12297 set gitk_msgsdir $::env(GITK_MSGSDIR)
12298} else {
12299 ## Let's guess the prefix from argv0.
12300 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
12301 set gitk_libdir [file join $gitk_prefix share gitk lib]
12302 set gitk_msgsdir [file join $gitk_libdir msgs]
12303 unset gitk_prefix
12304}
12305
12306## Internationalization (i18n) through msgcat and gettext. See
12307## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
12308package require msgcat
12309namespace import ::msgcat::mc
12310## And eventually load the actual message catalog
12311::msgcat::mcload $gitk_msgsdir
12312
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012313# First check that Tcl/Tk is recent enough
12314if {[catch {package require Tk 8.4} err]} {
Alex Henrieef87a482015-05-11 13:26:41 -060012315 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
Denton Liue2445882020-09-10 21:36:33 -070012316 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012317 exit 1
12318}
12319
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060012320# on OSX bring the current Wish process window to front
12321if {[tk windowingsystem] eq "aqua"} {
12322 exec osascript -e [format {
12323 tell application "System Events"
12324 set frontmost of processes whose unix id is %d to true
12325 end tell
12326 } [pid] ]
12327}
12328
Aske Olsson0ae10352012-05-10 12:13:43 +020012329# Unset GIT_TRACE var if set
12330if { [info exists ::env(GIT_TRACE)] } {
12331 unset ::env(GIT_TRACE)
12332}
12333
Paul Mackerras1d10f362005-05-15 12:55:47 +000012334# defaults...
Chris Packhame203d1d2014-11-02 21:37:50 +130012335set wrcomcmd "git diff-tree --stdin -p --pretty=email"
Junio C Hamano671bc152005-11-27 16:12:51 -080012336
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012337set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080012338catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110012339 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080012340}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030012341catch {
12342 set gitencoding [exec git config --get i18n.logoutputencoding]
12343}
Junio C Hamano671bc152005-11-27 16:12:51 -080012344if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012345 set gitencoding "utf-8"
12346}
12347set tclencoding [tcl_encoding $gitencoding]
12348if {$tclencoding == {}} {
12349 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080012350}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012351
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012352set gui_encoding [encoding system]
12353catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012354 set enc [exec git config --get gui.encoding]
12355 if {$enc ne {}} {
Denton Liue2445882020-09-10 21:36:33 -070012356 set tclenc [tcl_encoding $enc]
12357 if {$tclenc ne {}} {
12358 set gui_encoding $tclenc
12359 } else {
12360 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
12361 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012362 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012363}
12364
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020012365set log_showroot true
12366catch {
12367 set log_showroot [exec git config --bool --get log.showroot]
12368}
12369
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012370if {[tk windowingsystem] eq "aqua"} {
12371 set mainfont {{Lucida Grande} 9}
12372 set textfont {Monaco 9}
12373 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060012374} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
12375 # fontconfig!
12376 set mainfont {sans 9}
12377 set textfont {monospace 9}
12378 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012379} else {
12380 set mainfont {Helvetica 9}
12381 set textfont {Courier 9}
12382 set uifont {Helvetica 9 bold}
12383}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040012384set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040012385set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100012386set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100012387set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110012388set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110012389set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100012390set uparrowlen 5
12391set downarrowlen 5
12392set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100012393set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040012394set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100012395set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020012396set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100012397set maxrefs 20
Max Kirillovbde4a0f2014-06-24 08:19:44 +030012398set visiblerefs {"master"}
Paul Mackerras322a8cc2006-10-15 18:03:46 +100012399set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012400set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100012401set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020012402set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050012403set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110012404set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012405set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012406set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000012407
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012408if {[tk windowingsystem] eq "aqua"} {
12409 set extdifftool "opendiff"
12410} else {
12411 set extdifftool "meld"
12412}
Thomas Arcila314f5de2008-03-24 12:55:36 +010012413
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012414set colors {"#00ff00" red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012415if {[tk windowingsystem] eq "win32"} {
12416 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012417 set uifgcolor SystemButtonText
12418 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012419 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012420 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012421 set selectbgcolor SystemHighlight
Paul Mackerras3441de52019-08-27 08:12:34 +100012422 set web_browser "cmd /c start"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012423} else {
12424 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012425 set uifgcolor black
12426 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012427 set bgcolor white
12428 set fgcolor black
12429 set selectbgcolor gray85
Paul Mackerras3441de52019-08-27 08:12:34 +100012430 if {[tk windowingsystem] eq "aqua"} {
Denton Liue2445882020-09-10 21:36:33 -070012431 set web_browser "open"
Paul Mackerras3441de52019-08-27 08:12:34 +100012432 } else {
Denton Liue2445882020-09-10 21:36:33 -070012433 set web_browser "xdg-open"
Paul Mackerras3441de52019-08-27 08:12:34 +100012434 }
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012435}
Stefan Dotterweich113ce122020-02-11 22:24:48 +010012436set diffcolors {"#c30000" "#009800" blue}
12437set diffbgcolors {"#fff3f3" "#f0fff0"}
Steffen Prohaska890fae72007-08-12 12:05:46 +020012438set diffcontext 3
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012439set mergecolors {red blue "#00ff00" purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010012440set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020012441set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110012442set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000012443
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012444set headbgcolor "#00ff00"
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012445set headfgcolor black
12446set headoutlinecolor black
12447set remotebgcolor #ffddaa
12448set tagbgcolor yellow
12449set tagfgcolor black
12450set tagoutlinecolor black
12451set reflinecolor black
12452set filesepbgcolor #aaaaaa
12453set filesepfgcolor black
12454set linehoverbgcolor #ffff80
12455set linehoverfgcolor black
12456set linehoveroutlinecolor black
12457set mainheadcirclecolor yellow
12458set workingfilescirclecolor red
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012459set indexcirclecolor "#00ff00"
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012460set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012461set linkfgcolor blue
12462set circleoutlinecolor $fgcolor
12463set foundbgcolor yellow
12464set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012465
Paul Mackerrasd277e892008-09-21 18:11:37 -050012466# button for popping up context menus
12467if {[tk windowingsystem] eq "aqua"} {
12468 set ctxbut <Button-2>
12469} else {
12470 set ctxbut <Button-3>
12471}
12472
Astril Hayato8f863392014-01-21 19:10:16 +000012473catch {
12474 # follow the XDG base directory specification by default. See
12475 # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
12476 if {[info exists env(XDG_CONFIG_HOME)] && $env(XDG_CONFIG_HOME) ne ""} {
Denton Liue2445882020-09-10 21:36:33 -070012477 # XDG_CONFIG_HOME environment variable is set
12478 set config_file [file join $env(XDG_CONFIG_HOME) git gitk]
12479 set config_file_tmp [file join $env(XDG_CONFIG_HOME) git gitk-tmp]
Astril Hayato8f863392014-01-21 19:10:16 +000012480 } else {
Denton Liue2445882020-09-10 21:36:33 -070012481 # default XDG_CONFIG_HOME
12482 set config_file "~/.config/git/gitk"
12483 set config_file_tmp "~/.config/git/gitk-tmp"
Astril Hayato8f863392014-01-21 19:10:16 +000012484 }
12485 if {![file exists $config_file]} {
Denton Liue2445882020-09-10 21:36:33 -070012486 # for backward compatibility use the old config file if it exists
12487 if {[file exists "~/.gitk"]} {
12488 set config_file "~/.gitk"
12489 set config_file_tmp "~/.gitk-tmp"
12490 } elseif {![file exists [file dirname $config_file]]} {
12491 file mkdir [file dirname $config_file]
12492 }
Astril Hayato8f863392014-01-21 19:10:16 +000012493 }
12494 source $config_file
12495}
Max Kirilloveaf7e832015-03-04 05:58:18 +020012496config_check_tmp_exists 50
Paul Mackerras1d10f362005-05-15 12:55:47 +000012497
Max Kirillov9fabefb2014-09-14 23:35:57 +030012498set config_variables {
12499 mainfont textfont uifont tabstop findmergefiles maxgraphpct maxwidth
12500 cmitmode wrapcomment autoselect autosellen showneartags maxrefs visiblerefs
12501 hideremotes showlocalchanges datetimeformat limitdiffs uicolor want_ttk
12502 bgcolor fgcolor uifgcolor uifgdisabledcolor colors diffcolors mergecolors
12503 markbgcolor diffcontext selectbgcolor foundbgcolor currentsearchhitbgcolor
12504 extdifftool perfile_attrs headbgcolor headfgcolor headoutlinecolor
12505 remotebgcolor tagbgcolor tagfgcolor tagoutlinecolor reflinecolor
12506 filesepbgcolor filesepfgcolor linehoverbgcolor linehoverfgcolor
12507 linehoveroutlinecolor mainheadcirclecolor workingfilescirclecolor
Stefan Dotterweich113ce122020-02-11 22:24:48 +010012508 indexcirclecolor circlecolors linkfgcolor circleoutlinecolor diffbgcolors
Paul Mackerras3441de52019-08-27 08:12:34 +100012509 web_browser
Max Kirillov9fabefb2014-09-14 23:35:57 +030012510}
Max Kirillov995f7922015-03-04 05:58:16 +020012511foreach var $config_variables {
12512 config_init_trace $var
12513 trace add variable $var write config_variable_change_cb
12514}
Max Kirillov9fabefb2014-09-14 23:35:57 +030012515
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100012516parsefont mainfont $mainfont
12517eval font create mainfont [fontflags mainfont]
12518eval font create mainfontbold [fontflags mainfont 1]
12519
12520parsefont textfont $textfont
12521eval font create textfont [fontflags textfont]
12522eval font create textfontbold [fontflags textfont 1]
12523
12524parsefont uifont $uifont
12525eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000012526
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110012527setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020012528
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110012529setoptions
12530
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012531# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040012532if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012533 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020012534 exit 1
12535}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012536
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012537set selecthead {}
12538set selectheadid {}
12539
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012540set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012541set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012542set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010012543set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012544foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010012545 switch -glob -- $arg {
Denton Liue2445882020-09-10 21:36:33 -070012546 "" { }
12547 "--" {
12548 set cmdline_files [lrange $argv [expr {$i + 1}] end]
12549 break
12550 }
12551 "--select-commit=*" {
12552 set selecthead [string range $arg 16 end]
12553 }
12554 "--argscmd=*" {
12555 set revtreeargscmd [string range $arg 10 end]
12556 }
12557 default {
12558 lappend revtreeargs $arg
12559 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012560 }
12561 incr i
12562}
12563
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012564if {$selecthead eq "HEAD"} {
12565 set selecthead {}
12566}
12567
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012568if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012569 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012570 if {[catch {
Denton Liue2445882020-09-10 21:36:33 -070012571 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
12572 set cmdline_files [split $f "\n"]
12573 set n [llength $cmdline_files]
12574 set revtreeargs [lrange $revtreeargs 0 end-$n]
12575 # Unfortunately git rev-parse doesn't produce an error when
12576 # something is both a revision and a filename. To be consistent
12577 # with git log and git rev-list, check revtreeargs for filenames.
12578 foreach arg $revtreeargs {
12579 if {[file exists $arg]} {
12580 show_error {} . [mc "Ambiguous argument '%s': both revision\
12581 and filename" $arg]
12582 exit 1
12583 }
12584 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012585 } err]} {
Denton Liue2445882020-09-10 21:36:33 -070012586 # unfortunately we get both stdout and stderr in $err,
12587 # so look for "fatal:".
12588 set i [string first "fatal:" $err]
12589 if {$i > 0} {
12590 set err [string range $err [expr {$i + 6}] end]
12591 }
12592 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
12593 exit 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012594 }
12595}
12596
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012597set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012598set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012599set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012600
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012601set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012602if {![info exists have_ttk]} {
12603 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012604}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012605set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012606set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012607
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +010012608if {$use_ttk} {
12609 setttkstyle
12610}
12611
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012612regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012613
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012614set show_notes {}
12615if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12616 set show_notes "--show-notes"
12617}
12618
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012619set appname "gitk"
12620
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012621set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012622set history {}
12623set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012624set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012625set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012626set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012627set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012628set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012629set boldids {}
12630set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012631set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012632set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012633set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012634set need_redisplay 0
12635set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012636set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012637
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012638set nextviewnum 1
12639set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012640set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012641set selectedhlview [mc "None"]
12642set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012643set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012644set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012645set viewperm(0) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012646set viewchanged(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012647set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012648set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012649
Paul Mackerras94b4a692008-05-20 20:51:06 +100012650set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012651set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012652set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012653set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012654set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012655set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012656set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012657set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012658set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012659set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012660if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012661 set cdup [exec git rev-parse --show-cdup]
12662}
Junio C Hamanoe272a772020-01-23 11:20:36 -080012663set worktree [gitworktree]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012664setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012665makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012666catch {
12667 image create photo gitlogo -width 16 -height 16
12668
12669 image create photo gitlogominus -width 4 -height 2
12670 gitlogominus put #C00000 -to 0 0 4 2
12671 gitlogo copy gitlogominus -to 1 5
12672 gitlogo copy gitlogominus -to 6 5
12673 gitlogo copy gitlogominus -to 11 5
12674 image delete gitlogominus
12675
12676 image create photo gitlogoplus -width 4 -height 4
12677 gitlogoplus put #008000 -to 1 0 3 4
12678 gitlogoplus put #008000 -to 0 1 4 3
12679 gitlogo copy gitlogoplus -to 1 9
12680 gitlogo copy gitlogoplus -to 6 9
12681 gitlogo copy gitlogoplus -to 11 9
12682 image delete gitlogoplus
12683
Stephen Boydd38d7d42009-03-19 01:54:18 -070012684 image create photo gitlogo32 -width 32 -height 32
12685 gitlogo32 copy gitlogo -zoom 2 2
12686
12687 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012688}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012689# wait for the window to become visible
12690tkwait visibility .
Marc Branchaud9922c5a2015-04-07 11:51:51 -040012691set_window_title
Pat Thoyts478afad2009-04-15 17:14:03 +010012692update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012693readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012694
Yann Dirson2d480852008-02-21 21:23:31 +010012695if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012696 # create a view for the files/dirs specified on the command line
12697 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012698 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012699 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012700 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012701 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012702 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012703 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012704 set viewperm(1) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012705 set viewchanged(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012706 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012707 addviewmenu 1
Beat Bolli28de5682015-09-30 21:50:11 +020012708 .bar.view entryconf [mca "&Edit view..."] -state normal
12709 .bar.view entryconf [mca "&Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012710}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012711
12712if {[info exists permviews]} {
12713 foreach v $permviews {
Denton Liue2445882020-09-10 21:36:33 -070012714 set n $nextviewnum
12715 incr nextviewnum
12716 set viewname($n) [lindex $v 0]
12717 set viewfiles($n) [lindex $v 1]
12718 set viewargs($n) [lindex $v 2]
12719 set viewargscmd($n) [lindex $v 3]
12720 set viewperm($n) 1
12721 set viewchanged($n) 0
12722 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012723 }
12724}
Johannes Sixte4df5192008-12-18 08:30:49 +010012725
12726if {[tk windowingsystem] eq "win32"} {
12727 focus -force .
12728}
12729
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012730getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012731
12732# Local variables:
12733# mode: tcl
12734# indent-tabs-mode: t
12735# tab-width: 8
12736# End: