blob: 5cd00d80fe2fb80a07a59b7e5327f8ff6c29d8f6 [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 Mackerrasbb3e86a2011-07-24 15:34:48 +10005# Copyright © 2005-2011 Paul Mackerras. All rights reserved.
Paul Mackerras1db95b02005-05-09 04:08:39 +00006# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
Pat Thoytsd93f1712009-04-17 01:24:35 +010010package require Tk
11
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012proc hasworktree {} {
13 return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
14 [exec git rev-parse --is-inside-git-dir] == "false"}]
15}
16
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010017proc reponame {} {
18 global gitdir
19 set n [file normalize $gitdir]
20 if {[string match "*/.git" $n]} {
21 set n [string range $n 0 end-5]
22 }
23 return [file tail $n]
24}
25
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000026proc gitworktree {} {
27 variable _gitworktree
28 if {[info exists _gitworktree]} {
29 return $_gitworktree
30 }
31 # v1.7.0 introduced --show-toplevel to return the canonical work-tree
32 if {[catch {set _gitworktree [exec git rev-parse --show-toplevel]}]} {
33 # try to set work tree from environment, core.worktree or use
34 # cdup to obtain a relative path to the top of the worktree. If
35 # run from the top, the ./ prefix ensures normalize expands pwd.
36 if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
37 catch {set _gitworktree [exec git config --get core.worktree]}
38 if {$_gitworktree eq ""} {
39 set _gitworktree [file normalize ./[exec git rev-parse --show-cdup]]
40 }
41 }
42 }
43 return $_gitworktree
44}
45
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100046# A simple scheduler for compute-intensive stuff.
47# The aim is to make sure that event handlers for GUI actions can
48# run at least every 50-100 ms. Unfortunately fileevent handlers are
49# run before X event handlers, so reading from a fast source can
50# make the GUI completely unresponsive.
51proc run args {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040052 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100053
54 set script $args
55 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040056 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100057 after idle dorunq
58 }
59 lappend runq [list {} $script]
60 set isonrunq($script) 1
61}
62
63proc filerun {fd script} {
64 fileevent $fd readable [list filereadable $fd $script]
65}
66
67proc filereadable {fd script} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040068 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100069
70 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040071 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 after idle dorunq
73 }
74 lappend runq [list $fd $script]
75}
76
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110077proc nukefile {fd} {
78 global runq
79
80 for {set i 0} {$i < [llength $runq]} {} {
81 if {[lindex $runq $i 0] eq $fd} {
82 set runq [lreplace $runq $i $i]
83 } else {
84 incr i
85 }
86 }
87}
88
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100089proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040090 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100091
92 set tstart [clock clicks -milliseconds]
93 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110094 while {[llength $runq] > 0} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100095 set fd [lindex $runq 0 0]
96 set script [lindex $runq 0 1]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040097 set currunq [lindex $runq 0]
98 set runq [lrange $runq 1 end]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100099 set repeat [eval $script]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +0400100 unset currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000101 set t1 [clock clicks -milliseconds]
102 set t [expr {$t1 - $t0}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000103 if {$repeat ne {} && $repeat} {
104 if {$fd eq {} || $repeat == 2} {
105 # script returns 1 if it wants to be readded
106 # file readers return 2 if they could do more straight away
107 lappend runq [list $fd $script]
108 } else {
109 fileevent $fd readable [list filereadable $fd $script]
110 }
111 } elseif {$fd eq {}} {
112 unset isonrunq($script)
113 }
114 set t0 $t1
115 if {$t1 - $tstart >= 80} break
116 }
117 if {$runq ne {}} {
118 after idle dorunq
119 }
120}
121
Alexander Gavrilove439e092008-07-13 16:40:47 +0400122proc reg_instance {fd} {
123 global commfd leftover loginstance
124
125 set i [incr loginstance]
126 set commfd($i) $fd
127 set leftover($i) {}
128 return $i
129}
130
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000131proc unmerged_files {files} {
132 global nr_unmerged
133
134 # find the list of unmerged files
135 set mlist {}
136 set nr_unmerged 0
137 if {[catch {
138 set fd [open "| git ls-files -u" r]
139 } err]} {
140 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
141 exit 1
142 }
143 while {[gets $fd line] >= 0} {
144 set i [string first "\t" $line]
145 if {$i < 0} continue
146 set fname [string range $line [expr {$i+1}] end]
147 if {[lsearch -exact $mlist $fname] >= 0} continue
148 incr nr_unmerged
149 if {$files eq {} || [path_filter $files $fname]} {
150 lappend mlist $fname
151 }
152 }
153 catch {close $fd}
154 return $mlist
155}
156
157proc parseviewargs {n arglist} {
Christian Couderc2f2dab2009-12-12 05:52:39 +0100158 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
Thomas 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
Paul Mackerrasee66e082008-05-09 10:14:07 +1000163 set glflags {}
164 set diffargs {}
165 set nextisval 0
166 set revargs {}
167 set origargs $arglist
168 set allknown 1
169 set filtered 0
170 set i -1
171 foreach arg $arglist {
172 incr i
173 if {$nextisval} {
174 lappend glflags $arg
175 set nextisval 0
176 continue
177 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000178 switch -glob -- $arg {
179 "-d" -
180 "--date-order" {
181 set vdatemode($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000182 # remove from origargs in case we hit an unknown option
183 set origargs [lreplace $origargs $i $i]
184 incr i -1
185 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000186 "-[puabwcrRBMC]" -
187 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
188 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
189 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
190 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
191 "--ignore-space-change" - "-U*" - "--unified=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100192 # These request or affect diff output, which we don't want.
193 # Some could be used to set our defaults for diff display.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000194 lappend diffargs $arg
195 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000196 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200197 "--name-only" - "--name-status" - "--color" -
Paul Mackerrasee66e082008-05-09 10:14:07 +1000198 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
199 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
200 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
201 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
202 "--objects" - "--objects-edge" - "--reverse" {
Paul Mackerras29582282008-11-18 19:44:20 +1100203 # These cause our parsing of git log's output to fail, or else
204 # they're options we want to set ourselves, so ignore them.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000205 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200206 "--color-words*" - "--word-diff=color" {
207 # These trigger a word diff in the console interface,
208 # so help the user by enabling our own support
209 if {[package vcompare $git_version "1.7.2"] >= 0} {
210 set worddiff [mc "Color words"]
211 }
212 }
213 "--word-diff*" {
214 if {[package vcompare $git_version "1.7.2"] >= 0} {
215 set worddiff [mc "Markup words"]
216 }
217 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000218 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
219 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
220 "--full-history" - "--dense" - "--sparse" -
221 "--follow" - "--left-right" - "--encoding=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100222 # These are harmless, and some are even useful
Paul Mackerrasee66e082008-05-09 10:14:07 +1000223 lappend glflags $arg
224 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000225 "--diff-filter=*" - "--no-merges" - "--unpacked" -
226 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
227 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
228 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
229 "--remove-empty" - "--first-parent" - "--cherry-pick" -
Dirk Suesserottf687aaa2009-05-21 15:35:40 +0200230 "-S*" - "--pickaxe-all" - "--pickaxe-regex" -
231 "--simplify-by-decoration" {
Paul Mackerras29582282008-11-18 19:44:20 +1100232 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000233 set filtered 1
234 lappend glflags $arg
235 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000236 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100237 # This appears to be the only one that has a value as a
238 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000239 set filtered 1
240 set nextisval 1
241 lappend glflags $arg
242 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100243 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000244 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000245 }
246 "--merge" {
247 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000248 # git rev-parse doesn't understand --merge
249 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000250 }
Christian Couderc2f2dab2009-12-12 05:52:39 +0100251 "--no-replace-objects" {
252 set env(GIT_NO_REPLACE_OBJECTS) "1"
253 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000254 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100255 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000256 if {[string is digit -strict [string range $arg 1 end]]} {
257 set filtered 1
258 } else {
259 # a flag argument that we don't recognize;
260 # that means we can't optimize
261 set allknown 0
262 }
263 lappend glflags $arg
264 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000265 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100266 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000267 if {[string match "*...*" $arg]} {
268 lappend revargs --gitk-symmetric-diff-marker
269 }
270 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000271 }
272 }
273 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000274 set vdflags($n) $diffargs
275 set vflags($n) $glflags
276 set vrevs($n) $revargs
277 set vfiltered($n) $filtered
278 set vorigargs($n) $origargs
279 return $allknown
280}
281
282proc parseviewrevs {view revs} {
283 global vposids vnegids
284
285 if {$revs eq {}} {
286 set revs HEAD
287 }
288 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
289 # we get stdout followed by stderr in $err
290 # for an unknown rev, git rev-parse echoes it and then errors out
291 set errlines [split $err "\n"]
292 set badrev {}
293 for {set l 0} {$l < [llength $errlines]} {incr l} {
294 set line [lindex $errlines $l]
295 if {!([string length $line] == 40 && [string is xdigit $line])} {
296 if {[string match "fatal:*" $line]} {
297 if {[string match "fatal: ambiguous argument*" $line]
298 && $badrev ne {}} {
299 if {[llength $badrev] == 1} {
300 set err "unknown revision $badrev"
301 } else {
302 set err "unknown revisions: [join $badrev ", "]"
303 }
304 } else {
305 set err [join [lrange $errlines $l end] "\n"]
306 }
307 break
308 }
309 lappend badrev $line
310 }
Pat Thoytsd93f1712009-04-17 01:24:35 +0100311 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200312 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000313 return {}
314 }
315 set ret {}
316 set pos {}
317 set neg {}
318 set sdm 0
319 foreach id [split $ids "\n"] {
320 if {$id eq "--gitk-symmetric-diff-marker"} {
321 set sdm 4
322 } elseif {[string match "^*" $id]} {
323 if {$sdm != 1} {
324 lappend ret $id
325 if {$sdm == 3} {
326 set sdm 0
327 }
328 }
329 lappend neg [string range $id 1 end]
330 } else {
331 if {$sdm != 2} {
332 lappend ret $id
333 } else {
Thomas Rast2b1fbf92009-08-05 23:15:36 +0200334 lset ret end $id...[lindex $ret end]
Paul Mackerrasee66e082008-05-09 10:14:07 +1000335 }
336 lappend pos $id
337 }
338 incr sdm -1
339 }
340 set vposids($view) $pos
341 set vnegids($view) $neg
342 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000343}
344
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100345# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000346proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000347 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400348 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000349 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100350 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400351 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100352 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000353 global vcanopt vflags vrevs vorigargs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400354 global show_notes
Paul Mackerras38ad0912005-12-01 22:42:46 +1100355
356 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000357 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000358 # these are set this way for the error exits
359 set viewcomplete($view) 1
360 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100361 varcinit $view
362
Yann Dirson2d480852008-02-21 21:23:31 +0100363 set args $viewargs($view)
364 if {$viewargscmd($view) ne {}} {
365 if {[catch {
366 set str [exec sh -c $viewargscmd($view)]
367 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200368 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000369 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100370 }
371 set args [concat $args [split $str "\n"]]
372 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000373 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000374
375 set files $viewfiles($view)
376 if {$vmergeonly($view)} {
377 set files [unmerged_files $files]
378 if {$files eq {}} {
379 global nr_unmerged
380 if {$nr_unmerged == 0} {
381 error_popup [mc "No files selected: --merge specified but\
382 no files are unmerged."]
383 } else {
384 error_popup [mc "No files selected: --merge specified but\
385 no unmerged files are within file limit."]
386 }
387 return 0
388 }
389 }
390 set vfilelimit($view) $files
391
Paul Mackerrasee66e082008-05-09 10:14:07 +1000392 if {$vcanopt($view)} {
393 set revs [parseviewrevs $view $vrevs($view)]
394 if {$revs eq {}} {
395 return 0
396 }
397 set args [concat $vflags($view) $revs]
398 } else {
399 set args $vorigargs($view)
400 }
401
Paul Mackerras418c4c72006-02-07 09:10:18 +1100402 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400403 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
404 --parents --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100405 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100406 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000407 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100408 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400409 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100410 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100411 set viewmainheadid($view) $mainheadid
412 set viewmainheadid_orig($view) $mainheadid
413 if {$files ne {} && $mainheadid ne {}} {
414 get_viewmainhead $view
415 }
416 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
417 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000418 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400419 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100420 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000421 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100422 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100423 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100424 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000425 set viewcomplete($view) 0
426 set viewactive($view) 1
427 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100428}
429
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400430proc stop_instance {inst} {
431 global commfd leftover
432
433 set fd $commfd($inst)
434 catch {
435 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400436
437 if {$::tcl_platform(platform) eq {windows}} {
438 exec kill -f $pid
439 } else {
440 exec kill $pid
441 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400442 }
443 catch {close $fd}
444 nukefile $fd
445 unset commfd($inst)
446 unset leftover($inst)
447}
448
449proc stop_backends {} {
450 global commfd
451
452 foreach inst [array names commfd] {
453 stop_instance $inst
454 }
455}
456
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100457proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400458 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000459
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100460 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400461 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000462 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100463 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000464}
465
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400466proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400467 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400468
469 if {$selid ne {}} {
470 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400471 } elseif {$selectheadid ne {}} {
472 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400473 } else {
474 set pending_select $mainheadid
475 }
476}
477
478proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000479 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100480
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000481 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000482 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400483 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000484 show_status [mc "Reading commits..."]
485 set need_redisplay 1
486 } else {
487 show_status [mc "No commits selected"]
488 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000489}
490
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100491proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000492 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400493 global viewactive viewcomplete tclencoding
494 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100495 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400496 global hasworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000497 global varcid vposids vnegids vflags vrevs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400498 global show_notes
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100499
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400500 set hasworktree [hasworktree]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100501 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100502 set view $curview
503 if {$mainheadid ne $viewmainheadid_orig($view)} {
504 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100505 dohidelocalchanges
506 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100507 set viewmainheadid($view) $mainheadid
508 set viewmainheadid_orig($view) $mainheadid
509 if {$vfilelimit($view) ne {}} {
510 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100511 }
512 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100513 if {$showlocalchanges} {
514 doshowlocalchanges
515 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000516 if {$vcanopt($view)} {
517 set oldpos $vposids($view)
518 set oldneg $vnegids($view)
519 set revs [parseviewrevs $view $vrevs($view)]
520 if {$revs eq {}} {
521 return
522 }
523 # note: getting the delta when negative refs change is hard,
524 # and could require multiple git log invocations, so in that
525 # case we ask git log for all the commits (not just the delta)
526 if {$oldneg eq $vnegids($view)} {
527 set newrevs {}
528 set npos 0
529 # take out positive refs that we asked for before or
530 # that we have already seen
531 foreach rev $revs {
532 if {[string length $rev] == 40} {
533 if {[lsearch -exact $oldpos $rev] < 0
534 && ![info exists varcid($view,$rev)]} {
535 lappend newrevs $rev
536 incr npos
537 }
538 } else {
539 lappend $newrevs $rev
540 }
541 }
542 if {$npos == 0} return
543 set revs $newrevs
544 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
545 }
546 set args [concat $vflags($view) $revs --not $oldpos]
547 } else {
548 set args $vorigargs($view)
549 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100550 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400551 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
552 --parents --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100553 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200554 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000555 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100556 }
557 if {$viewactive($view) == 0} {
558 set startmsecs [clock clicks -milliseconds]
559 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400560 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100561 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100562 fconfigure $fd -blocking 0 -translation lf -eofchar {}
563 if {$tclencoding != {}} {
564 fconfigure $fd -encoding $tclencoding
565 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100566 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100567 incr viewactive($view)
568 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400569 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200570 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100571 if {$showneartags} {
572 getallcommits
573 }
574}
575
576proc reloadcommits {} {
577 global curview viewcomplete selectedline currentid thickerline
578 global showneartags treediffs commitinterest cached_commitrow
Paul Mackerras6df74032008-05-11 22:13:02 +1000579 global targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100580
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400581 set selid {}
582 if {$selectedline ne {}} {
583 set selid $currentid
584 }
585
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100586 if {!$viewcomplete($curview)} {
587 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100588 }
589 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000590 set selectedline {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100591 catch {unset currentid}
592 catch {unset thickerline}
593 catch {unset treediffs}
594 readrefs
595 changedrefs
596 if {$showneartags} {
597 getallcommits
598 }
599 clear_display
600 catch {unset commitinterest}
601 catch {unset cached_commitrow}
Paul Mackerras42a671f2008-01-02 09:59:39 +1100602 catch {unset targetid}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100603 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400604 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100605 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100606}
607
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000608# This makes a string representation of a positive integer which
609# sorts as a string in numerical order
610proc strrep {n} {
611 if {$n < 16} {
612 return [format "%x" $n]
613 } elseif {$n < 256} {
614 return [format "x%.2x" $n]
615 } elseif {$n < 65536} {
616 return [format "y%.4x" $n]
617 }
618 return [format "z%.8x" $n]
619}
620
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100621# Procedures used in reordering commits from git log (without
622# --topo-order) into the order for display.
623
624proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100625 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
626 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100627
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100628 set varcstart($view) {{}}
629 set vupptr($view) {0}
630 set vdownptr($view) {0}
631 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100632 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100633 set varctok($view) {{}}
634 set varcrow($view) {{}}
635 set vtokmod($view) {}
636 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100637 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100638 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100639 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100640}
641
642proc resetvarcs {view} {
643 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100644 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100645
646 foreach vid [array names varcid $view,*] {
647 unset varcid($vid)
648 unset children($vid)
649 unset parents($vid)
650 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100651 foreach vid [array names vshortids $view,*] {
652 unset vshortids($vid)
653 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100654 # some commits might have children but haven't been seen yet
655 foreach vid [array names children $view,*] {
656 unset children($vid)
657 }
658 foreach va [array names varccommits $view,*] {
659 unset varccommits($va)
660 }
661 foreach vd [array names vseedcount $view,*] {
662 unset vseedcount($vd)
663 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100664 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100665}
666
Paul Mackerras468bcae2008-03-03 10:19:35 +1100667# returns a list of the commits with no children
668proc seeds {v} {
669 global vdownptr vleftptr varcstart
670
671 set ret {}
672 set a [lindex $vdownptr($v) 0]
673 while {$a != 0} {
674 lappend ret [lindex $varcstart($v) $a]
675 set a [lindex $vleftptr($v) $a]
676 }
677 return $ret
678}
679
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100680proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000681 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100682 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
683 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100684
685 set a [llength $varctok($view)]
686 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000687 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100688 if {![info exists commitinfo($id)]} {
689 parsecommit $id $commitdata($id) 1
690 }
Anders Kaseorgf5974d92011-01-19 14:47:25 -0500691 set cdate [lindex [lindex $commitinfo($id) 4] 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100692 if {![string is integer -strict $cdate]} {
693 set cdate 0
694 }
695 if {![info exists vseedcount($view,$cdate)]} {
696 set vseedcount($view,$cdate) -1
697 }
698 set c [incr vseedcount($view,$cdate)]
699 set cdate [expr {$cdate ^ 0xffffffff}]
700 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100701 } else {
702 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100703 }
704 set ka 0
705 if {[llength $children($vid)] > 0} {
706 set kid [lindex $children($vid) end]
707 set k $varcid($view,$kid)
708 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
709 set ki $kid
710 set ka $k
711 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100712 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100713 }
714 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100715 set i [lsearch -exact $parents($view,$ki) $id]
716 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100717 append tok [strrep $j]
718 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100719 set c [lindex $vlastins($view) $ka]
720 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
721 set c $ka
722 set b [lindex $vdownptr($view) $ka]
723 } else {
724 set b [lindex $vleftptr($view) $c]
725 }
726 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
727 set c $b
728 set b [lindex $vleftptr($view) $c]
729 }
730 if {$c == $ka} {
731 lset vdownptr($view) $ka $a
732 lappend vbackptr($view) 0
733 } else {
734 lset vleftptr($view) $c $a
735 lappend vbackptr($view) $c
736 }
737 lset vlastins($view) $ka $a
738 lappend vupptr($view) $ka
739 lappend vleftptr($view) $b
740 if {$b != 0} {
741 lset vbackptr($view) $b $a
742 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100743 lappend varctok($view) $tok
744 lappend varcstart($view) $id
745 lappend vdownptr($view) 0
746 lappend varcrow($view) {}
747 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100748 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100749 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100750 return $a
751}
752
753proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100754 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100755 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100756
757 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100758 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100759 set ac $varccommits($v,$oa)
760 set i [lsearch -exact $varccommits($v,$oa) $p]
761 if {$i <= 0} return
762 set na [llength $varctok($v)]
763 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100764 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100765 lappend varctok($v) $tok
766 lappend varcrow($v) {}
767 lappend varcix($v) {}
768 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
769 set varccommits($v,$na) [lrange $ac $i end]
770 lappend varcstart($v) $p
771 foreach id $varccommits($v,$na) {
772 set varcid($v,$id) $na
773 }
774 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100775 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100776 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100777 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100778 lappend vupptr($v) $oa
779 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100780 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100781 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
782 lset vupptr($v) $b $na
783 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100784 if {[string compare $otok $vtokmod($v)] <= 0} {
785 modify_arc $v $oa
786 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100787}
788
789proc renumbervarc {a v} {
790 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000791 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100792
793 set t1 [clock clicks -milliseconds]
794 set todo {}
795 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100796 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100797 set ntot 0
798 while {$a != 0} {
799 if {[info exists isrelated($a)]} {
800 lappend todo $a
801 set id [lindex $varccommits($v,$a) end]
802 foreach p $parents($v,$id) {
803 if {[info exists varcid($v,$p)]} {
804 set isrelated($varcid($v,$p)) 1
805 }
806 }
807 }
808 incr ntot
809 set b [lindex $vdownptr($v) $a]
810 if {$b == 0} {
811 while {$a != 0} {
812 set b [lindex $vleftptr($v) $a]
813 if {$b != 0} break
814 set a [lindex $vupptr($v) $a]
815 }
816 }
817 set a $b
818 }
819 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100820 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100821 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100822 if {[llength $children($v,$id)] > 1} {
823 set children($v,$id) [lsort -command [list vtokcmp $v] \
824 $children($v,$id)]
825 }
826 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000827 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100828 set tok {}
829 } else {
830 set tok $oldtok
831 }
832 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100833 set kid [last_real_child $v,$id]
834 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100835 set k $varcid($v,$kid)
836 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
837 set ki $kid
838 set ka $k
839 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100840 }
841 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100842 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100843 set i [lsearch -exact $parents($v,$ki) $id]
844 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
845 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100846 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100847 if {$tok eq $oldtok} {
848 continue
849 }
850 set id [lindex $varccommits($v,$a) end]
851 foreach p $parents($v,$id) {
852 if {[info exists varcid($v,$p)]} {
853 set kidchanged($varcid($v,$p)) 1
854 } else {
855 set sortkids($p) 1
856 }
857 }
858 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100859 set b [lindex $vupptr($v) $a]
860 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100861 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
862 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100863 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100864 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
865 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100866 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100867 set c [lindex $vbackptr($v) $a]
868 set d [lindex $vleftptr($v) $a]
869 if {$c == 0} {
870 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100871 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100872 lset vleftptr($v) $c $d
873 }
874 if {$d != 0} {
875 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100876 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100877 if {[lindex $vlastins($v) $b] == $a} {
878 lset vlastins($v) $b $c
879 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100880 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100881 set c [lindex $vlastins($v) $ka]
882 if {$c == 0 || \
883 [string compare $tok [lindex $varctok($v) $c]] < 0} {
884 set c $ka
885 set b [lindex $vdownptr($v) $ka]
886 } else {
887 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100888 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100889 while {$b != 0 && \
890 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
891 set c $b
892 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100893 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100894 if {$c == $ka} {
895 lset vdownptr($v) $ka $a
896 lset vbackptr($v) $a 0
897 } else {
898 lset vleftptr($v) $c $a
899 lset vbackptr($v) $a $c
900 }
901 lset vleftptr($v) $a $b
902 if {$b != 0} {
903 lset vbackptr($v) $b $a
904 }
905 lset vlastins($v) $ka $a
906 }
907 }
908 foreach id [array names sortkids] {
909 if {[llength $children($v,$id)] > 1} {
910 set children($v,$id) [lsort -command [list vtokcmp $v] \
911 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100912 }
913 }
914 set t2 [clock clicks -milliseconds]
915 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
916}
917
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100918# Fix up the graph after we have found out that in view $v,
919# $p (a commit that we have already seen) is actually the parent
920# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100921proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100922 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100923
924 set pa $varcid($v,$p)
925 if {$p ne [lindex $varcstart($v) $pa]} {
926 splitvarc $p $v
927 set pa $varcid($v,$p)
928 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100929 # seeds always need to be renumbered
930 if {[lindex $vupptr($v) $pa] == 0 ||
931 [string compare [lindex $varctok($v) $a] \
932 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100933 renumbervarc $pa $v
934 }
935}
936
937proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100938 global cmitlisted children parents varcid varctok vtokmod
939 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100940 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100941
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100942 readcommit $id
943 set vid $v,$id
944 set cmitlisted($vid) 1
945 set children($vid) {}
946 set parents($vid) [list $p]
947 set a [newvarc $v $id]
948 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100949 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100950 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
951 modify_arc $v $a
952 }
953 lappend varccommits($v,$a) $id
954 set vp $v,$p
955 if {[llength [lappend children($vp) $id]] > 1} {
956 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
957 catch {unset ordertok}
958 }
959 fix_reversal $p $a $v
960 incr commitidx($v)
961 if {$v == $curview} {
962 set numcommits $commitidx($v)
963 setcanvscroll
964 if {[info exists targetid]} {
965 if {![comes_before $targetid $p]} {
966 incr targetrow
967 }
968 }
969 }
970}
971
972proc insertfakerow {id p} {
973 global varcid varccommits parents children cmitlisted
974 global commitidx varctok vtokmod targetid targetrow curview numcommits
975
976 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100977 set a $varcid($v,$p)
978 set i [lsearch -exact $varccommits($v,$a) $p]
979 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100980 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100981 return
982 }
983 set children($v,$id) {}
984 set parents($v,$id) [list $p]
985 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100986 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100987 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100988 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100989 # note we deliberately don't update varcstart($v) even if $i == 0
990 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100991 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +1100992 if {[info exists targetid]} {
993 if {![comes_before $targetid $p]} {
994 incr targetrow
995 }
996 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100997 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100998 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100999}
1000
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001001proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001002 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001003 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001004 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001005
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001006 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001007 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001008 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001009 return
1010 }
1011 set p [lindex $parents($v,$id) 0]
1012 set a $varcid($v,$id)
1013 set i [lsearch -exact $varccommits($v,$a) $id]
1014 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001015 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001016 return
1017 }
1018 unset varcid($v,$id)
1019 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1020 unset parents($v,$id)
1021 unset children($v,$id)
1022 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001023 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001024 set j [lsearch -exact $children($v,$p) $id]
1025 if {$j >= 0} {
1026 set children($v,$p) [lreplace $children($v,$p) $j $j]
1027 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001028 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001029 if {[info exist currentid] && $id eq $currentid} {
1030 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +10001031 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001032 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001033 if {[info exists targetid] && $targetid eq $id} {
1034 set targetid $p
1035 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001036 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001037 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001038}
1039
Paul Mackerrasaa435612009-09-10 21:58:40 +10001040proc real_children {vp} {
1041 global children nullid nullid2
1042
1043 set kids {}
1044 foreach id $children($vp) {
1045 if {$id ne $nullid && $id ne $nullid2} {
1046 lappend kids $id
1047 }
1048 }
1049 return $kids
1050}
1051
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001052proc first_real_child {vp} {
1053 global children nullid nullid2
1054
1055 foreach id $children($vp) {
1056 if {$id ne $nullid && $id ne $nullid2} {
1057 return $id
1058 }
1059 }
1060 return {}
1061}
1062
1063proc last_real_child {vp} {
1064 global children nullid nullid2
1065
1066 set kids $children($vp)
1067 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1068 set id [lindex $kids $i]
1069 if {$id ne $nullid && $id ne $nullid2} {
1070 return $id
1071 }
1072 }
1073 return {}
1074}
1075
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001076proc vtokcmp {v a b} {
1077 global varctok varcid
1078
1079 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1080 [lindex $varctok($v) $varcid($v,$b)]]
1081}
1082
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001083# This assumes that if lim is not given, the caller has checked that
1084# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001085proc modify_arc {v a {lim {}}} {
1086 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001087
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001088 if {$lim ne {}} {
1089 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1090 if {$c > 0} return
1091 if {$c == 0} {
1092 set r [lindex $varcrow($v) $a]
1093 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1094 }
1095 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001096 set vtokmod($v) [lindex $varctok($v) $a]
1097 set varcmod($v) $a
1098 if {$v == $curview} {
1099 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1100 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001101 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001102 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001103 set r 0
1104 if {$a != 0} {
1105 if {$lim eq {}} {
1106 set lim [llength $varccommits($v,$a)]
1107 }
1108 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1109 }
1110 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001111 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001112 }
1113}
1114
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001115proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001116 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001117 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001118 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001119 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001120
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001121 if {$vrowmod($v) == $commitidx($v)} return
1122 if {$v == $curview} {
1123 if {[llength $displayorder] > $vrowmod($v)} {
1124 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1125 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1126 }
1127 catch {unset cached_commitrow}
1128 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001129 set narctot [expr {[llength $varctok($v)] - 1}]
1130 set a $varcmod($v)
1131 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1132 # go up the tree until we find something that has a row number,
1133 # or we get to a seed
1134 set a [lindex $vupptr($v) $a]
1135 }
1136 if {$a == 0} {
1137 set a [lindex $vdownptr($v) 0]
1138 if {$a == 0} return
1139 set vrownum($v) {0}
1140 set varcorder($v) [list $a]
1141 lset varcix($v) $a 0
1142 lset varcrow($v) $a 0
1143 set arcn 0
1144 set row 0
1145 } else {
1146 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001147 if {[llength $vrownum($v)] > $arcn + 1} {
1148 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1149 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1150 }
1151 set row [lindex $varcrow($v) $a]
1152 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001153 while {1} {
1154 set p $a
1155 incr row [llength $varccommits($v,$a)]
1156 # go down if possible
1157 set b [lindex $vdownptr($v) $a]
1158 if {$b == 0} {
1159 # if not, go left, or go up until we can go left
1160 while {$a != 0} {
1161 set b [lindex $vleftptr($v) $a]
1162 if {$b != 0} break
1163 set a [lindex $vupptr($v) $a]
1164 }
1165 if {$a == 0} break
1166 }
1167 set a $b
1168 incr arcn
1169 lappend vrownum($v) $row
1170 lappend varcorder($v) $a
1171 lset varcix($v) $a $arcn
1172 lset varcrow($v) $a $row
1173 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001174 set vtokmod($v) [lindex $varctok($v) $p]
1175 set varcmod($v) $p
1176 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001177 if {[info exists currentid]} {
1178 set selectedline [rowofcommit $currentid]
1179 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001180}
1181
1182# Test whether view $v contains commit $id
1183proc commitinview {id v} {
1184 global varcid
1185
1186 return [info exists varcid($v,$id)]
1187}
1188
1189# Return the row number for commit $id in the current view
1190proc rowofcommit {id} {
1191 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001192 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001193
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001194 set v $curview
1195 if {![info exists varcid($v,$id)]} {
1196 puts "oops rowofcommit no arc for [shortids $id]"
1197 return {}
1198 }
1199 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001200 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001201 update_arcrows $v
1202 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001203 if {[info exists cached_commitrow($id)]} {
1204 return $cached_commitrow($id)
1205 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001206 set i [lsearch -exact $varccommits($v,$a) $id]
1207 if {$i < 0} {
1208 puts "oops didn't find commit [shortids $id] in arc $a"
1209 return {}
1210 }
1211 incr i [lindex $varcrow($v) $a]
1212 set cached_commitrow($id) $i
1213 return $i
1214}
1215
Paul Mackerras42a671f2008-01-02 09:59:39 +11001216# Returns 1 if a is on an earlier row than b, otherwise 0
1217proc comes_before {a b} {
1218 global varcid varctok curview
1219
1220 set v $curview
1221 if {$a eq $b || ![info exists varcid($v,$a)] || \
1222 ![info exists varcid($v,$b)]} {
1223 return 0
1224 }
1225 if {$varcid($v,$a) != $varcid($v,$b)} {
1226 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1227 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1228 }
1229 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1230}
1231
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001232proc bsearch {l elt} {
1233 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1234 return 0
1235 }
1236 set lo 0
1237 set hi [llength $l]
1238 while {$hi - $lo > 1} {
1239 set mid [expr {int(($lo + $hi) / 2)}]
1240 set t [lindex $l $mid]
1241 if {$elt < $t} {
1242 set hi $mid
1243 } elseif {$elt > $t} {
1244 set lo $mid
1245 } else {
1246 return $mid
1247 }
1248 }
1249 return $lo
1250}
1251
1252# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1253proc make_disporder {start end} {
1254 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001255 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001256 global d_valid_start d_valid_end
1257
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001258 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001259 update_arcrows $curview
1260 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001261 set ai [bsearch $vrownum($curview) $start]
1262 set start [lindex $vrownum($curview) $ai]
1263 set narc [llength $vrownum($curview)]
1264 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1265 set a [lindex $varcorder($curview) $ai]
1266 set l [llength $displayorder]
1267 set al [llength $varccommits($curview,$a)]
1268 if {$l < $r + $al} {
1269 if {$l < $r} {
1270 set pad [ntimes [expr {$r - $l}] {}]
1271 set displayorder [concat $displayorder $pad]
1272 set parentlist [concat $parentlist $pad]
1273 } elseif {$l > $r} {
1274 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1275 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1276 }
1277 foreach id $varccommits($curview,$a) {
1278 lappend displayorder $id
1279 lappend parentlist $parents($curview,$id)
1280 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001281 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001282 set i $r
1283 foreach id $varccommits($curview,$a) {
1284 lset displayorder $i $id
1285 lset parentlist $i $parents($curview,$id)
1286 incr i
1287 }
1288 }
1289 incr r $al
1290 }
1291}
1292
1293proc commitonrow {row} {
1294 global displayorder
1295
1296 set id [lindex $displayorder $row]
1297 if {$id eq {}} {
1298 make_disporder $row [expr {$row + 1}]
1299 set id [lindex $displayorder $row]
1300 }
1301 return $id
1302}
1303
1304proc closevarcs {v} {
1305 global varctok varccommits varcid parents children
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001306 global cmitlisted commitidx vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001307
1308 set missing_parents 0
1309 set scripts {}
1310 set narcs [llength $varctok($v)]
1311 for {set a 1} {$a < $narcs} {incr a} {
1312 set id [lindex $varccommits($v,$a) end]
1313 foreach p $parents($v,$id) {
1314 if {[info exists varcid($v,$p)]} continue
1315 # add p as a new commit
1316 incr missing_parents
1317 set cmitlisted($v,$p) 0
1318 set parents($v,$p) {}
1319 if {[llength $children($v,$p)] == 1 &&
1320 [llength $parents($v,$id)] == 1} {
1321 set b $a
1322 } else {
1323 set b [newvarc $v $p]
1324 }
1325 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001326 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1327 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001328 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001329 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001330 incr commitidx($v)
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001331 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001332 }
1333 }
1334 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001335 foreach s $scripts {
1336 eval $s
1337 }
1338 }
1339}
1340
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001341# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1342# Assumes we already have an arc for $rwid.
1343proc rewrite_commit {v id rwid} {
1344 global children parents varcid varctok vtokmod varccommits
1345
1346 foreach ch $children($v,$id) {
1347 # make $rwid be $ch's parent in place of $id
1348 set i [lsearch -exact $parents($v,$ch) $id]
1349 if {$i < 0} {
1350 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1351 }
1352 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1353 # add $ch to $rwid's children and sort the list if necessary
1354 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1355 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1356 $children($v,$rwid)]
1357 }
1358 # fix the graph after joining $id to $rwid
1359 set a $varcid($v,$ch)
1360 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001361 # parentlist is wrong for the last element of arc $a
1362 # even if displayorder is right, hence the 3rd arg here
1363 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001364 }
1365}
1366
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001367# Mechanism for registering a command to be executed when we come
1368# across a particular commit. To handle the case when only the
1369# prefix of the commit is known, the commitinterest array is now
1370# indexed by the first 4 characters of the ID. Each element is a
1371# list of id, cmd pairs.
1372proc interestedin {id cmd} {
1373 global commitinterest
1374
1375 lappend commitinterest([string range $id 0 3]) $id $cmd
1376}
1377
1378proc check_interest {id scripts} {
1379 global commitinterest
1380
1381 set prefix [string range $id 0 3]
1382 if {[info exists commitinterest($prefix)]} {
1383 set newlist {}
1384 foreach {i script} $commitinterest($prefix) {
1385 if {[string match "$i*" $id]} {
1386 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1387 } else {
1388 lappend newlist $i $script
1389 }
1390 }
1391 if {$newlist ne {}} {
1392 set commitinterest($prefix) $newlist
1393 } else {
1394 unset commitinterest($prefix)
1395 }
1396 }
1397 return $scripts
1398}
1399
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001400proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001401 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001402 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001403 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001404 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001405 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001406
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001407 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001408 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001409 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001410 set stuff "\0"
1411 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001412 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001413 if {![eof $fd]} {
1414 return 1
1415 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001416 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001417 global viewinstances
1418 unset commfd($inst)
1419 set i [lsearch -exact $viewinstances($view) $inst]
1420 if {$i >= 0} {
1421 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001422 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001423 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001424 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001425 if {[catch {close $fd} err]} {
1426 set fv {}
1427 if {$view != $curview} {
1428 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001429 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001430 if {[string range $err 0 4] == "usage"} {
1431 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001432 bad arguments to git log."
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001433 if {$viewname($view) eq "Command line"} {
1434 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001435 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001436 to allow selection of commits to be displayed.)"
1437 }
1438 } else {
1439 set err "Error reading commits$fv: $err"
1440 }
1441 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001442 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001443 if {[incr viewactive($view) -1] <= 0} {
1444 set viewcomplete($view) 1
1445 # Check if we have seen any ids listed as parents that haven't
1446 # appeared in the list
1447 closevarcs $view
1448 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001449 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001450 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001451 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001452 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001453 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001454 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001455 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001456 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001457 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001458 while 1 {
1459 set i [string first "\0" $stuff $start]
1460 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001461 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001462 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001463 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001464 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001465 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001466 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001467 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001468 } else {
1469 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001470 }
1471 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001472 set j [string first "\n" $cmit]
1473 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001474 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001475 if {$j >= 0 && [string match "commit *" $cmit]} {
1476 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001477 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001478 switch -- [string index $ids 0] {
1479 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001480 "^" {set listed 2}
1481 "<" {set listed 3}
1482 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001483 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001484 set ids [string range $ids 1 end]
1485 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001486 set ok 1
1487 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001488 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001489 set ok 0
1490 break
1491 }
1492 }
1493 }
1494 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001495 set shortcmit $cmit
1496 if {[string length $shortcmit] > 80} {
1497 set shortcmit "[string range $shortcmit 0 80]..."
1498 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001499 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001500 exit 1
1501 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001502 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001503 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001504
Paul Mackerras22387f22012-03-19 11:21:08 +11001505 lappend vshortids($view,[string range $id 0 3]) $id
1506
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001507 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001508 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001509 # git log doesn't rewrite parents for unlisted commits
1510 # when doing path limiting, so work around that here
1511 # by working out the rewritten parent with git rev-list
1512 # and if we already know about it, using the rewritten
1513 # parent as a substitute parent for $id's children.
1514 if {![catch {
1515 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001516 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001517 }]} {
1518 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1519 # use $rwid in place of $id
1520 rewrite_commit $view $id $rwid
1521 continue
1522 }
1523 }
1524 }
1525
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001526 set a 0
1527 if {[info exists varcid($vid)]} {
1528 if {$cmitlisted($vid) || !$listed} continue
1529 set a $varcid($vid)
1530 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001531 if {$listed} {
1532 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001533 } else {
1534 set olds {}
1535 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001536 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001537 set cmitlisted($vid) $listed
1538 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001539 if {![info exists children($vid)]} {
1540 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001541 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001542 set k [lindex $children($vid) 0]
1543 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001544 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001545 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1546 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001547 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001548 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001549 if {$a == 0} {
1550 # new arc
1551 set a [newvarc $view $id]
1552 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001553 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1554 modify_arc $view $a
1555 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001556 if {![info exists varcid($vid)]} {
1557 set varcid($vid) $a
1558 lappend varccommits($view,$a) $id
1559 incr commitidx($view)
1560 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001561
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001562 set i 0
1563 foreach p $olds {
1564 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1565 set vp $view,$p
1566 if {[llength [lappend children($vp) $id]] > 1 &&
1567 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1568 set children($vp) [lsort -command [list vtokcmp $view] \
1569 $children($vp)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001570 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001571 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001572 if {[info exists varcid($view,$p)]} {
1573 fix_reversal $p $a $view
1574 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001575 }
1576 incr i
1577 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001578
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001579 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001580 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001581 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001582 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001583 global numcommits hlview
1584
1585 if {$view == $curview} {
1586 set numcommits $commitidx($view)
1587 run chewcommits
1588 }
1589 if {[info exists hlview] && $view == $hlview} {
1590 # we never actually get here...
1591 run vhighlightmore
1592 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001593 foreach s $scripts {
1594 eval $s
1595 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001596 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001597 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001598}
1599
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001600proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001601 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001602 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001603
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001604 layoutmore
1605 if {$viewcomplete($curview)} {
1606 global commitidx varctok
1607 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001608
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001609 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001610 update
1611 reset_pending_select {}
1612
1613 if {[commitinview $pending_select $curview]} {
1614 selectline [rowofcommit $pending_select] 1
1615 } else {
1616 set row [first_real_row]
1617 selectline $row 1
1618 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001619 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001620 if {$commitidx($curview) > 0} {
1621 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1622 #puts "overall $ms ms for $numcommits commits"
1623 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1624 } else {
1625 show_status [mc "No commits selected"]
1626 }
1627 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001628 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001629 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001630}
1631
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001632proc do_readcommit {id} {
1633 global tclencoding
1634
1635 # Invoke git-log to handle automatic encoding conversion
1636 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1637 # Read the results using i18n.logoutputencoding
1638 fconfigure $fd -translation lf -eofchar {}
1639 if {$tclencoding != {}} {
1640 fconfigure $fd -encoding $tclencoding
1641 }
1642 set contents [read $fd]
1643 close $fd
1644 # Remove the heading line
1645 regsub {^commit [0-9a-f]+\n} $contents {} contents
1646
1647 return $contents
1648}
1649
Paul Mackerras1db95b02005-05-09 04:08:39 +00001650proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001651 if {[catch {set contents [do_readcommit $id]}]} return
1652 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001653}
1654
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001655proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001656 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001657
1658 set inhdr 1
1659 set comment {}
1660 set headline {}
1661 set auname {}
1662 set audate {}
1663 set comname {}
1664 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001665 set hdrend [string first "\n\n" $contents]
1666 if {$hdrend < 0} {
1667 # should never happen...
1668 set hdrend [string length $contents]
1669 }
1670 set header [string range $contents 0 [expr {$hdrend - 1}]]
1671 set comment [string range $contents [expr {$hdrend + 2}] end]
1672 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001673 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001674 set tag [lindex $line 0]
1675 if {$tag == "author"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001676 set audate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001677 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001678 } elseif {$tag == "committer"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001679 set comdate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001680 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001681 }
1682 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001683 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001684 # take the first non-blank line of the comment as the headline
1685 set headline [string trimleft $comment]
1686 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001687 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001688 set headline [string range $headline 0 $i]
1689 }
1690 set headline [string trimright $headline]
1691 set i [string first "\r" $headline]
1692 if {$i >= 0} {
1693 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001694 }
1695 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001696 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001697 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001698 set newcomment {}
1699 foreach line [split $comment "\n"] {
1700 append newcomment " "
1701 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001702 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001703 }
1704 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001705 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001706 set hasnote [string first "\nNotes:\n" $contents]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001707 set commitinfo($id) [list $headline $auname $audate \
Raphael Zimmerer36242492011-04-19 22:37:09 +02001708 $comname $comdate $comment $hasnote]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001709}
1710
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001711proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001712 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001713
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001714 if {[info exists commitdata($id)]} {
1715 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001716 } else {
1717 readcommit $id
1718 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001719 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001720 }
1721 }
1722 return 1
1723}
1724
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001725# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1726# and are present in the current view.
1727# This is fairly slow...
1728proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001729 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001730
1731 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001732 if {[string length $prefix] >= 4} {
1733 set vshortid $curview,[string range $prefix 0 3]
1734 if {[info exists vshortids($vshortid)]} {
1735 foreach id $vshortids($vshortid) {
1736 if {[string match "$prefix*" $id]} {
1737 if {[lsearch -exact $ids $id] < 0} {
1738 lappend ids $id
1739 if {[llength $ids] >= 2} break
1740 }
1741 }
1742 }
1743 }
1744 } else {
1745 foreach match [array names varcid "$curview,$prefix*"] {
1746 lappend ids [lindex [split $match ","] 1]
1747 if {[llength $ids] >= 2} break
1748 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001749 }
1750 return $ids
1751}
1752
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001753proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001754 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001755 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001756 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001757 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001758
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001759 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
1760 catch {unset $v}
1761 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001762 set refd [open [list | git show-ref -d] r]
1763 while {[gets $refd line] >= 0} {
1764 if {[string index $line 40] ne " "} continue
1765 set id [string range $line 0 39]
1766 set ref [string range $line 41 end]
1767 if {![string match "refs/*" $ref]} continue
1768 set name [string range $ref 5 end]
1769 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001770 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001771 set headids($name) $id
1772 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001773 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001774 } elseif {[string match "heads/*" $name]} {
1775 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001776 set headids($name) $id
1777 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001778 } elseif {[string match "tags/*" $name]} {
1779 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1780 # which is what we want since the former is the commit ID
1781 set name [string range $name 5 end]
1782 if {[string match "*^{}" $name]} {
1783 set name [string range $name 0 end-3]
1784 } else {
1785 set tagobjid($name) $id
1786 }
1787 set tagids($name) $id
1788 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001789 } else {
1790 set otherrefids($name) $id
1791 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001792 }
1793 }
Alex Riesen062d6712007-07-29 22:28:40 +02001794 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001795 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001796 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001797 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001798 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001799 set thehead [exec git symbolic-ref HEAD]
1800 if {[string match "refs/heads/*" $thehead]} {
1801 set mainhead [string range $thehead 11 end]
1802 }
1803 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001804 set selectheadid {}
1805 if {$selecthead ne {}} {
1806 catch {
1807 set selectheadid [exec git rev-parse --verify $selecthead]
1808 }
1809 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001810}
1811
Paul Mackerras8f489362007-07-13 19:49:37 +10001812# skip over fake commits
1813proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001814 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001815
1816 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001817 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001818 if {$id ne $nullid && $id ne $nullid2} {
1819 break
1820 }
1821 }
1822 return $row
1823}
1824
Paul Mackerrase11f1232007-06-16 20:29:25 +10001825# update things for a head moved to a child of its previous location
1826proc movehead {id name} {
1827 global headids idheads
1828
1829 removehead $headids($name) $name
1830 set headids($name) $id
1831 lappend idheads($id) $name
1832}
1833
1834# update things when a head has been removed
1835proc removehead {id name} {
1836 global headids idheads
1837
1838 if {$idheads($id) eq $name} {
1839 unset idheads($id)
1840 } else {
1841 set i [lsearch -exact $idheads($id) $name]
1842 if {$i >= 0} {
1843 set idheads($id) [lreplace $idheads($id) $i $i]
1844 }
1845 }
1846 unset headids($name)
1847}
1848
Pat Thoytsd93f1712009-04-17 01:24:35 +01001849proc ttk_toplevel {w args} {
1850 global use_ttk
1851 eval [linsert $args 0 ::toplevel $w]
1852 if {$use_ttk} {
1853 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1854 }
1855 return $w
1856}
1857
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001858proc make_transient {window origin} {
1859 global have_tk85
1860
1861 # In MacOS Tk 8.4 transient appears to work by setting
1862 # overrideredirect, which is utterly useless, since the
1863 # windows get no border, and are not even kept above
1864 # the parent.
1865 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1866
1867 wm transient $window $origin
1868
1869 # Windows fails to place transient windows normally, so
1870 # schedule a callback to center them on the parent.
1871 if {[tk windowingsystem] eq {win32}} {
1872 after idle [list tk::PlaceWindow $window widget $origin]
1873 }
1874}
1875
Bernt Hansen8d849952009-11-02 07:41:00 -05001876proc show_error {w top msg {mc mc}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001877 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001878 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001879 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001880 message $w.m -text $msg -justify center -aspect 400
1881 pack $w.m -side top -fill x -padx 20 -pady 20
Paul Mackerras7a0ebbf2009-11-14 21:26:31 +11001882 ${NS}::button $w.ok -default active -text [$mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001883 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001884 bind $top <Visibility> "grab $top; focus $top"
1885 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001886 bind $top <Key-space> "destroy $top"
1887 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001888 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001889}
1890
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001891proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001892 if {[tk windowingsystem] eq "win32"} {
1893 tk_messageBox -icon error -type ok -title [wm title .] \
1894 -parent $owner -message $msg
1895 } else {
1896 set w .error
1897 ttk_toplevel $w
1898 make_transient $w $owner
1899 show_error $w $w $msg
1900 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001901}
1902
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001903proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001904 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001905 set confirm_ok 0
1906 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001907 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001908 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001909 message $w.m -text $msg -justify center -aspect 400
1910 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001911 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001912 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001913 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001914 pack $w.cancel -side right -fill x
1915 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001916 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1917 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1918 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001919 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001920 tkwait window $w
1921 return $confirm_ok
1922}
1923
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001924proc setoptions {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001925 if {[tk windowingsystem] ne "win32"} {
1926 option add *Panedwindow.showHandle 1 startupFile
1927 option add *Panedwindow.sashRelief raised startupFile
1928 if {[tk windowingsystem] ne "aqua"} {
1929 option add *Menu.font uifont startupFile
1930 }
1931 } else {
1932 option add *Menu.TearOff 0 startupFile
1933 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001934 option add *Button.font uifont startupFile
1935 option add *Checkbutton.font uifont startupFile
1936 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001937 option add *Menubutton.font uifont startupFile
1938 option add *Label.font uifont startupFile
1939 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001940 option add *Entry.font textfont startupFile
1941 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001942 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001943 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001944 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001945}
1946
Paul Mackerras79056032008-10-18 16:24:46 +11001947# Make a menu and submenus.
1948# m is the window name for the menu, items is the list of menu items to add.
1949# Each item is a list {mc label type description options...}
1950# mc is ignored; it's so we can put mc there to alert xgettext
1951# label is the string that appears in the menu
1952# type is cascade, command or radiobutton (should add checkbutton)
1953# description depends on type; it's the sublist for cascade, the
1954# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001955proc makemenu {m items} {
1956 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001957 if {[tk windowingsystem] eq {aqua}} {
1958 set Meta1 Cmd
1959 } else {
1960 set Meta1 Ctrl
1961 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001962 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11001963 set name [mc [lindex $i 1]]
1964 set type [lindex $i 2]
1965 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001966 set params [list $type]
1967 if {$name ne {}} {
1968 set u [string first "&" [string map {&& x} $name]]
1969 lappend params -label [string map {&& & & {}} $name]
1970 if {$u >= 0} {
1971 lappend params -underline $u
1972 }
1973 }
1974 switch -- $type {
1975 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11001976 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001977 lappend params -menu $m.$submenu
1978 }
1979 "command" {
1980 lappend params -command $thing
1981 }
1982 "radiobutton" {
1983 lappend params -variable [lindex $thing 0] \
1984 -value [lindex $thing 1]
1985 }
1986 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001987 set tail [lrange $i 4 end]
1988 regsub -all {\yMeta1\y} $tail $Meta1 tail
1989 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001990 if {$type eq "cascade"} {
1991 makemenu $m.$submenu $thing
1992 }
1993 }
1994}
1995
1996# translate string and remove ampersands
1997proc mca {str} {
1998 return [string map {&& & & {}} [mc $str]]
1999}
2000
Paul Mackerras39c12692013-05-11 17:08:41 +10002001proc cleardropsel {w} {
2002 $w selection clear
2003}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002004proc makedroplist {w varname args} {
2005 global use_ttk
2006 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002007 set width 0
2008 foreach label $args {
2009 set cx [string length $label]
2010 if {$cx > $width} {set width $cx}
2011 }
2012 set gm [ttk::combobox $w -width $width -state readonly\
Paul Mackerras39c12692013-05-11 17:08:41 +10002013 -textvariable $varname -values $args \
2014 -exportselection false]
2015 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002016 } else {
2017 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
2018 }
2019 return $gm
2020}
2021
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002022proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002023 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002024 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002025 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002026 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002027 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002028 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002029 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002030 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002031 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002032 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04002033 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002034 global uifgcolor uifgdisabledcolor
2035 global filesepbgcolor filesepfgcolor
2036 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002037 global headctxmenu progresscanv progressitem progresscoords statusw
2038 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002039 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002040 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002041 global git_version
2042 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002043
Paul Mackerras79056032008-10-18 16:24:46 +11002044 # The "mc" arguments here are purely so that xgettext
2045 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002046 set file {
2047 mc "File" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002048 {mc "Update" command updatecommits -accelerator F5}
Felipe Contrerasa135f212012-04-07 03:29:38 +03002049 {mc "Reload" command reloadcommits -accelerator Shift-F5}
Paul Mackerras79056032008-10-18 16:24:46 +11002050 {mc "Reread references" command rereadrefs}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002051 {mc "List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002052 {xx "" separator}
2053 {mc "Start git gui" command {exec git gui &}}
2054 {xx "" separator}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002055 {mc "Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002056 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002057 set edit {
2058 mc "Edit" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002059 {mc "Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002060 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002061 set view {
2062 mc "View" cascade {
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002063 {mc "New view..." command {newview 0} -accelerator Shift-F4}
2064 {mc "Edit view..." command editview -state disabled -accelerator F4}
Paul Mackerras79056032008-10-18 16:24:46 +11002065 {mc "Delete view" command delview -state disabled}
2066 {xx "" separator}
2067 {mc "All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002068 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002069 if {[tk windowingsystem] ne "aqua"} {
2070 set help {
2071 mc "Help" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002072 {mc "About gitk" command about}
2073 {mc "Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002074 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002075 set bar [list $file $edit $view $help]
2076 } else {
2077 proc ::tk::mac::ShowPreferences {} {doprefs}
2078 proc ::tk::mac::Quit {} {doquit}
2079 lset file end [lreplace [lindex $file end] end-1 end]
2080 set apple {
2081 xx "Apple" cascade {
2082 {mc "About gitk" command about}
2083 {xx "" separator}
2084 }}
2085 set help {
2086 mc "Help" cascade {
2087 {mc "Key bindings" command keys}
2088 }}
2089 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002090 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002091 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002092 . configure -menu .bar
2093
Pat Thoytsd93f1712009-04-17 01:24:35 +01002094 if {$use_ttk} {
2095 # cover the non-themed toplevel with a themed frame.
2096 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2097 }
2098
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002099 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002100 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002101
2102 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002103 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002104 set geometry(topheight) [expr {15 * $linespc}]
2105 set geometry(topwidth) [expr {80 * $charspc}]
2106 set geometry(botheight) [expr {15 * $linespc}]
2107 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002108 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2109 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002110 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002111
2112 # 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 +01002113 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2114 ${NS}::frame .tf.histframe
2115 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2116 if {!$use_ttk} {
2117 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
2118 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002119
2120 # create three canvases
2121 set cscroll .tf.histframe.csb
2122 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002123 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04002124 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002125 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002126 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002127 .tf.histframe.pwclist add $canv
2128 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002129 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002130 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002131 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002132 .tf.histframe.pwclist add $canv2
2133 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002134 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002135 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002136 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002137 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002138 if {$use_ttk} {
2139 bind .tf.histframe.pwclist <Map> {
2140 bind %W <Map> {}
2141 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2142 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2143 }
2144 } else {
2145 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2146 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
2147 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002148
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002149 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002150 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2151 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002152 pack $cscroll -side right -fill y
2153 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2154 lappend bglist $canv $canv2 $canv3
2155 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2156
2157 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002158 ${NS}::frame .tf.bar
2159 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002160
2161 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002162 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002163 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002164 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002165 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002166 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002167 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002168 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002169 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002170 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002171
Stefan Hallerf062e502012-09-22 09:46:48 +02002172 set bm_left_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002173 #define left_width 16
2174 #define left_height 16
2175 static unsigned char left_bits[] = {
2176 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2177 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2178 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2179 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002180 set bm_right_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002181 #define right_width 16
2182 #define right_height 16
2183 static unsigned char right_bits[] = {
2184 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2185 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2186 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2187 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002188 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2189 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2190 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2191 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002192
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002193 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2194 if {$use_ttk} {
2195 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
2196 } else {
2197 .tf.bar.leftbut configure -image bm-left
2198 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002199 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002200 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2201 if {$use_ttk} {
2202 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
2203 } else {
2204 .tf.bar.rightbut configure -image bm-right
2205 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002206 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002207
Pat Thoytsd93f1712009-04-17 01:24:35 +01002208 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002209 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002210 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Paul Mackerras6df74032008-05-11 22:13:02 +10002211 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002212 ${NS}::label .tf.bar.rowlabel2 -text "/"
2213 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Paul Mackerras6df74032008-05-11 22:13:02 +10002214 -relief sunken -anchor e
2215 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2216 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002217 if {!$use_ttk} {
2218 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2219 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002220 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002221 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002222
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002223 # Status label and progress bar
2224 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002225 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002226 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002227 if {$use_ttk} {
2228 set progresscanv [ttk::progressbar .tf.bar.progress]
2229 } else {
2230 set h [expr {[font metrics uifont -linespace] + 2}]
2231 set progresscanv .tf.bar.progress
2232 canvas $progresscanv -relief sunken -height $h -borderwidth 2
2233 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
2234 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2235 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
2236 }
2237 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002238 set progresscoords {0 0}
2239 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002240 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002241 bind $progresscanv <Configure> adjustprogress
2242 set lastprogupdate [clock clicks -milliseconds]
2243 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002244
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002245 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002246 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
2247 ${NS}::button .tf.lbar.fnext -text [mc "next"] -command {dofind 1 1}
2248 ${NS}::button .tf.lbar.fprev -text [mc "prev"] -command {dofind -1 1}
2249 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Paul Mackerras687c8762007-09-22 12:49:33 +10002250 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2251 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002252 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002253 set gm [makedroplist .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002254 [mc "containing:"] \
2255 [mc "touching paths:"] \
Martin Langhoffc33cb902012-06-14 20:34:11 +02002256 [mc "adding/removing string:"] \
2257 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002258 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002259 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002260
2261 set findstring {}
2262 set fstring .tf.lbar.findstring
2263 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002264 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002265 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002266 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002267 set findtypemenu [makedroplist .tf.lbar.findtype \
2268 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002269 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002270 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002271 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002272 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002273 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002274 pack .tf.lbar.findloc -side right
2275 pack .tf.lbar.findtype -side right
2276 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002277
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002278 # Finish putting the upper half of the viewer together
2279 pack .tf.lbar -in .tf -side bottom -fill x
2280 pack .tf.bar -in .tf -side bottom -fill x
2281 pack .tf.histframe -fill both -side top -expand 1
2282 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002283 if {!$use_ttk} {
2284 .ctop paneconfigure .tf -height $geometry(topheight)
2285 .ctop paneconfigure .tf -width $geometry(topwidth)
2286 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002287
2288 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002289 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002290
2291 # lower left, a text box over search bar, scroll bar to the right
2292 # if we know window height, then that will set the lower text height, otherwise
2293 # we set lower text height which will drive window height
2294 if {[info exists geometry(main)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002295 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002296 } else {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002297 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002298 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002299 ${NS}::frame .bleft.top
2300 ${NS}::frame .bleft.mid
2301 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002302
Pat Thoytsd93f1712009-04-17 01:24:35 +01002303 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002304 pack .bleft.top.search -side left -padx 5
2305 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002306 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002307 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002308 lappend entries $sstring
2309 trace add variable searchstring write incrsearch
2310 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002311 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002312 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002313 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002314 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002315 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002316 -command changediffdisp -variable diffelide -value {1 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002317 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002318 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Mark Hills0933b042010-01-13 20:40:19 +00002319 spinbox .bleft.mid.diffcontext -width 5 \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002320 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002321 -validate all -validatecommand "diffcontextvalidate %P" \
2322 -textvariable diffcontextstring
2323 .bleft.mid.diffcontext set $diffcontext
2324 trace add variable diffcontextstring write diffcontextchange
2325 lappend entries .bleft.mid.diffcontext
2326 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002327 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002328 -command changeignorespace -variable ignorespace
2329 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002330
2331 set worddiff [mc "Line diff"]
2332 if {[package vcompare $git_version "1.7.2"] >= 0} {
2333 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2334 [mc "Markup words"] [mc "Color words"]
2335 trace add variable worddiff write changeworddiff
2336 pack .bleft.mid.worddiff -side left -padx 5
2337 }
2338
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002339 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002340 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002341 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002342 -yscrollcommand scrolltext -wrap none \
2343 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002344 if {$have_tk85} {
2345 $ctext conf -tabstyle wordprocessor
2346 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002347 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2348 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002349 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002350 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002351 grid $ctext .bleft.bottom.sb -sticky nsew
2352 grid .bleft.bottom.sbhorizontal -sticky ew
2353 grid columnconfigure .bleft.bottom 0 -weight 1
2354 grid rowconfigure .bleft.bottom 0 -weight 1
2355 grid rowconfigure .bleft.bottom 1 -weight 0
2356 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002357 lappend bglist $ctext
2358 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002359
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002360 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002361 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002362 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2363 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002364 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002365 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2366 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2367 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2368 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2369 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2370 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2371 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2372 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2373 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2374 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2375 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2376 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2377 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2378 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2379 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2380 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002381 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002382 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002383 $ctext tag conf mresult -font textfontbold
2384 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002385 $ctext tag conf found -back $foundbgcolor
2386 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerrasd34835c2013-01-01 23:08:12 +11002387 $ctext tag conf wwrap -wrap word
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002388
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002389 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002390 if {!$use_ttk} {
2391 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
2392 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002393
2394 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002395 ${NS}::frame .bright
2396 ${NS}::frame .bright.mode
2397 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002398 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002399 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002400 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002401 grid .bright.mode.patch .bright.mode.tree -sticky ew
2402 pack .bright.mode -side top -fill x
2403 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002404 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002405 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002406 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002407 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002408 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002409 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002410 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002411 -cursor [. cget -cursor] \
2412 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002413 lappend bglist $cflist
2414 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002415 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002416 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002417 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002418 $cflist tag configure highlight \
2419 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002420 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002421
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002422 .pwbottom add .bright
2423 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002424
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002425 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002426 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002427 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2428 if {$w > [winfo screenwidth .]} {
2429 set w [winfo screenwidth .]
2430 }
2431 if {$h > [winfo screenheight .]} {
2432 set h [winfo screenheight .]
2433 }
2434 wm geometry . "${w}x$h"
2435 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002436 }
2437
Pat Thoytsc876dba2009-04-14 22:09:53 +01002438 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2439 wm state . $geometry(state)
2440 }
2441
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002442 if {[tk windowingsystem] eq {aqua}} {
2443 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002444 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002445 } else {
2446 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002447 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002448 }
2449
Pat Thoytsd93f1712009-04-17 01:24:35 +01002450 if {$use_ttk} {
2451 bind .ctop <Map> {
2452 bind %W <Map> {}
2453 %W sashpos 0 $::geometry(topheight)
2454 }
2455 bind .pwbottom <Map> {
2456 bind %W <Map> {}
2457 %W sashpos 0 $::geometry(botwidth)
2458 }
2459 }
2460
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002461 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2462 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002463 bindall <1> {selcanvline %W %x %y}
2464 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002465 if {[tk windowingsystem] == "win32"} {
2466 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2467 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2468 } else {
2469 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2470 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002471 if {[tk windowingsystem] eq "aqua"} {
2472 bindall <MouseWheel> {
2473 set delta [expr {- (%D)}]
2474 allcanvs yview scroll $delta units
2475 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002476 bindall <Shift-MouseWheel> {
2477 set delta [expr {- (%D)}]
2478 $canv xview scroll $delta units
2479 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002480 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002481 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002482 bindall <$::BM> "canvscan mark %W %x %y"
2483 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002484 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2485 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002486 bindkey <Home> selfirstline
2487 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002488 bind . <Key-Up> "selnextline -1"
2489 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002490 bind . <Shift-Key-Up> "dofind -1 0"
2491 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002492 bindkey <Key-Right> "goforw"
2493 bindkey <Key-Left> "goback"
2494 bind . <Key-Prior> "selnextpage -1"
2495 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002496 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2497 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2498 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2499 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2500 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2501 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002502 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2503 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2504 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002505 bindkey p "selnextline -1"
2506 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002507 bindkey z "goback"
2508 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002509 bindkey k "selnextline -1"
2510 bindkey j "selnextline 1"
2511 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002512 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002513 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002514 bindkey d "$ctext yview scroll 18 units"
2515 bindkey u "$ctext yview scroll -18 units"
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002516 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002517 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002518 bindkey <Key-Return> {dofind 1 1}
2519 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002520 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002521 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002522 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002523 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002524 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002525 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002526 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002527 bind . <$M1B-f> {dofind 1 1}
2528 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002529 bind . <$M1B-r> dosearchback
2530 bind . <$M1B-s> dosearch
2531 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002532 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002533 bind . <$M1B-KP_Add> {incrfont 1}
2534 bind . <$M1B-minus> {incrfont -1}
2535 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002536 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002537 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002538 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002539 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002540 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002541 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002542 bind $cflist <1> {sel_flist %W %x %y; break}
2543 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002544 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002545 global ctxbut
2546 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002547 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002548 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002549 bind $ctext <<Selection>> rehighlight_search_results
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002550
2551 set maincursor [. cget -cursor]
2552 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002553 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002554
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002555 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002556 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002557 {mc "Diff this -> selected" command {diffvssel 0}}
2558 {mc "Diff selected -> this" command {diffvssel 1}}
2559 {mc "Make patch" command mkpatch}
2560 {mc "Create tag" command mktag}
2561 {mc "Write commit to file" command writecommit}
2562 {mc "Create new branch" command mkbranch}
2563 {mc "Cherry-pick this commit" command cherrypick}
2564 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002565 {mc "Mark this commit" command markhere}
2566 {mc "Return to mark" command gotomark}
2567 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002568 {mc "Compare with marked commit" command compare_commits}
Paul Mackerras6febded2012-03-23 22:07:27 +11002569 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2570 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Knut Franke8f3ff932013-04-27 16:36:13 +02002571 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002572 }
2573 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002574
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002575 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002576 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002577 {mc "Diff this -> selected" command {diffvssel 0}}
2578 {mc "Diff selected -> this" command {diffvssel 1}}
2579 {mc "Make patch" command mkpatch}
Paul Mackerras6febded2012-03-23 22:07:27 +11002580 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2581 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002582 }
2583 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002584
Paul Mackerras10299152006-08-02 09:52:01 +10002585 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002586 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002587 {mc "Check out this branch" command cobranch}
2588 {mc "Remove this branch" command rmbranch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002589 }
2590 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002591
2592 global flist_menu
2593 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002594 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002595 {mc "Highlight this too" command {flist_hl 0}}
2596 {mc "Highlight this only" command {flist_hl 1}}
2597 {mc "External diff" command {external_diff}}
2598 {mc "Blame parent commit" command {external_blame 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002599 }
2600 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002601
2602 global diff_menu
2603 set diff_menu .diffctxmenu
2604 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002605 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002606 {mc "Run git gui blame on this line" command {external_blame_diff}}
2607 }
2608 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002609}
2610
Mark Levedahl314c3092007-08-07 21:40:35 -04002611# Windows sends all mouse wheel events to the current focused window, not
2612# the one where the mouse hovers, so bind those events here and redirect
2613# to the correct window
2614proc windows_mousewheel_redirector {W X Y D} {
2615 global canv canv2 canv3
2616 set w [winfo containing -displayof $W $X $Y]
2617 if {$w ne ""} {
2618 set u [expr {$D < 0 ? 5 : -5}]
2619 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2620 allcanvs yview scroll $u units
2621 } else {
2622 catch {
2623 $w yview scroll $u units
2624 }
2625 }
2626 }
2627}
2628
Paul Mackerras6df74032008-05-11 22:13:02 +10002629# Update row number label when selectedline changes
2630proc selectedline_change {n1 n2 op} {
2631 global selectedline rownumsel
2632
Paul Mackerras94b4a692008-05-20 20:51:06 +10002633 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002634 set rownumsel {}
2635 } else {
2636 set rownumsel [expr {$selectedline + 1}]
2637 }
2638}
2639
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002640# mouse-2 makes all windows scan vertically, but only the one
2641# the cursor is in scans horizontally
2642proc canvscan {op w x y} {
2643 global canv canv2 canv3
2644 foreach c [list $canv $canv2 $canv3] {
2645 if {$c == $w} {
2646 $c scan $op $x $y
2647 } else {
2648 $c scan $op 0 $y
2649 }
2650 }
2651}
2652
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002653proc scrollcanv {cscroll f0 f1} {
2654 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002655 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002656 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002657}
2658
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002659# when we make a key binding for the toplevel, make sure
2660# it doesn't get triggered when that key is pressed in the
2661# find string entry widget.
2662proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002663 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002664 bind . $ev $script
2665 set escript [bind Entry $ev]
2666 if {$escript == {}} {
2667 set escript [bind Entry <Key>]
2668 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002669 foreach e $entries {
2670 bind $e $ev "$escript; break"
2671 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002672}
2673
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002674proc bindmodfunctionkey {mod n script} {
2675 bind . <$mod-F$n> $script
2676 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2677}
2678
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002679# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002680# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002681proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002682 global ctext entries
2683 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002684 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002685 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002686 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002687}
2688
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002689# Adjust the progress bar for a change in requested extent or canvas size
2690proc adjustprogress {} {
2691 global progresscanv progressitem progresscoords
2692 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002693 global rprogitem rprogcoord use_ttk
2694
2695 if {$use_ttk} {
2696 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2697 return
2698 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002699
2700 set w [expr {[winfo width $progresscanv] - 4}]
2701 set x0 [expr {$w * [lindex $progresscoords 0]}]
2702 set x1 [expr {$w * [lindex $progresscoords 1]}]
2703 set h [winfo height $progresscanv]
2704 $progresscanv coords $progressitem $x0 0 $x1 $h
2705 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002706 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002707 set now [clock clicks -milliseconds]
2708 if {$now >= $lastprogupdate + 100} {
2709 set progupdatepending 0
2710 update
2711 } elseif {!$progupdatepending} {
2712 set progupdatepending 1
2713 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2714 }
2715}
2716
2717proc doprogupdate {} {
2718 global lastprogupdate progupdatepending
2719
2720 if {$progupdatepending} {
2721 set progupdatepending 0
2722 set lastprogupdate [clock clicks -milliseconds]
2723 update
2724 }
2725}
2726
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002727proc savestuff {w} {
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002728 global canv canv2 canv3 mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11002729 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002730 global maxwidth showneartags showlocalchanges
Yann Dirson2d480852008-02-21 21:23:31 +01002731 global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
Paul Mackerras7a39a172007-10-23 10:15:11 +10002732 global cmitmode wrapcomment datetimeformat limitdiffs
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +02002733 global colors uicolor bgcolor fgcolor diffcolors diffcontext selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002734 global uifgcolor uifgdisabledcolor
2735 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
2736 global tagbgcolor tagfgcolor tagoutlinecolor
2737 global reflinecolor filesepbgcolor filesepfgcolor
2738 global mergecolors foundbgcolor currentsearchhitbgcolor
2739 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor circlecolors
2740 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
2741 global linkfgcolor circleoutlinecolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +11002742 global autoselect autosellen extdifftool perfile_attrs markbgcolor use_ttk
Paul Mackerrasd34835c2013-01-01 23:08:12 +11002743 global hideremotes want_ttk maxrefs
Paul Mackerras4ef17532005-07-27 22:16:51 -05002744
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002745 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002746 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002747 catch {
Pat Thoyts9bedb0e2009-09-15 10:26:30 +01002748 if {[file exists ~/.gitk-new]} {file delete -force ~/.gitk-new}
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002749 set f [open "~/.gitk-new" w]
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002750 if {$::tcl_platform(platform) eq {windows}} {
2751 file attributes "~/.gitk-new" -hidden true
2752 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04002753 puts $f [list set mainfont $mainfont]
2754 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07002755 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04002756 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002757 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10002758 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10002759 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002760 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002761 puts $f [list set wrapcomment $wrapcomment]
Jeff King95293b52008-03-06 06:49:25 -05002762 puts $f [list set autoselect $autoselect]
Paul Mackerras21ac8a82011-03-09 20:52:38 +11002763 puts $f [list set autosellen $autosellen]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10002764 puts $f [list set showneartags $showneartags]
Paul Mackerrasd34835c2013-01-01 23:08:12 +11002765 puts $f [list set maxrefs $maxrefs]
Thomas Rastffe15292009-08-03 23:53:36 +02002766 puts $f [list set hideremotes $hideremotes]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002767 puts $f [list set showlocalchanges $showlocalchanges]
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02002768 puts $f [list set datetimeformat $datetimeformat]
Paul Mackerras7a39a172007-10-23 10:15:11 +10002769 puts $f [list set limitdiffs $limitdiffs]
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +02002770 puts $f [list set uicolor $uicolor]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +10002771 puts $f [list set want_ttk $want_ttk]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002772 puts $f [list set bgcolor $bgcolor]
2773 puts $f [list set fgcolor $fgcolor]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002774 puts $f [list set uifgcolor $uifgcolor]
2775 puts $f [list set uifgdisabledcolor $uifgdisabledcolor]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002776 puts $f [list set colors $colors]
2777 puts $f [list set diffcolors $diffcolors]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002778 puts $f [list set mergecolors $mergecolors]
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002779 puts $f [list set markbgcolor $markbgcolor]
Steffen Prohaska890fae72007-08-12 12:05:46 +02002780 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04002781 puts $f [list set selectbgcolor $selectbgcolor]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002782 puts $f [list set foundbgcolor $foundbgcolor]
2783 puts $f [list set currentsearchhitbgcolor $currentsearchhitbgcolor]
Thomas Arcila314f5de2008-03-24 12:55:36 +01002784 puts $f [list set extdifftool $extdifftool]
Paul Mackerras39ee47e2008-10-15 22:23:03 +11002785 puts $f [list set perfile_attrs $perfile_attrs]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002786 puts $f [list set headbgcolor $headbgcolor]
2787 puts $f [list set headfgcolor $headfgcolor]
2788 puts $f [list set headoutlinecolor $headoutlinecolor]
2789 puts $f [list set remotebgcolor $remotebgcolor]
2790 puts $f [list set tagbgcolor $tagbgcolor]
2791 puts $f [list set tagfgcolor $tagfgcolor]
2792 puts $f [list set tagoutlinecolor $tagoutlinecolor]
2793 puts $f [list set reflinecolor $reflinecolor]
2794 puts $f [list set filesepbgcolor $filesepbgcolor]
2795 puts $f [list set filesepfgcolor $filesepfgcolor]
2796 puts $f [list set linehoverbgcolor $linehoverbgcolor]
2797 puts $f [list set linehoverfgcolor $linehoverfgcolor]
2798 puts $f [list set linehoveroutlinecolor $linehoveroutlinecolor]
2799 puts $f [list set mainheadcirclecolor $mainheadcirclecolor]
2800 puts $f [list set workingfilescirclecolor $workingfilescirclecolor]
2801 puts $f [list set indexcirclecolor $indexcirclecolor]
2802 puts $f [list set circlecolors $circlecolors]
2803 puts $f [list set linkfgcolor $linkfgcolor]
2804 puts $f [list set circleoutlinecolor $circleoutlinecolor]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002805
Mark Levedahlb6047c52007-02-08 22:22:24 -05002806 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002807 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002808 puts $f "set geometry(topwidth) [winfo width .tf]"
2809 puts $f "set geometry(topheight) [winfo height .tf]"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002810 if {$use_ttk} {
2811 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2812 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2813 } else {
2814 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2815 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2816 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002817 puts $f "set geometry(botwidth) [winfo width .bleft]"
2818 puts $f "set geometry(botheight) [winfo height .bleft]"
2819
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002820 puts -nonewline $f "set permviews {"
2821 for {set v 0} {$v < $nextviewnum} {incr v} {
2822 if {$viewperm($v)} {
Yann Dirson2d480852008-02-21 21:23:31 +01002823 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002824 }
2825 }
2826 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002827 close $f
2828 file rename -force "~/.gitk-new" "~/.gitk"
2829 }
2830 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002831}
2832
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002833proc resizeclistpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002834 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002835 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002836 if {$use_ttk} {
2837 set s0 [$win sashpos 0]
2838 set s1 [$win sashpos 1]
2839 } else {
2840 set s0 [$win sash coord 0]
2841 set s1 [$win sash coord 1]
2842 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002843 if {$w < 60} {
2844 set sash0 [expr {int($w/2 - 2)}]
2845 set sash1 [expr {int($w*5/6 - 2)}]
2846 } else {
2847 set factor [expr {1.0 * $w / $oldwidth($win)}]
2848 set sash0 [expr {int($factor * [lindex $s0 0])}]
2849 set sash1 [expr {int($factor * [lindex $s1 0])}]
2850 if {$sash0 < 30} {
2851 set sash0 30
2852 }
2853 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002854 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002855 }
2856 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002857 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002858 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002859 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002860 }
2861 }
2862 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002863 if {$use_ttk} {
2864 $win sashpos 0 $sash0
2865 $win sashpos 1 $sash1
2866 } else {
2867 $win sash place 0 $sash0 [lindex $s0 1]
2868 $win sash place 1 $sash1 [lindex $s1 1]
2869 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002870 }
2871 set oldwidth($win) $w
2872}
2873
2874proc resizecdetpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002875 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002876 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002877 if {$use_ttk} {
2878 set s0 [$win sashpos 0]
2879 } else {
2880 set s0 [$win sash coord 0]
2881 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002882 if {$w < 60} {
2883 set sash0 [expr {int($w*3/4 - 2)}]
2884 } else {
2885 set factor [expr {1.0 * $w / $oldwidth($win)}]
2886 set sash0 [expr {int($factor * [lindex $s0 0])}]
2887 if {$sash0 < 45} {
2888 set sash0 45
2889 }
2890 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002891 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002892 }
2893 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002894 if {$use_ttk} {
2895 $win sashpos 0 $sash0
2896 } else {
2897 $win sash place 0 $sash0 [lindex $s0 1]
2898 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002899 }
2900 set oldwidth($win) $w
2901}
2902
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002903proc allcanvs args {
2904 global canv canv2 canv3
2905 eval $canv $args
2906 eval $canv2 $args
2907 eval $canv3 $args
2908}
2909
2910proc bindall {event action} {
2911 global canv canv2 canv3
2912 bind $canv $event $action
2913 bind $canv2 $event $action
2914 bind $canv3 $event $action
2915}
2916
Paul Mackerras9a40c502005-05-12 23:46:16 +00002917proc about {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002918 global uifont NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00002919 set w .about
2920 if {[winfo exists $w]} {
2921 raise $w
2922 return
2923 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002924 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002925 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002926 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01002927 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002928Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00002929
Paul Mackerrasbb3e86a2011-07-24 15:34:48 +10002930Copyright \u00a9 2005-2011 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00002931
Christian Stimmingd990ced2007-11-07 18:42:55 +01002932Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002933 -justify center -aspect 400 -border 2 -bg white -relief groove
2934 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01002935 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00002936 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002937 bind $w <Visibility> "focus $w.ok"
2938 bind $w <Key-Escape> "destroy $w"
2939 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002940 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00002941}
2942
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002943proc keys {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002944 global NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002945 set w .keys
2946 if {[winfo exists $w]} {
2947 raise $w
2948 return
2949 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002950 if {[tk windowingsystem] eq {aqua}} {
2951 set M1T Cmd
2952 } else {
2953 set M1T Ctrl
2954 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002955 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002956 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002957 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002958 message $w.m -text "
2959[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002960
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002961[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002962[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002963[mc "<Home> Move to first commit"]
2964[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002965[mc "<Up>, p, k Move up one commit"]
2966[mc "<Down>, n, j Move down one commit"]
2967[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002968[mc "<Right>, x, l Go forward in history list"]
2969[mc "<PageUp> Move up one page in commit list"]
2970[mc "<PageDown> Move down one page in commit list"]
2971[mc "<%s-Home> Scroll to top of commit list" $M1T]
2972[mc "<%s-End> Scroll to bottom of commit list" $M1T]
2973[mc "<%s-Up> Scroll commit list up one line" $M1T]
2974[mc "<%s-Down> Scroll commit list down one line" $M1T]
2975[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
2976[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
2977[mc "<Shift-Up> Find backwards (upwards, later commits)"]
2978[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
2979[mc "<Delete>, b Scroll diff view up one page"]
2980[mc "<Backspace> Scroll diff view up one page"]
2981[mc "<Space> Scroll diff view down one page"]
2982[mc "u Scroll diff view up 18 lines"]
2983[mc "d Scroll diff view down 18 lines"]
2984[mc "<%s-F> Find" $M1T]
2985[mc "<%s-G> Move to next find hit" $M1T]
2986[mc "<Return> Move to next find hit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002987[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002988[mc "? Move to previous find hit"]
2989[mc "f Scroll diff view to next file"]
2990[mc "<%s-S> Search for next hit in diff view" $M1T]
2991[mc "<%s-R> Search for previous hit in diff view" $M1T]
2992[mc "<%s-KP+> Increase font size" $M1T]
2993[mc "<%s-plus> Increase font size" $M1T]
2994[mc "<%s-KP-> Decrease font size" $M1T]
2995[mc "<%s-minus> Decrease font size" $M1T]
2996[mc "<F5> Update"]
2997" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002998 -justify left -bg white -border 2 -relief groove
2999 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003000 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003001 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003002 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003003 bind $w <Visibility> "focus $w.ok"
3004 bind $w <Key-Escape> "destroy $w"
3005 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003006}
3007
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003008# Procedures for manipulating the file list window at the
3009# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003010
3011proc treeview {w l openlevs} {
3012 global treecontents treediropen treeheight treeparent treeindex
3013
3014 set ix 0
3015 set treeindex() 0
3016 set lev 0
3017 set prefix {}
3018 set prefixend -1
3019 set prefendstack {}
3020 set htstack {}
3021 set ht 0
3022 set treecontents() {}
3023 $w conf -state normal
3024 foreach f $l {
3025 while {[string range $f 0 $prefixend] ne $prefix} {
3026 if {$lev <= $openlevs} {
3027 $w mark set e:$treeindex($prefix) "end -1c"
3028 $w mark gravity e:$treeindex($prefix) left
3029 }
3030 set treeheight($prefix) $ht
3031 incr ht [lindex $htstack end]
3032 set htstack [lreplace $htstack end end]
3033 set prefixend [lindex $prefendstack end]
3034 set prefendstack [lreplace $prefendstack end end]
3035 set prefix [string range $prefix 0 $prefixend]
3036 incr lev -1
3037 }
3038 set tail [string range $f [expr {$prefixend+1}] end]
3039 while {[set slash [string first "/" $tail]] >= 0} {
3040 lappend htstack $ht
3041 set ht 0
3042 lappend prefendstack $prefixend
3043 incr prefixend [expr {$slash + 1}]
3044 set d [string range $tail 0 $slash]
3045 lappend treecontents($prefix) $d
3046 set oldprefix $prefix
3047 append prefix $d
3048 set treecontents($prefix) {}
3049 set treeindex($prefix) [incr ix]
3050 set treeparent($prefix) $oldprefix
3051 set tail [string range $tail [expr {$slash+1}] end]
3052 if {$lev <= $openlevs} {
3053 set ht 1
3054 set treediropen($prefix) [expr {$lev < $openlevs}]
3055 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3056 $w mark set d:$ix "end -1c"
3057 $w mark gravity d:$ix left
3058 set str "\n"
3059 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3060 $w insert end $str
3061 $w image create end -align center -image $bm -padx 1 \
3062 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10003063 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003064 $w mark set s:$ix "end -1c"
3065 $w mark gravity s:$ix left
3066 }
3067 incr lev
3068 }
3069 if {$tail ne {}} {
3070 if {$lev <= $openlevs} {
3071 incr ht
3072 set str "\n"
3073 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3074 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003075 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003076 }
3077 lappend treecontents($prefix) $tail
3078 }
3079 }
3080 while {$htstack ne {}} {
3081 set treeheight($prefix) $ht
3082 incr ht [lindex $htstack end]
3083 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05003084 set prefixend [lindex $prefendstack end]
3085 set prefendstack [lreplace $prefendstack end end]
3086 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003087 }
3088 $w conf -state disabled
3089}
3090
3091proc linetoelt {l} {
3092 global treeheight treecontents
3093
3094 set y 2
3095 set prefix {}
3096 while {1} {
3097 foreach e $treecontents($prefix) {
3098 if {$y == $l} {
3099 return "$prefix$e"
3100 }
3101 set n 1
3102 if {[string index $e end] eq "/"} {
3103 set n $treeheight($prefix$e)
3104 if {$y + $n > $l} {
3105 append prefix $e
3106 incr y
3107 break
3108 }
3109 }
3110 incr y $n
3111 }
3112 }
3113}
3114
Paul Mackerras45a9d502006-05-20 22:56:27 +10003115proc highlight_tree {y prefix} {
3116 global treeheight treecontents cflist
3117
3118 foreach e $treecontents($prefix) {
3119 set path $prefix$e
3120 if {[highlight_tag $path] ne {}} {
3121 $cflist tag add bold $y.0 "$y.0 lineend"
3122 }
3123 incr y
3124 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3125 set y [highlight_tree $y $path]
3126 }
3127 }
3128 return $y
3129}
3130
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003131proc treeclosedir {w dir} {
3132 global treediropen treeheight treeparent treeindex
3133
3134 set ix $treeindex($dir)
3135 $w conf -state normal
3136 $w delete s:$ix e:$ix
3137 set treediropen($dir) 0
3138 $w image configure a:$ix -image tri-rt
3139 $w conf -state disabled
3140 set n [expr {1 - $treeheight($dir)}]
3141 while {$dir ne {}} {
3142 incr treeheight($dir) $n
3143 set dir $treeparent($dir)
3144 }
3145}
3146
3147proc treeopendir {w dir} {
3148 global treediropen treeheight treeparent treecontents treeindex
3149
3150 set ix $treeindex($dir)
3151 $w conf -state normal
3152 $w image configure a:$ix -image tri-dn
3153 $w mark set e:$ix s:$ix
3154 $w mark gravity e:$ix right
3155 set lev 0
3156 set str "\n"
3157 set n [llength $treecontents($dir)]
3158 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
3159 incr lev
3160 append str "\t"
3161 incr treeheight($x) $n
3162 }
3163 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003164 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003165 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003166 set iy $treeindex($de)
3167 $w mark set d:$iy e:$ix
3168 $w mark gravity d:$iy left
3169 $w insert e:$ix $str
3170 set treediropen($de) 0
3171 $w image create e:$ix -align center -image tri-rt -padx 1 \
3172 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10003173 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003174 $w mark set s:$iy e:$ix
3175 $w mark gravity s:$iy left
3176 set treeheight($de) 1
3177 } else {
3178 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003179 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003180 }
3181 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003182 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003183 $w conf -state disabled
3184 set treediropen($dir) 1
3185 set top [lindex [split [$w index @0,0] .] 0]
3186 set ht [$w cget -height]
3187 set l [lindex [split [$w index s:$ix] .] 0]
3188 if {$l < $top} {
3189 $w yview $l.0
3190 } elseif {$l + $n + 1 > $top + $ht} {
3191 set top [expr {$l + $n + 2 - $ht}]
3192 if {$l < $top} {
3193 set top $l
3194 }
3195 $w yview $top.0
3196 }
3197}
3198
3199proc treeclick {w x y} {
3200 global treediropen cmitmode ctext cflist cflist_top
3201
3202 if {$cmitmode ne "tree"} return
3203 if {![info exists cflist_top]} return
3204 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3205 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3206 $cflist tag add highlight $l.0 "$l.0 lineend"
3207 set cflist_top $l
3208 if {$l == 1} {
3209 $ctext yview 1.0
3210 return
3211 }
3212 set e [linetoelt $l]
3213 if {[string index $e end] ne "/"} {
3214 showfile $e
3215 } elseif {$treediropen($e)} {
3216 treeclosedir $w $e
3217 } else {
3218 treeopendir $w $e
3219 }
3220}
3221
3222proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003223 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003224
3225 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003226 if {$jump_to_here ne {}} {
3227 set f [lindex $jump_to_here 0]
3228 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3229 showfile $f
3230 }
3231 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003232}
3233
3234image create bitmap tri-rt -background black -foreground blue -data {
3235 #define tri-rt_width 13
3236 #define tri-rt_height 13
3237 static unsigned char tri-rt_bits[] = {
3238 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3239 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3240 0x00, 0x00};
3241} -maskdata {
3242 #define tri-rt-mask_width 13
3243 #define tri-rt-mask_height 13
3244 static unsigned char tri-rt-mask_bits[] = {
3245 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3246 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3247 0x08, 0x00};
3248}
3249image create bitmap tri-dn -background black -foreground blue -data {
3250 #define tri-dn_width 13
3251 #define tri-dn_height 13
3252 static unsigned char tri-dn_bits[] = {
3253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3254 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3255 0x00, 0x00};
3256} -maskdata {
3257 #define tri-dn-mask_width 13
3258 #define tri-dn-mask_height 13
3259 static unsigned char tri-dn-mask_bits[] = {
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3261 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00};
3263}
3264
Paul Mackerras887c9962007-08-20 19:36:20 +10003265image create bitmap reficon-T -background black -foreground yellow -data {
3266 #define tagicon_width 13
3267 #define tagicon_height 9
3268 static unsigned char tagicon_bits[] = {
3269 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3270 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3271} -maskdata {
3272 #define tagicon-mask_width 13
3273 #define tagicon-mask_height 9
3274 static unsigned char tagicon-mask_bits[] = {
3275 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3276 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3277}
3278set rectdata {
3279 #define headicon_width 13
3280 #define headicon_height 9
3281 static unsigned char headicon_bits[] = {
3282 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3283 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3284}
3285set rectmask {
3286 #define headicon-mask_width 13
3287 #define headicon-mask_height 9
3288 static unsigned char headicon-mask_bits[] = {
3289 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3290 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3291}
3292image create bitmap reficon-H -background black -foreground green \
3293 -data $rectdata -maskdata $rectmask
3294image create bitmap reficon-o -background black -foreground "#ddddff" \
3295 -data $rectdata -maskdata $rectmask
3296
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003297proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003298 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003299
3300 $cflist conf -state normal
3301 $cflist delete 0.0 end
3302 if {$first ne {}} {
3303 $cflist insert end $first
3304 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003305 $cflist tag add highlight 1.0 "1.0 lineend"
3306 } else {
3307 catch {unset cflist_top}
3308 }
3309 $cflist conf -state disabled
3310 set difffilestart {}
3311}
3312
Paul Mackerras63b79192006-05-20 21:31:52 +10003313proc highlight_tag {f} {
3314 global highlight_paths
3315
3316 foreach p $highlight_paths {
3317 if {[string match $p $f]} {
3318 return "bold"
3319 }
3320 }
3321 return {}
3322}
3323
3324proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003325 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003326
Paul Mackerras45a9d502006-05-20 22:56:27 +10003327 $cflist conf -state normal
3328 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003329 set end [lindex [split [$cflist index end] .] 0]
3330 for {set l 2} {$l < $end} {incr l} {
3331 set line [$cflist get $l.0 "$l.0 lineend"]
3332 if {[highlight_tag $line] ne {}} {
3333 $cflist tag add bold $l.0 "$l.0 lineend"
3334 }
3335 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003336 } else {
3337 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003338 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003339 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003340}
3341
3342proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003343 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003344
Paul Mackerras45a9d502006-05-20 22:56:27 +10003345 $cflist conf -state normal
3346 $cflist tag remove bold 1.0 end
3347 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003348}
3349
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003350proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003351 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003352
Paul Mackerras45a9d502006-05-20 22:56:27 +10003353 $cflist conf -state normal
3354 foreach f $fl {
3355 $cflist insert end "\n"
3356 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003357 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003358 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003359}
3360
3361proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003362 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003363
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003364 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003365 if {![info exists cflist_top]} return
3366 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003367 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3368 $cflist tag add highlight $l.0 "$l.0 lineend"
3369 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003370 if {$l == 1} {
3371 $ctext yview 1.0
3372 } else {
3373 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003374 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003375 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003376}
3377
Paul Mackerras32447292007-07-27 22:30:15 +10003378proc pop_flist_menu {w X Y x y} {
3379 global ctext cflist cmitmode flist_menu flist_menu_file
3380 global treediffs diffids
3381
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003382 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003383 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3384 if {$l <= 1} return
3385 if {$cmitmode eq "tree"} {
3386 set e [linetoelt $l]
3387 if {[string index $e end] eq "/"} return
3388 } else {
3389 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3390 }
3391 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003392 set xdiffstate "normal"
3393 if {$cmitmode eq "tree"} {
3394 set xdiffstate "disabled"
3395 }
3396 # Disable "External diff" item in tree mode
3397 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003398 tk_popup $flist_menu $X $Y
3399}
3400
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003401proc find_ctext_fileinfo {line} {
3402 global ctext_file_names ctext_file_lines
3403
3404 set ok [bsearch $ctext_file_lines $line]
3405 set tline [lindex $ctext_file_lines $ok]
3406
3407 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3408 return {}
3409 } else {
3410 return [list [lindex $ctext_file_names $ok] $tline]
3411 }
3412}
3413
3414proc pop_diff_menu {w X Y x y} {
3415 global ctext diff_menu flist_menu_file
3416 global diff_menu_txtpos diff_menu_line
3417 global diff_menu_filebase
3418
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003419 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3420 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003421 # don't pop up the menu on hunk-separator or file-separator lines
3422 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3423 return
3424 }
3425 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003426 set f [find_ctext_fileinfo $diff_menu_line]
3427 if {$f eq {}} return
3428 set flist_menu_file [lindex $f 0]
3429 set diff_menu_filebase [lindex $f 1]
3430 tk_popup $diff_menu $X $Y
3431}
3432
Paul Mackerras32447292007-07-27 22:30:15 +10003433proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003434 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003435
3436 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003437 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003438 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003439 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003440 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003441 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003442 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003443}
3444
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003445proc gitknewtmpdir {} {
3446 global diffnum gitktmpdir gitdir
3447
3448 if {![info exists gitktmpdir]} {
Martin von Zweigbergk929f5772011-04-04 22:14:16 -04003449 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003450 if {[catch {file mkdir $gitktmpdir} err]} {
3451 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3452 unset gitktmpdir
3453 return {}
3454 }
3455 set diffnum 0
3456 }
3457 incr diffnum
3458 set diffdir [file join $gitktmpdir $diffnum]
3459 if {[catch {file mkdir $diffdir} err]} {
3460 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3461 return {}
3462 }
3463 return $diffdir
3464}
3465
Thomas Arcila314f5de2008-03-24 12:55:36 +01003466proc save_file_from_commit {filename output what} {
3467 global nullfile
3468
3469 if {[catch {exec git show $filename -- > $output} err]} {
3470 if {[string match "fatal: bad revision *" $err]} {
3471 return $nullfile
3472 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003473 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003474 return {}
3475 }
3476 return $output
3477}
3478
3479proc external_diff_get_one_file {diffid filename diffdir} {
3480 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003481 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003482
3483 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003484 set difffile [file join $worktree $filename]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003485 if {[file exists $difffile]} {
3486 return $difffile
3487 }
3488 return $nullfile
3489 }
3490 if {$diffid == $nullid2} {
3491 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3492 return [save_file_from_commit :$filename $difffile index]
3493 }
3494 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3495 return [save_file_from_commit $diffid:$filename $difffile \
3496 "revision $diffid"]
3497}
3498
3499proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003500 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003501 global flist_menu_file
3502 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003503 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003504
3505 if {[llength $diffids] == 1} {
3506 # no reference commit given
3507 set diffidto [lindex $diffids 0]
3508 if {$diffidto eq $nullid} {
3509 # diffing working copy with index
3510 set diffidfrom $nullid2
3511 } elseif {$diffidto eq $nullid2} {
3512 # diffing index with HEAD
3513 set diffidfrom "HEAD"
3514 } else {
3515 # use first parent commit
3516 global parentlist selectedline
3517 set diffidfrom [lindex $parentlist $selectedline 0]
3518 }
3519 } else {
3520 set diffidfrom [lindex $diffids 0]
3521 set diffidto [lindex $diffids 1]
3522 }
3523
3524 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003525 set diffdir [gitknewtmpdir]
3526 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003527
3528 # gather files to diff
3529 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3530 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3531
3532 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003533 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3534 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003535 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003536 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003537 } else {
3538 fconfigure $fl -blocking 0
3539 filerun $fl [list delete_at_eof $fl $diffdir]
3540 }
3541 }
3542}
3543
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003544proc find_hunk_blamespec {base line} {
3545 global ctext
3546
3547 # Find and parse the hunk header
3548 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3549 if {$s_lix eq {}} return
3550
3551 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3552 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3553 s_line old_specs osz osz1 new_line nsz]} {
3554 return
3555 }
3556
3557 # base lines for the parents
3558 set base_lines [list $new_line]
3559 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3560 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3561 old_spec old_line osz]} {
3562 return
3563 }
3564 lappend base_lines $old_line
3565 }
3566
3567 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003568 set max_parent [expr {[llength $base_lines]-2}]
3569 set dline 0
3570 set s_lno [lindex [split $s_lix "."] 0]
3571
Paul Mackerras190ec522008-10-27 21:13:37 +11003572 # Determine if the line is removed
3573 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3574 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003575 set removed_idx [string first "-" $chunk]
3576 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003577 if {$removed_idx >= 0} {
3578 set parent $removed_idx
3579 } else {
3580 set unchanged_idx [string first " " $chunk]
3581 if {$unchanged_idx >= 0} {
3582 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003583 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003584 # blame the current commit
3585 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003586 }
3587 }
3588 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003589 for {set i $line} {[incr i -1] > $s_lno} {} {
3590 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3591 # Determine if the line is removed
3592 set removed_idx [string first "-" $chunk]
3593 if {$parent >= 0} {
3594 set code [string index $chunk $parent]
3595 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3596 incr dline
3597 }
3598 } else {
3599 if {$removed_idx < 0} {
3600 incr dline
3601 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003602 }
3603 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003604 incr parent
3605 } else {
3606 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003607 }
3608
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003609 incr dline [lindex $base_lines $parent]
3610 return [list $parent $dline]
3611}
3612
3613proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003614 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003615 global diff_menu_txtpos diff_menu_line
3616 global diff_menu_filebase flist_menu_file
3617
3618 if {$cmitmode eq "tree"} {
3619 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003620 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003621 } else {
3622 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3623 if {$hinfo ne {}} {
3624 set parent_idx [lindex $hinfo 0]
3625 set line [lindex $hinfo 1]
3626 } else {
3627 set parent_idx 0
3628 set line 0
3629 }
3630 }
3631
3632 external_blame $parent_idx $line
3633}
3634
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003635# Find the SHA1 ID of the blob for file $fname in the index
3636# at stage 0 or 2
3637proc index_sha1 {fname} {
3638 set f [open [list | git ls-files -s $fname] r]
3639 while {[gets $f line] >= 0} {
3640 set info [lindex [split $line "\t"] 0]
3641 set stage [lindex $info 2]
3642 if {$stage eq "0" || $stage eq "2"} {
3643 close $f
3644 return [lindex $info 1]
3645 }
3646 }
3647 close $f
3648 return {}
3649}
3650
Paul Mackerras9712b812008-12-06 21:44:05 +11003651# Turn an absolute path into one relative to the current directory
3652proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003653 if {[file pathtype $f] eq "relative"} {
3654 return $f
3655 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003656 set elts [file split $f]
3657 set here [file split [pwd]]
3658 set ei 0
3659 set hi 0
3660 set res {}
3661 foreach d $here {
3662 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3663 lappend res ".."
3664 } else {
3665 incr ei
3666 }
3667 incr hi
3668 }
3669 set elts [concat $res [lrange $elts $ei end]]
3670 return [eval file join $elts]
3671}
3672
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003673proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003674 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003675 global nullid nullid2
3676 global parentlist selectedline currentid
3677
3678 if {$parent_idx > 0} {
3679 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3680 } else {
3681 set base_commit $currentid
3682 }
3683
3684 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3685 error_popup [mc "No such commit"]
3686 return
3687 }
3688
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003689 set cmdline [list git gui blame]
3690 if {$line ne {} && $line > 1} {
3691 lappend cmdline "--line=$line"
3692 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003693 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003694 # Unfortunately it seems git gui blame doesn't like
3695 # being given an absolute path...
3696 set f [make_relative $f]
3697 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003698 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003699 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003700 }
3701}
3702
Paul Mackerras8a897742008-10-27 21:36:25 +11003703proc show_line_source {} {
3704 global cmitmode currentid parents curview blamestuff blameinst
3705 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003706 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003707
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003708 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003709 if {$cmitmode eq "tree"} {
3710 set id $currentid
3711 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3712 } else {
3713 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3714 if {$h eq {}} return
3715 set pi [lindex $h 0]
3716 if {$pi == 0} {
3717 mark_ctext_line $diff_menu_line
3718 return
3719 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003720 incr pi -1
3721 if {$currentid eq $nullid} {
3722 if {$pi > 0} {
3723 # must be a merge in progress...
3724 if {[catch {
3725 # get the last line from .git/MERGE_HEAD
3726 set f [open [file join $gitdir MERGE_HEAD] r]
3727 set id [lindex [split [read $f] "\n"] end-1]
3728 close $f
3729 } err]} {
3730 error_popup [mc "Couldn't read merge head: %s" $err]
3731 return
3732 }
3733 } elseif {$parents($curview,$currentid) eq $nullid2} {
3734 # need to do the blame from the index
3735 if {[catch {
3736 set from_index [index_sha1 $flist_menu_file]
3737 } err]} {
3738 error_popup [mc "Error reading index: %s" $err]
3739 return
3740 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003741 } else {
3742 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003743 }
3744 } else {
3745 set id [lindex $parents($curview,$currentid) $pi]
3746 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003747 set line [lindex $h 1]
3748 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003749 set blameargs {}
3750 if {$from_index ne {}} {
3751 lappend blameargs | git cat-file blob $from_index
3752 }
3753 lappend blameargs | git blame -p -L$line,+1
3754 if {$from_index ne {}} {
3755 lappend blameargs --contents -
3756 } else {
3757 lappend blameargs $id
3758 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003759 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003760 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003761 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003762 } err]} {
3763 error_popup [mc "Couldn't start git blame: %s" $err]
3764 return
3765 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003766 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003767 fconfigure $f -blocking 0
3768 set i [reg_instance $f]
3769 set blamestuff($i) {}
3770 set blameinst $i
3771 filerun $f [list read_line_source $f $i]
3772}
3773
3774proc stopblaming {} {
3775 global blameinst
3776
3777 if {[info exists blameinst]} {
3778 stop_instance $blameinst
3779 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003780 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003781 }
3782}
3783
3784proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003785 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003786
3787 while {[gets $fd line] >= 0} {
3788 lappend blamestuff($inst) $line
3789 }
3790 if {![eof $fd]} {
3791 return 1
3792 }
3793 unset commfd($inst)
3794 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003795 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003796 fconfigure $fd -blocking 1
3797 if {[catch {close $fd} err]} {
3798 error_popup [mc "Error running git blame: %s" $err]
3799 return 0
3800 }
3801
3802 set fname {}
3803 set line [split [lindex $blamestuff($inst) 0] " "]
3804 set id [lindex $line 0]
3805 set lnum [lindex $line 1]
3806 if {[string length $id] == 40 && [string is xdigit $id] &&
3807 [string is digit -strict $lnum]} {
3808 # look for "filename" line
3809 foreach l $blamestuff($inst) {
3810 if {[string match "filename *" $l]} {
3811 set fname [string range $l 9 end]
3812 break
3813 }
3814 }
3815 }
3816 if {$fname ne {}} {
3817 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003818 if {$id eq $nullid} {
3819 # blame uses all-zeroes to mean not committed,
3820 # which would mean a change in the index
3821 set id $nullid2
3822 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003823 if {[commitinview $id $curview]} {
3824 selectline [rowofcommit $id] 1 [list $fname $lnum]
3825 } else {
3826 error_popup [mc "That line comes from commit %s, \
3827 which is not in this view" [shortids $id]]
3828 }
3829 } else {
3830 puts "oops couldn't parse git blame output"
3831 }
3832 return 0
3833}
3834
Thomas Arcila314f5de2008-03-24 12:55:36 +01003835# delete $dir when we see eof on $f (presumably because the child has exited)
3836proc delete_at_eof {f dir} {
3837 while {[gets $f line] >= 0} {}
3838 if {[eof $f]} {
3839 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003840 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003841 }
3842 file delete -force $dir
3843 return 0
3844 }
3845 return 1
3846}
3847
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003848# Functions for adding and removing shell-type quoting
3849
3850proc shellquote {str} {
3851 if {![string match "*\['\"\\ \t]*" $str]} {
3852 return $str
3853 }
3854 if {![string match "*\['\"\\]*" $str]} {
3855 return "\"$str\""
3856 }
3857 if {![string match "*'*" $str]} {
3858 return "'$str'"
3859 }
3860 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3861}
3862
3863proc shellarglist {l} {
3864 set str {}
3865 foreach a $l {
3866 if {$str ne {}} {
3867 append str " "
3868 }
3869 append str [shellquote $a]
3870 }
3871 return $str
3872}
3873
3874proc shelldequote {str} {
3875 set ret {}
3876 set used -1
3877 while {1} {
3878 incr used
3879 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3880 append ret [string range $str $used end]
3881 set used [string length $str]
3882 break
3883 }
3884 set first [lindex $first 0]
3885 set ch [string index $str $first]
3886 if {$first > $used} {
3887 append ret [string range $str $used [expr {$first - 1}]]
3888 set used $first
3889 }
3890 if {$ch eq " " || $ch eq "\t"} break
3891 incr used
3892 if {$ch eq "'"} {
3893 set first [string first "'" $str $used]
3894 if {$first < 0} {
3895 error "unmatched single-quote"
3896 }
3897 append ret [string range $str $used [expr {$first - 1}]]
3898 set used $first
3899 continue
3900 }
3901 if {$ch eq "\\"} {
3902 if {$used >= [string length $str]} {
3903 error "trailing backslash"
3904 }
3905 append ret [string index $str $used]
3906 continue
3907 }
3908 # here ch == "\""
3909 while {1} {
3910 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
3911 error "unmatched double-quote"
3912 }
3913 set first [lindex $first 0]
3914 set ch [string index $str $first]
3915 if {$first > $used} {
3916 append ret [string range $str $used [expr {$first - 1}]]
3917 set used $first
3918 }
3919 if {$ch eq "\""} break
3920 incr used
3921 append ret [string index $str $used]
3922 incr used
3923 }
3924 }
3925 return [list $used $ret]
3926}
3927
3928proc shellsplit {str} {
3929 set l {}
3930 while {1} {
3931 set str [string trimleft $str]
3932 if {$str eq {}} break
3933 set dq [shelldequote $str]
3934 set n [lindex $dq 0]
3935 set word [lindex $dq 1]
3936 set str [string range $str $n end]
3937 lappend l $word
3938 }
3939 return $l
3940}
3941
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003942# Code to implement multiple views
3943
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003944proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003945 global nextviewnum newviewname newishighlight
3946 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003947
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003948 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003949 set top .gitkview
3950 if {[winfo exists $top]} {
3951 raise $top
3952 return
3953 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06003954 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01003955 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003956 set newviewopts($nextviewnum,perm) 0
3957 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01003958 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003959}
3960
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003961set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06003962 {perm b . {} {mc "Remember this view"}}
3963 {reflabel l + {} {mc "References (space separated list):"}}
3964 {refs t15 .. {} {mc "Branches & tags:"}}
3965 {allrefs b *. "--all" {mc "All refs"}}
3966 {branches b . "--branches" {mc "All (local) branches"}}
3967 {tags b . "--tags" {mc "All tags"}}
3968 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
3969 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
3970 {author t15 .. "--author=*" {mc "Author:"}}
3971 {committer t15 . "--committer=*" {mc "Committer:"}}
3972 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
3973 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
3974 {changes_l l + {} {mc "Changes to Files:"}}
3975 {pickaxe_s r0 . {} {mc "Fixed String"}}
3976 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
3977 {pickaxe t15 .. "-S*" {mc "Search string:"}}
3978 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
3979 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
3980 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
3981 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
3982 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
3983 {skip t10 . "--skip=*" {mc "Number to skip:"}}
3984 {misc_lbl l + {} {mc "Miscellaneous options:"}}
3985 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
3986 {lright b . "--left-right" {mc "Mark branch sides"}}
3987 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02003988 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06003989 {args t50 *. {} {mc "Additional arguments to git log:"}}
3990 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
3991 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003992 }
3993
Jonathan Niedere7feb692010-03-06 16:48:38 -06003994# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003995proc encode_view_opts {n} {
3996 global known_view_options newviewopts
3997
3998 set rargs [list]
3999 foreach opt $known_view_options {
4000 set patterns [lindex $opt 3]
4001 if {$patterns eq {}} continue
4002 set pattern [lindex $patterns 0]
4003
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004004 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004005 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004006 if {$val} {
4007 lappend rargs $pattern
4008 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004009 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4010 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4011 set val $newviewopts($n,$button_id)
4012 if {$val eq $value} {
4013 lappend rargs $pattern
4014 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004015 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004016 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004017 set val [string trim $val]
4018 if {$val ne {}} {
4019 set pfix [string range $pattern 0 end-1]
4020 lappend rargs $pfix$val
4021 }
4022 }
4023 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004024 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004025 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4026}
4027
Jonathan Niedere7feb692010-03-06 16:48:38 -06004028# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004029proc decode_view_opts {n view_args} {
4030 global known_view_options newviewopts
4031
4032 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004033 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004034 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004035 # Checkboxes
4036 set val 0
4037 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
4038 # Radiobuttons
4039 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004040 set val 0
4041 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004042 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004043 set val {}
4044 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004045 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004046 }
4047 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004048 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004049 foreach arg $view_args {
4050 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4051 && ![info exists found(limit)]} {
4052 set newviewopts($n,limit) $cnt
4053 set found(limit) 1
4054 continue
4055 }
4056 catch { unset val }
4057 foreach opt $known_view_options {
4058 set id [lindex $opt 0]
4059 if {[info exists found($id)]} continue
4060 foreach pattern [lindex $opt 3] {
4061 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004062 if {[lindex $opt 1] eq "b"} {
4063 # Check buttons
4064 set val 1
4065 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4066 # Radio buttons
4067 regexp {^(.*_)} $id uselessvar id
4068 set val $num
4069 } else {
4070 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004071 set size [string length $pattern]
4072 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004073 }
4074 set newviewopts($n,$id) $val
4075 set found($id) 1
4076 break
4077 }
4078 if {[info exists val]} break
4079 }
4080 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004081 if {[regexp {^-} $arg]} {
4082 lappend oargs $arg
4083 } else {
4084 lappend refargs $arg
4085 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004086 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004087 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004088 set newviewopts($n,args) [shellarglist $oargs]
4089}
4090
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004091proc edit_or_newview {} {
4092 global curview
4093
4094 if {$curview > 0} {
4095 editview
4096 } else {
4097 newview 0
4098 }
4099}
4100
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004101proc editview {} {
4102 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004103 global viewname viewperm newviewname newviewopts
4104 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004105
4106 set top .gitkvedit-$curview
4107 if {[winfo exists $top]} {
4108 raise $top
4109 return
4110 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004111 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004112 set newviewname($curview) $viewname($curview)
4113 set newviewopts($curview,perm) $viewperm($curview)
4114 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004115 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004116}
4117
4118proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004119 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004120 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004121
Pat Thoytsd93f1712009-04-17 01:24:35 +01004122 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004123 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004124 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004125
4126 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004127 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004128 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004129 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004130 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004131 pack $top.nl -in $top.nfr -side left -padx {0 5}
4132 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004133
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004134 # View options
4135 set cframe $top.nfr
4136 set cexpand 0
4137 set cnt 0
4138 foreach opt $known_view_options {
4139 set id [lindex $opt 0]
4140 set type [lindex $opt 1]
4141 set flags [lindex $opt 2]
4142 set title [eval [lindex $opt 4]]
4143 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004144
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004145 if {$flags eq "+" || $flags eq "*"} {
4146 set cframe $top.fr$cnt
4147 incr cnt
Pat Thoytsd93f1712009-04-17 01:24:35 +01004148 ${NS}::frame $cframe
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004149 pack $cframe -in $top -fill x -pady 3 -padx 3
4150 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004151 } elseif {$flags eq ".." || $flags eq "*."} {
4152 set cframe $top.fr$cnt
4153 incr cnt
Paul Mackerraseae7d642009-09-05 17:34:03 +10004154 ${NS}::frame $cframe
Elijah Newren13d40b62009-03-23 11:57:46 -06004155 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4156 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004157 } else {
4158 set lxpad 5
4159 }
4160
Elijah Newren13d40b62009-03-23 11:57:46 -06004161 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004162 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004163 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
4164 } elseif {$type eq "b"} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004165 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004166 pack $cframe.c_$id -in $cframe -side left \
4167 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06004168 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4169 regexp {^(.*_)} $id uselessvar button_id
Paul Mackerraseae7d642009-09-05 17:34:03 +10004170 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
Elijah Newren13d40b62009-03-23 11:57:46 -06004171 pack $cframe.c_$id -in $cframe -side left \
4172 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004173 } elseif {[regexp {^t(\d+)$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004174 ${NS}::label $cframe.l_$id -text $title
4175 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004176 -textvariable newviewopts($n,$id)
4177 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4178 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4179 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004180 ${NS}::label $cframe.l_$id -text $title
4181 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004182 -textvariable newviewopts($n,$id)
4183 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4184 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06004185 } elseif {$type eq "path"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004186 ${NS}::label $top.l -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004187 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
Mark Hillsb9b142f2010-01-13 20:40:22 +00004188 text $top.t -width 40 -height 5 -background $bgcolor
Elijah Newren13d40b62009-03-23 11:57:46 -06004189 if {[info exists viewfiles($n)]} {
4190 foreach f $viewfiles($n) {
4191 $top.t insert end $f
4192 $top.t insert end "\n"
4193 }
4194 $top.t delete {end - 1c} end
4195 $top.t mark set insert 0.0
4196 }
4197 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004198 }
4199 }
4200
Pat Thoytsd93f1712009-04-17 01:24:35 +01004201 ${NS}::frame $top.buts
4202 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4203 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4204 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004205 bind $top <Control-Return> [list newviewok $top $n]
4206 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004207 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004208 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004209 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4210 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004211 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4212 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004213 focus $top.t
4214}
4215
Paul Mackerras908c3582006-05-20 09:38:11 +10004216proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004217 set nmenu [$m index end]
4218 for {set i $first} {$i <= $nmenu} {incr i} {
4219 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004220 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004221 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004222 }
4223 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004224}
4225
4226proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004227 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004228
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004229 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004230 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004231}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004232
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004233proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004234 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004235 global viewname viewfiles viewperm selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004236 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004237
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004238 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004239 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004240 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03004241 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004242 return
4243 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004244 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004245 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004246 set ft [string trim $f]
4247 if {$ft ne {}} {
4248 lappend files $ft
4249 }
4250 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004251 if {![info exists viewfiles($n)]} {
4252 # creating a new view
4253 incr nextviewnum
4254 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004255 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004256 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004257 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004258 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004259 addviewmenu $n
4260 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004261 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004262 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004263 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004264 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004265 } else {
4266 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004267 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004268 if {$newviewname($n) ne $viewname($n)} {
4269 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004270 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004271 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10004272 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4273 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004274 }
Yann Dirson2d480852008-02-21 21:23:31 +01004275 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004276 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004277 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004278 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004279 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004280 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004281 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004282 }
4283 }
4284 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004285 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004286 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004287}
4288
4289proc delview {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004290 global curview viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004291
4292 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004293 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004294 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004295 unset hlview
4296 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004297 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004298 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004299 showview 0
4300}
4301
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004302proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004303 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004304
4305 .bar.view add radiobutton -label $viewname($n) \
4306 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004307 #$viewhlmenu add radiobutton -label $viewname($n) \
4308 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004309}
4310
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004311proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004312 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004313 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004314 global colormap rowtextx nextcolor canvxmax
4315 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004316 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004317 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004318 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004319 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004320 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004321 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004322
4323 if {$n == $curview} return
4324 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004325 set ymax [lindex [$canv cget -scrollregion] 3]
4326 set span [$canv yview]
4327 set ytop [expr {[lindex $span 0] * $ymax}]
4328 set ybot [expr {[lindex $span 1] * $ymax}]
4329 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004330 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004331 set selid $currentid
4332 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004333 if {$ytop < $y && $y < $ybot} {
4334 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004335 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004336 } elseif {[info exists pending_select]} {
4337 set selid $pending_select
4338 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004339 }
4340 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004341 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004342 catch {unset treediffs}
4343 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004344 if {[info exists hlview] && $hlview == $n} {
4345 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004346 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004347 }
Paul Mackerras97645682007-08-23 22:24:38 +10004348 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004349 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004350 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004351
4352 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004353 set selectedview $n
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11004354 .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4355 .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004356
Paul Mackerrasdf904492007-08-29 22:03:07 +10004357 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004358 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004359 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004360 return
4361 }
4362
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004363 set displayorder {}
4364 set parentlist {}
4365 set rowidlist {}
4366 set rowisopt {}
4367 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004368 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004369
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004370 catch {unset colormap}
4371 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004372 set nextcolor 0
4373 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004374 set curview $n
4375 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004376 setcanvscroll
4377 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004378 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004379 if {$selid ne {} && [commitinview $selid $n]} {
4380 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004381 # try to get the selected row in the same position on the screen
4382 set ymax [lindex [$canv cget -scrollregion] 3]
4383 set ytop [expr {[yc $row] - $yscreen}]
4384 if {$ytop < 0} {
4385 set ytop 0
4386 }
4387 set yf [expr {$ytop * 1.0 / $ymax}]
4388 }
4389 allcanvs yview moveto $yf
4390 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004391 if {$row ne {}} {
4392 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004393 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004394 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004395 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004396 reset_pending_select {}
4397
4398 if {[commitinview $pending_select $curview]} {
4399 selectline [rowofcommit $pending_select] 1
4400 } else {
4401 set row [first_real_row]
4402 if {$row < $numcommits} {
4403 selectline $row 0
4404 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004405 }
4406 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004407 if {!$viewcomplete($n)} {
4408 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004409 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004410 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004411 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004412 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004413 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004414}
4415
Paul Mackerras908c3582006-05-20 09:38:11 +10004416# Stuff relating to the highlighting facility
4417
Paul Mackerras476ca632008-01-07 22:16:31 +11004418proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004419 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004420
Paul Mackerras476ca632008-01-07 22:16:31 +11004421 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4422 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004423 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004424 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4425 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004426 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004427 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4428 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004429 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004430 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4431 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004432 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004433 return 0
4434}
4435
Paul Mackerras28593d32008-11-13 23:01:46 +11004436proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004437 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004438
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004439 # need_redisplay = 1 means the display is stale and about to be redrawn
4440 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004441 lappend boldids $id
4442 $canv itemconf $linehtag($id) -font $font
4443 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004444 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004445 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004446 -outline {{}} -tags secsel \
4447 -fill [$canv cget -selectbackground]]
4448 $canv lower $t
4449 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004450 if {[info exists markedid] && $id eq $markedid} {
4451 make_idmark $id
4452 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004453}
4454
Paul Mackerras28593d32008-11-13 23:01:46 +11004455proc bolden_name {id font} {
4456 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004457
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004458 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004459 lappend boldnameids $id
4460 $canv2 itemconf $linentag($id) -font $font
4461 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004462 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004463 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004464 -outline {{}} -tags secsel \
4465 -fill [$canv2 cget -selectbackground]]
4466 $canv2 lower $t
4467 }
4468}
4469
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004470proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004471 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004472
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004473 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004474 foreach id $boldids {
4475 if {![ishighlighted $id]} {
4476 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004477 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004478 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004479 }
4480 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004481 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004482}
4483
4484proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004485 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004486
4487 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004488 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004489 }
4490 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004491 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004492 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004493 }
4494 set vhl_done $commitidx($hlview)
4495 if {$vhl_done > 0} {
4496 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004497 }
4498}
4499
Paul Mackerras908c3582006-05-20 09:38:11 +10004500proc delvhighlight {} {
4501 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004502
4503 if {![info exists hlview]} return
4504 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004505 catch {unset vhighlights}
4506 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004507}
4508
Paul Mackerras908c3582006-05-20 09:38:11 +10004509proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004510 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004511
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004512 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004513 set vr [visiblerows]
4514 set r0 [lindex $vr 0]
4515 set r1 [lindex $vr 1]
4516 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004517 set id [commitonrow $i $hlview]
4518 if {[commitinview $id $curview]} {
4519 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004520 if {$r0 <= $row && $row <= $r1} {
4521 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004522 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004523 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004524 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004525 }
4526 }
4527 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004528 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004529 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004530}
4531
4532proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004533 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004534
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004535 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004536 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004537 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004538 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004539 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004540 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004541 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004542 }
4543}
4544
Paul Mackerras687c8762007-09-22 12:49:33 +10004545proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004546 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004547 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004548
4549 if {[info exists filehighlight]} {
4550 # delete previous highlights
4551 catch {close $filehighlight}
4552 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004553 catch {unset fhighlights}
4554 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004555 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004556 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004557 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004558 after cancel do_file_hl $fh_serial
4559 incr fh_serial
4560 if {$highlight_files ne {}} {
4561 after 300 do_file_hl $fh_serial
4562 }
4563}
4564
Paul Mackerras687c8762007-09-22 12:49:33 +10004565proc gdttype_change {name ix op} {
4566 global gdttype highlight_files findstring findpattern
4567
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004568 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004569 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004570 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004571 if {$highlight_files ne {}} {
4572 set highlight_files {}
4573 hfiles_change
4574 }
4575 findcom_change
4576 } else {
4577 if {$findpattern ne {}} {
4578 set findpattern {}
4579 findcom_change
4580 }
4581 set highlight_files $findstring
4582 hfiles_change
4583 }
4584 drawvisible
4585 }
4586 # enable/disable findtype/findloc menus too
4587}
4588
4589proc find_change {name ix op} {
4590 global gdttype findstring highlight_files
4591
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004592 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004593 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004594 findcom_change
4595 } else {
4596 if {$highlight_files ne $findstring} {
4597 set highlight_files $findstring
4598 hfiles_change
4599 }
4600 }
4601 drawvisible
4602}
4603
Paul Mackerras64b5f142007-10-04 22:19:24 +10004604proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004605 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004606 global findpattern findtype findstring gdttype
4607
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004608 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004609 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004610 foreach id $boldnameids {
4611 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004612 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004613 set boldnameids {}
Paul Mackerras687c8762007-09-22 12:49:33 +10004614 catch {unset nhighlights}
4615 unbolden
4616 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004617 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004618 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004619 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004620 set findpattern $findstring
4621 } else {
4622 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4623 $findstring]
4624 set findpattern "*$e*"
4625 }
4626}
4627
Paul Mackerras63b79192006-05-20 21:31:52 +10004628proc makepatterns {l} {
4629 set ret {}
4630 foreach e $l {
4631 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4632 if {[string index $ee end] eq "/"} {
4633 lappend ret "$ee*"
4634 } else {
4635 lappend ret $ee
4636 lappend ret "$ee/*"
4637 }
4638 }
4639 return $ret
4640}
4641
Paul Mackerras908c3582006-05-20 09:38:11 +10004642proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004643 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004644 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004645
Christian Stimmingb007ee22007-11-07 18:44:35 +01004646 if {$gdttype eq [mc "touching paths:"]} {
Yggy Kingde665fd2011-07-13 01:30:26 -07004647 # If "exact" match then convert backslashes to forward slashes.
4648 # Most useful to support Windows-flavoured file paths.
4649 if {$findtype eq [mc "Exact"]} {
4650 set highlight_files [string map {"\\" "/"} $highlight_files]
4651 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004652 if {[catch {set paths [shellsplit $highlight_files]}]} return
4653 set highlight_paths [makepatterns $paths]
4654 highlight_filelist
Martin von Zweigbergkc332f442011-04-04 22:14:12 -04004655 set relative_paths {}
4656 foreach path $paths {
4657 lappend relative_paths [file join $cdup $path]
4658 }
4659 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004660 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004661 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004662 } elseif {$gdttype eq [mc "changing lines matching:"]} {
4663 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004664 } else {
4665 # must be "containing:", i.e. we're searching commit info
4666 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004667 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004668 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004669 set filehighlight [open $cmd r+]
4670 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004671 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004672 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004673 drawvisible
4674 flushhighlights
4675}
4676
4677proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004678 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004679
4680 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004681 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004682 puts $filehighlight ""
4683 flush $filehighlight
4684 }
4685}
4686
4687proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004688 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004689
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004690 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004691 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004692 puts $filehighlight $id
4693}
4694
4695proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004696 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004697 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004698
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004699 if {![info exists filehighlight]} {
4700 return 0
4701 }
4702 set nr 0
4703 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004704 set line [string trim $line]
4705 set i [lsearch -exact $fhl_list $line]
4706 if {$i < 0} continue
4707 for {set j 0} {$j < $i} {incr j} {
4708 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004709 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004710 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004711 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4712 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004713 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004714 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004715 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004716 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004717 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004718 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004719 if {[eof $filehighlight]} {
4720 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004721 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004722 catch {close $filehighlight}
4723 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004724 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004725 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004726 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004727 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004728 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004729 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004730}
4731
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004732proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004733 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004734
Christian Stimmingb007ee22007-11-07 18:44:35 +01004735 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004736 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004737 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004738 return [string match -nocase $findpattern $f]
4739 } else {
4740 return [string match $findpattern $f]
4741 }
4742}
4743
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004744proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004745 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004746 global findloc
4747 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004748
4749 if {![info exists commitinfo($id)]} {
4750 getcommit $id
4751 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004752 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004753 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004754 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004755 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04004756 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01004757 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004758 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004759 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004760 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004761 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004762 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004763 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004764 }
4765 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004766 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004767 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004768 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004769 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004770 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004771 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004772 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004773 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004774 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004775 }
4776 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004777 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004778}
4779
Paul Mackerras005a2f42007-07-26 22:36:39 +10004780proc markrowmatches {row id} {
4781 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004782
Paul Mackerras005a2f42007-07-26 22:36:39 +10004783 set headline [lindex $commitinfo($id) 0]
4784 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004785 $canv delete match$row
4786 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004787 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004788 set m [findmatches $headline]
4789 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004790 markmatches $canv $row $headline $linehtag($id) $m \
4791 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004792 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004793 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004794 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004795 set m [findmatches $author]
4796 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004797 markmatches $canv2 $row $author $linentag($id) $m \
4798 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004799 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004800 }
4801}
4802
Paul Mackerras164ff272006-05-29 19:50:02 +10004803proc vrel_change {name ix op} {
4804 global highlight_related
4805
4806 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004807 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004808 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004809 }
4810}
4811
4812# prepare for testing whether commits are descendents or ancestors of a
4813proc rhighlight_sel {a} {
4814 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004815 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004816
4817 catch {unset descendent}
4818 set desc_todo [list $a]
4819 catch {unset ancestor}
4820 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004821 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004822 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004823 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004824 }
4825}
4826
4827proc rhighlight_none {} {
4828 global rhighlights
4829
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004830 catch {unset rhighlights}
4831 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004832}
4833
4834proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004835 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004836
4837 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004838 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004839 set todo $desc_todo
4840 set leftover {}
4841 set done 0
4842 for {set i 0} {$i < [llength $todo]} {incr i} {
4843 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004844 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004845 lappend leftover $do
4846 continue
4847 }
4848 foreach nk $children($v,$do) {
4849 if {![info exists descendent($nk)]} {
4850 set descendent($nk) 1
4851 lappend todo $nk
4852 if {$nk eq $a} {
4853 set done 1
4854 }
4855 }
4856 }
4857 if {$done} {
4858 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4859 return
4860 }
4861 }
4862 set descendent($a) 0
4863 set desc_todo $leftover
4864}
4865
4866proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004867 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004868
4869 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004870 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004871 set todo $anc_todo
4872 set leftover {}
4873 set done 0
4874 for {set i 0} {$i < [llength $todo]} {incr i} {
4875 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004876 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004877 lappend leftover $do
4878 continue
4879 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004880 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10004881 if {![info exists ancestor($np)]} {
4882 set ancestor($np) 1
4883 lappend todo $np
4884 if {$np eq $a} {
4885 set done 1
4886 }
4887 }
4888 }
4889 if {$done} {
4890 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4891 return
4892 }
4893 }
4894 set ancestor($a) 0
4895 set anc_todo $leftover
4896}
4897
4898proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004899 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004900 global selectedline ancestor
4901
Paul Mackerras94b4a692008-05-20 20:51:06 +10004902 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10004903 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01004904 if {$highlight_related eq [mc "Descendant"] ||
4905 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004906 if {![info exists descendent($id)]} {
4907 is_descendent $id
4908 }
Christian Stimming55e34432008-01-09 22:23:18 +01004909 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004910 set isbold 1
4911 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004912 } elseif {$highlight_related eq [mc "Ancestor"] ||
4913 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004914 if {![info exists ancestor($id)]} {
4915 is_ancestor $id
4916 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004917 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004918 set isbold 1
4919 }
4920 }
4921 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004922 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004923 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004924 }
4925 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004926 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004927}
4928
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004929# Graph layout functions
4930
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004931proc shortids {ids} {
4932 set res {}
4933 foreach id $ids {
4934 if {[llength $id] > 1} {
4935 lappend res [shortids $id]
4936 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
4937 lappend res [string range $id 0 7]
4938 } else {
4939 lappend res $id
4940 }
4941 }
4942 return $res
4943}
4944
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004945proc ntimes {n o} {
4946 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10004947 set o [list $o]
4948 for {set mask 1} {$mask <= $n} {incr mask $mask} {
4949 if {($n & $mask) != 0} {
4950 set ret [concat $ret $o]
4951 }
4952 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004953 }
4954 return $ret
4955}
4956
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004957proc ordertoken {id} {
4958 global ordertok curview varcid varcstart varctok curview parents children
4959 global nullid nullid2
4960
4961 if {[info exists ordertok($id)]} {
4962 return $ordertok($id)
4963 }
4964 set origid $id
4965 set todo {}
4966 while {1} {
4967 if {[info exists varcid($curview,$id)]} {
4968 set a $varcid($curview,$id)
4969 set p [lindex $varcstart($curview) $a]
4970 } else {
4971 set p [lindex $children($curview,$id) 0]
4972 }
4973 if {[info exists ordertok($p)]} {
4974 set tok $ordertok($p)
4975 break
4976 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11004977 set id [first_real_child $curview,$p]
4978 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004979 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11004980 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004981 break
4982 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004983 if {[llength $parents($curview,$id)] == 1} {
4984 lappend todo [list $p {}]
4985 } else {
4986 set j [lsearch -exact $parents($curview,$id) $p]
4987 if {$j < 0} {
4988 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
4989 }
4990 lappend todo [list $p [strrep $j]]
4991 }
4992 }
4993 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
4994 set p [lindex $todo $i 0]
4995 append tok [lindex $todo $i 1]
4996 set ordertok($p) $tok
4997 }
4998 set ordertok($origid) $tok
4999 return $tok
5000}
5001
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005002# Work out where id should go in idlist so that order-token
5003# values increase from left to right
5004proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005005 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005006 if {$i < 0} {
5007 set i 0
5008 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005009 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005010 if {$i > [llength $idlist]} {
5011 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005012 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005013 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005014 incr i
5015 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005016 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005017 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005018 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005019 }
5020 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005021 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005022}
5023
5024proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005025 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005026 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005027 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005028 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005029
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005030 set numcommits 0
5031 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005032 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005033 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005034 set rowidlist {}
5035 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005036 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005037 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005038 catch {unset colormap}
5039 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005040 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005041}
5042
5043proc setcanvscroll {} {
5044 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005045 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005046
5047 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5048 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5049 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5050 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005051 set lastscrollset [clock clicks -milliseconds]
5052 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005053}
5054
5055proc visiblerows {} {
5056 global canv numcommits linespc
5057
5058 set ymax [lindex [$canv cget -scrollregion] 3]
5059 if {$ymax eq {} || $ymax == 0} return
5060 set f [$canv yview]
5061 set y0 [expr {int([lindex $f 0] * $ymax)}]
5062 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5063 if {$r0 < 0} {
5064 set r0 0
5065 }
5066 set y1 [expr {int([lindex $f 1] * $ymax)}]
5067 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5068 if {$r1 >= $numcommits} {
5069 set r1 [expr {$numcommits - 1}]
5070 }
5071 return [list $r0 $r1]
5072}
5073
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005074proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005075 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005076 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005077 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005078
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005079 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
5080 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005081 setcanvscroll
5082 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005083 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005084 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04005085 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005086 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005087 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005088 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005089}
5090
Paul Mackerrascdc84292008-11-18 19:54:14 +11005091# With path limiting, we mightn't get the actual HEAD commit,
5092# so ask git rev-list what is the first ancestor of HEAD that
5093# touches a file in the path limit.
5094proc get_viewmainhead {view} {
5095 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005096
Paul Mackerrascdc84292008-11-18 19:54:14 +11005097 catch {
5098 set rfd [open [concat | git rev-list -1 $mainheadid \
5099 -- $vfilelimit($view)] r]
5100 set j [reg_instance $rfd]
5101 lappend viewinstances($view) $j
5102 fconfigure $rfd -blocking 0
5103 filerun $rfd [list getviewhead $rfd $j $view]
5104 set viewmainheadid($curview) {}
5105 }
5106}
5107
5108# git rev-list should give us just 1 line to use as viewmainheadid($view)
5109proc getviewhead {fd inst view} {
5110 global viewmainheadid commfd curview viewinstances showlocalchanges
5111
5112 set id {}
5113 if {[gets $fd line] < 0} {
5114 if {![eof $fd]} {
5115 return 1
5116 }
5117 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
5118 set id $line
5119 }
5120 set viewmainheadid($view) $id
5121 close $fd
5122 unset commfd($inst)
5123 set i [lsearch -exact $viewinstances($view) $inst]
5124 if {$i >= 0} {
5125 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
5126 }
5127 if {$showlocalchanges && $id ne {} && $view == $curview} {
5128 doshowlocalchanges
5129 }
5130 return 0
5131}
5132
5133proc doshowlocalchanges {} {
5134 global curview viewmainheadid
5135
5136 if {$viewmainheadid($curview) eq {}} return
5137 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005138 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005139 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005140 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005141 }
5142}
5143
5144proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005145 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005146
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005147 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005148 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005149 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005150 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005151 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005152 }
5153 incr lserial
5154}
5155
Paul Mackerras8f489362007-07-13 19:49:37 +10005156# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005157proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005158 global lserial showlocalchanges vfilelimit curview
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005159 global hasworktree
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005160
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005161 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005162 incr lserial
Paul Mackerrascdc84292008-11-18 19:54:14 +11005163 set cmd "|git diff-index --cached HEAD"
5164 if {$vfilelimit($curview) ne {}} {
5165 set cmd [concat $cmd -- $vfilelimit($curview)]
5166 }
5167 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005168 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005169 set i [reg_instance $fd]
5170 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005171}
5172
Alexander Gavrilove439e092008-07-13 16:40:47 +04005173proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005174 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5175 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005176
Paul Mackerras8f489362007-07-13 19:49:37 +10005177 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005178 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005179 if {![eof $fd]} {
5180 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005181 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005182 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005183 }
5184 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005185 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005186
Paul Mackerras24f7a662007-12-19 09:35:33 +11005187 if {$serial != $lserial} {
5188 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005189 }
5190
Paul Mackerras24f7a662007-12-19 09:35:33 +11005191 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005192 set cmd "|git diff-files"
5193 if {$vfilelimit($curview) ne {}} {
5194 set cmd [concat $cmd -- $vfilelimit($curview)]
5195 }
5196 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005197 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005198 set i [reg_instance $fd]
5199 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005200
5201 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005202 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005203 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10005204 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5205 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005206 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005207 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005208 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005209 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005210 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005211 if {[commitinview $nullid $curview]} {
5212 removefakerow $nullid
5213 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005214 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005215 }
5216 return 0
5217}
5218
Alexander Gavrilove439e092008-07-13 16:40:47 +04005219proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005220 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005221 global commitinfo commitdata lserial
5222
5223 set isdiff 1
5224 if {[gets $fd line] < 0} {
5225 if {![eof $fd]} {
5226 return 1
5227 }
5228 set isdiff 0
5229 }
5230 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005231 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005232
Paul Mackerras24f7a662007-12-19 09:35:33 +11005233 if {$serial != $lserial} {
5234 return 0
5235 }
5236
5237 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005238 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005239 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005240 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5241 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005242 if {[commitinview $nullid2 $curview]} {
5243 set p $nullid2
5244 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005245 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005246 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005247 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005248 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005249 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005250 }
5251 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005252}
5253
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005254proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005255 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005256
5257 if {[info exists children($curview,$id)]} {
5258 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005259 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005260 return -1
5261 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005262 if {[rowofcommit $kid] > $row} {
5263 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005264 }
5265 }
5266 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005267 if {[commitinview $id $curview]} {
5268 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005269 }
5270 return -1
5271}
5272
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005273proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005274 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005275
5276 set ret -1
5277 if {[info exists children($curview,$id)]} {
5278 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005279 if {![commitinview $kid $curview]} break
5280 if {[rowofcommit $kid] < $row} {
5281 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005282 }
5283 }
5284 }
5285 return $ret
5286}
5287
Paul Mackerras03800812007-08-29 21:45:21 +10005288proc make_idlist {row} {
5289 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005290 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005291
5292 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5293 if {$r < 0} {
5294 set r 0
5295 }
5296 set ra [expr {$row - $downarrowlen}]
5297 if {$ra < 0} {
5298 set ra 0
5299 }
5300 set rb [expr {$row + $uparrowlen}]
5301 if {$rb > $commitidx($curview)} {
5302 set rb $commitidx($curview)
5303 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005304 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005305 set ids {}
5306 for {} {$r < $ra} {incr r} {
5307 set nextid [lindex $displayorder [expr {$r + 1}]]
5308 foreach p [lindex $parentlist $r] {
5309 if {$p eq $nextid} continue
5310 set rn [nextuse $p $r]
5311 if {$rn >= $row &&
5312 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005313 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005314 }
5315 }
5316 }
5317 for {} {$r < $row} {incr r} {
5318 set nextid [lindex $displayorder [expr {$r + 1}]]
5319 foreach p [lindex $parentlist $r] {
5320 if {$p eq $nextid} continue
5321 set rn [nextuse $p $r]
5322 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005323 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005324 }
5325 }
5326 }
5327 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005328 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005329 while {$r < $rb} {
5330 foreach p [lindex $parentlist $r] {
5331 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005332 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005333 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005334 }
5335 }
5336 incr r
5337 set id [lindex $displayorder $r]
5338 if {$id ne {}} {
5339 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005340 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005341 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005342 }
5343 }
5344 }
5345 set idlist {}
5346 foreach idx [lsort -unique $ids] {
5347 lappend idlist [lindex $idx 1]
5348 }
5349 return $idlist
5350}
5351
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005352proc rowsequal {a b} {
5353 while {[set i [lsearch -exact $a {}]] >= 0} {
5354 set a [lreplace $a $i $i]
5355 }
5356 while {[set i [lsearch -exact $b {}]] >= 0} {
5357 set b [lreplace $b $i $i]
5358 }
5359 return [expr {$a eq $b}]
5360}
5361
5362proc makeupline {id row rend col} {
5363 global rowidlist uparrowlen downarrowlen mingaplen
5364
5365 for {set r $rend} {1} {set r $rstart} {
5366 set rstart [prevuse $id $r]
5367 if {$rstart < 0} return
5368 if {$rstart < $row} break
5369 }
5370 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5371 set rstart [expr {$rend - $uparrowlen - 1}]
5372 }
5373 for {set r $rstart} {[incr r] <= $row} {} {
5374 set idlist [lindex $rowidlist $r]
5375 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5376 set col [idcol $idlist $id $col]
5377 lset rowidlist $r [linsert $idlist $col $id]
5378 changedrow $r
5379 }
5380 }
5381}
5382
Paul Mackerras03800812007-08-29 21:45:21 +10005383proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005384 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005385 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005386 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005387 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005388
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005389 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005390 set idlist {}
5391 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005392 set rm1 [expr {$row - 1}]
5393 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005394 if {$id ne {}} {
5395 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005396 }
5397 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005398 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005399 }
Paul Mackerras03800812007-08-29 21:45:21 +10005400 for {} {$row < $endrow} {incr row} {
5401 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005402 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005403 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005404 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005405 } else {
5406 set id [lindex $displayorder $rm1]
5407 set col [lsearch -exact $idlist $id]
5408 set idlist [lreplace $idlist $col $col]
5409 foreach p [lindex $parentlist $rm1] {
5410 if {[lsearch -exact $idlist $p] < 0} {
5411 set col [idcol $idlist $p $col]
5412 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005413 # if not the first child, we have to insert a line going up
5414 if {$id ne [lindex $children($curview,$p) 0]} {
5415 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005416 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005417 }
5418 }
Paul Mackerras03800812007-08-29 21:45:21 +10005419 set id [lindex $displayorder $row]
5420 if {$row > $downarrowlen} {
5421 set termrow [expr {$row - $downarrowlen - 1}]
5422 foreach p [lindex $parentlist $termrow] {
5423 set i [lsearch -exact $idlist $p]
5424 if {$i < 0} continue
5425 set nr [nextuse $p $termrow]
5426 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5427 set idlist [lreplace $idlist $i $i]
5428 }
5429 }
5430 }
5431 set col [lsearch -exact $idlist $id]
5432 if {$col < 0} {
5433 set col [idcol $idlist $id]
5434 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005435 if {$children($curview,$id) ne {}} {
5436 makeupline $id $rm1 $row $col
5437 }
Paul Mackerras03800812007-08-29 21:45:21 +10005438 }
5439 set r [expr {$row + $uparrowlen - 1}]
5440 if {$r < $commitidx($curview)} {
5441 set x $col
5442 foreach p [lindex $parentlist $r] {
5443 if {[lsearch -exact $idlist $p] >= 0} continue
5444 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005445 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005446 set x [idcol $idlist $p $x]
5447 set idlist [linsert $idlist $x $p]
5448 }
5449 }
5450 if {[incr r] < $commitidx($curview)} {
5451 set p [lindex $displayorder $r]
5452 if {[lsearch -exact $idlist $p] < 0} {
5453 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005454 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005455 set x [idcol $idlist $p $x]
5456 set idlist [linsert $idlist $x $p]
5457 }
5458 }
5459 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005460 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005461 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005462 if {$final && !$viewcomplete($curview) &&
5463 $row + $uparrowlen + $mingaplen + $downarrowlen
5464 >= $commitidx($curview)} {
5465 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005466 }
Paul Mackerras03800812007-08-29 21:45:21 +10005467 set l [llength $rowidlist]
5468 if {$row == $l} {
5469 lappend rowidlist $idlist
5470 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005471 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005472 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005473 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005474 lset rowidlist $row $idlist
5475 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005476 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005477 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005478 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005479 set pad [ntimes [expr {$row - $l}] {}]
5480 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005481 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005482 set rowfinal [concat $rowfinal $pad]
5483 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005484 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005485 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005486 }
5487 return $row
5488}
5489
Paul Mackerras03800812007-08-29 21:45:21 +10005490proc changedrow {row} {
5491 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005492
Paul Mackerras03800812007-08-29 21:45:21 +10005493 set l [llength $rowisopt]
5494 if {$row < $l} {
5495 lset rowisopt $row 0
5496 if {$row + 1 < $l} {
5497 lset rowisopt [expr {$row + 1}] 0
5498 if {$row + 2 < $l} {
5499 lset rowisopt [expr {$row + 2}] 0
5500 }
5501 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005502 }
Paul Mackerras03800812007-08-29 21:45:21 +10005503 set id [lindex $displayorder $row]
5504 if {[info exists iddrawn($id)]} {
5505 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005506 }
5507}
5508
5509proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005510 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005511
5512 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005513 set idlist [lindex $rowidlist $row]
5514 set bef [lrange $idlist 0 [expr {$col - 1}]]
5515 set aft [lrange $idlist $col end]
5516 set i [lsearch -exact $aft {}]
5517 if {$i > 0} {
5518 set aft [lreplace $aft $i $i]
5519 }
5520 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005521 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005522}
5523
5524proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005525 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005526
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005527 if {$row < 1} {
5528 set row 1
5529 }
Paul Mackerras03800812007-08-29 21:45:21 +10005530 for {} {$row < $endrow} {incr row; set col 0} {
5531 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005532 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005533 set y0 [expr {$row - 1}]
5534 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005535 set idlist [lindex $rowidlist $row]
5536 set previdlist [lindex $rowidlist $y0]
5537 if {$idlist eq {} || $previdlist eq {}} continue
5538 if {$ym >= 0} {
5539 set pprevidlist [lindex $rowidlist $ym]
5540 if {$pprevidlist eq {}} continue
5541 } else {
5542 set pprevidlist {}
5543 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005544 set x0 -1
5545 set xm -1
5546 for {} {$col < [llength $idlist]} {incr col} {
5547 set id [lindex $idlist $col]
5548 if {[lindex $previdlist $col] eq $id} continue
5549 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005550 set haspad 1
5551 continue
5552 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005553 set x0 [lsearch -exact $previdlist $id]
5554 if {$x0 < 0} continue
5555 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005556 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005557 set z0 {}
5558 if {$ym >= 0} {
5559 set xm [lsearch -exact $pprevidlist $id]
5560 if {$xm >= 0} {
5561 set z0 [expr {$xm - $x0}]
5562 }
5563 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005564 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005565 # if row y0 is the first child of $id then it's not an arrow
5566 if {[lindex $children($curview,$id) 0] ne
5567 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005568 set isarrow 1
5569 }
5570 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005571 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5572 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5573 set isarrow 1
5574 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005575 # Looking at lines from this row to the previous row,
5576 # make them go straight up if they end in an arrow on
5577 # the previous row; otherwise make them go straight up
5578 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005579 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005580 # Line currently goes left too much;
5581 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005582 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005583 insert_pad $y0 $x0 $npad
5584 if {$y0 > 0} {
5585 optimize_rows $y0 $x0 $row
5586 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005587 set previdlist [lindex $rowidlist $y0]
5588 set x0 [lsearch -exact $previdlist $id]
5589 set z [expr {$x0 - $col}]
5590 if {$z0 ne {}} {
5591 set pprevidlist [lindex $rowidlist $ym]
5592 set xm [lsearch -exact $pprevidlist $id]
5593 set z0 [expr {$xm - $x0}]
5594 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005595 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005596 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005597 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005598 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005599 insert_pad $row $col $npad
5600 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005601 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005602 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005603 set haspad 1
5604 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005605 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005606 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005607 set id [lindex $displayorder $ym]
5608 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005609 if {$xc >= 0} {
5610 set z0 [expr {$xc - $x0}]
5611 }
5612 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005613 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005614 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5615 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005616 incr x0
5617 optimize_rows $y0 $x0 $row
5618 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005619 }
5620 }
5621 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005622 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005623 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005624 set id [lindex $idlist $col]
5625 if {$id eq {}} break
5626 set x0 [lsearch -exact $previdlist $id]
5627 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005628 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005629 set kid [lindex $displayorder $y0]
5630 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005631 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005632 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005633 }
5634 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005635 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005636 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005637 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005638 # isn't the last column
5639 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005640 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005641 lset rowidlist $row $idlist
5642 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005643 }
5644 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005645 }
5646}
5647
5648proc xc {row col} {
5649 global canvx0 linespc
5650 return [expr {$canvx0 + $col * $linespc}]
5651}
5652
5653proc yc {row} {
5654 global canvy0 linespc
5655 return [expr {$canvy0 + $row * $linespc}]
5656}
5657
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005658proc linewidth {id} {
5659 global thickerline lthickness
5660
5661 set wid $lthickness
5662 if {[info exists thickerline] && $id eq $thickerline} {
5663 set wid [expr {2 * $lthickness}]
5664 }
5665 return $wid
5666}
5667
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005668proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005669 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005670 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005671
Paul Mackerras92ed6662007-08-22 22:35:28 +10005672 set kids $children($curview,$id)
5673 if {$kids eq {}} {
5674 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005675 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005676 set ret {}
5677 lappend kids $id
5678 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005679 if {![commitinview $child $curview]} break
5680 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005681 if {![info exists prev]} {
5682 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005683 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005684 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005685 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005686 }
5687 # see if the line extends the whole way from prevrow to row
5688 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5689 [lsearch -exact [lindex $rowidlist \
5690 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5691 # it doesn't, see where it ends
5692 set r [expr {$prevrow + $downarrowlen}]
5693 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5694 while {[incr r -1] > $prevrow &&
5695 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5696 } else {
5697 while {[incr r] <= $row &&
5698 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5699 incr r -1
5700 }
5701 lappend ret $r
5702 # see where it starts up again
5703 set r [expr {$row - $uparrowlen}]
5704 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5705 while {[incr r] < $row &&
5706 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5707 } else {
5708 while {[incr r -1] >= $prevrow &&
5709 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5710 incr r
5711 }
5712 lappend ret $r
5713 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005714 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005715 if {$child eq $id} {
5716 lappend ret $row
5717 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005718 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005719 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005720 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005721 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005722}
5723
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005724proc drawlineseg {id row endrow arrowlow} {
5725 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005726 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005727
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005728 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5729 set le [expr {$row + 1}]
5730 set arrowhigh 1
5731 while {1} {
5732 set c [lsearch -exact [lindex $rowidlist $le] $id]
5733 if {$c < 0} {
5734 incr le -1
5735 break
5736 }
5737 lappend cols $c
5738 set x [lindex $displayorder $le]
5739 if {$x eq $id} {
5740 set arrowhigh 0
5741 break
5742 }
5743 if {[info exists iddrawn($x)] || $le == $endrow} {
5744 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5745 if {$c >= 0} {
5746 lappend cols $c
5747 set arrowhigh 0
5748 }
5749 break
5750 }
5751 incr le
5752 }
5753 if {$le <= $row} {
5754 return $row
5755 }
5756
5757 set lines {}
5758 set i 0
5759 set joinhigh 0
5760 if {[info exists linesegs($id)]} {
5761 set lines $linesegs($id)
5762 foreach li $lines {
5763 set r0 [lindex $li 0]
5764 if {$r0 > $row} {
5765 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5766 set joinhigh 1
5767 }
5768 break
5769 }
5770 incr i
5771 }
5772 }
5773 set joinlow 0
5774 if {$i > 0} {
5775 set li [lindex $lines [expr {$i-1}]]
5776 set r1 [lindex $li 1]
5777 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5778 set joinlow 1
5779 }
5780 }
5781
5782 set x [lindex $cols [expr {$le - $row}]]
5783 set xp [lindex $cols [expr {$le - 1 - $row}]]
5784 set dir [expr {$xp - $x}]
5785 if {$joinhigh} {
5786 set ith [lindex $lines $i 2]
5787 set coords [$canv coords $ith]
5788 set ah [$canv itemcget $ith -arrow]
5789 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5790 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5791 if {$x2 ne {} && $x - $x2 == $dir} {
5792 set coords [lrange $coords 0 end-2]
5793 }
5794 } else {
5795 set coords [list [xc $le $x] [yc $le]]
5796 }
5797 if {$joinlow} {
5798 set itl [lindex $lines [expr {$i-1}] 2]
5799 set al [$canv itemcget $itl -arrow]
5800 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005801 } elseif {$arrowlow} {
5802 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5803 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5804 set arrowlow 0
5805 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005806 }
5807 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5808 for {set y $le} {[incr y -1] > $row} {} {
5809 set x $xp
5810 set xp [lindex $cols [expr {$y - 1 - $row}]]
5811 set ndir [expr {$xp - $x}]
5812 if {$dir != $ndir || $xp < 0} {
5813 lappend coords [xc $y $x] [yc $y]
5814 }
5815 set dir $ndir
5816 }
5817 if {!$joinlow} {
5818 if {$xp < 0} {
5819 # join parent line to first child
5820 set ch [lindex $displayorder $row]
5821 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5822 if {$xc < 0} {
5823 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005824 } elseif {$xc != $x} {
5825 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5826 set d [expr {int(0.5 * $linespc)}]
5827 set x1 [xc $row $x]
5828 if {$xc < $x} {
5829 set x2 [expr {$x1 - $d}]
5830 } else {
5831 set x2 [expr {$x1 + $d}]
5832 }
5833 set y2 [yc $row]
5834 set y1 [expr {$y2 + $d}]
5835 lappend coords $x1 $y1 $x2 $y2
5836 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005837 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5838 } elseif {$xc > $x + 1} {
5839 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5840 }
5841 set x $xc
5842 }
5843 lappend coords [xc $row $x] [yc $row]
5844 } else {
5845 set xn [xc $row $xp]
5846 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005847 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005848 }
5849 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005850 assigncolor $id
5851 set t [$canv create line $coords -width [linewidth $id] \
5852 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5853 $canv lower $t
5854 bindline $t $id
5855 set lines [linsert $lines $i [list $row $le $t]]
5856 } else {
5857 $canv coords $ith $coords
5858 if {$arrow ne $ah} {
5859 $canv itemconf $ith -arrow $arrow
5860 }
5861 lset lines $i 0 $row
5862 }
5863 } else {
5864 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
5865 set ndir [expr {$xo - $xp}]
5866 set clow [$canv coords $itl]
5867 if {$dir == $ndir} {
5868 set clow [lrange $clow 2 end]
5869 }
5870 set coords [concat $coords $clow]
5871 if {!$joinhigh} {
5872 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005873 } else {
5874 # coalesce two pieces
5875 $canv delete $ith
5876 set b [lindex $lines [expr {$i-1}] 0]
5877 set e [lindex $lines $i 1]
5878 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
5879 }
5880 $canv coords $itl $coords
5881 if {$arrow ne $al} {
5882 $canv itemconf $itl -arrow $arrow
5883 }
5884 }
5885
5886 set linesegs($id) $lines
5887 return $le
5888}
5889
5890proc drawparentlinks {id row} {
5891 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10005892 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005893
5894 set rowids [lindex $rowidlist $row]
5895 set col [lsearch -exact $rowids $id]
5896 if {$col < 0} return
5897 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005898 set row2 [expr {$row + 1}]
5899 set x [xc $row $col]
5900 set y [yc $row]
5901 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10005902 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005903 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005904 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005905 # rmx = right-most X coord used
5906 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005907 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11005908 set i [lsearch -exact $ids $p]
5909 if {$i < 0} {
5910 puts "oops, parent $p of $id not in list"
5911 continue
5912 }
5913 set x2 [xc $row2 $i]
5914 if {$x2 > $rmx} {
5915 set rmx $x2
5916 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10005917 set j [lsearch -exact $rowids $p]
5918 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005919 # drawlineseg will do this one for us
5920 continue
5921 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005922 assigncolor $p
5923 # should handle duplicated parents here...
5924 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005925 if {$i != $col} {
5926 # if attaching to a vertical segment, draw a smaller
5927 # slant for visual distinctness
5928 if {$i == $j} {
5929 if {$i < $col} {
5930 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
5931 } else {
5932 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
5933 }
5934 } elseif {$i < $col && $i < $j} {
5935 # segment slants towards us already
5936 lappend coords [xc $row $j] $y
5937 } else {
5938 if {$i < $col - 1} {
5939 lappend coords [expr {$x2 + $linespc}] $y
5940 } elseif {$i > $col + 1} {
5941 lappend coords [expr {$x2 - $linespc}] $y
5942 }
5943 lappend coords $x2 $y2
5944 }
5945 } else {
5946 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005947 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005948 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005949 -fill $colormap($p) -tags lines.$p]
5950 $canv lower $t
5951 bindline $t $p
5952 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005953 if {$rmx > [lindex $idpos($id) 1]} {
5954 lset idpos($id) 1 $rmx
5955 redrawtags $id
5956 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005957}
5958
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005959proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005960 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005961
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005962 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005963}
5964
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005965proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005966 global linespc canv canv2 canv3 fgcolor curview
5967 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005968 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10005969 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10005970 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05005971 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01005972 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
5973 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005974
Linus Torvalds1407ade2008-02-09 14:02:07 -08005975 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005976 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005977 if {$id eq $nullid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01005978 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10005979 } elseif {$id eq $nullid2} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01005980 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005981 } elseif {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01005982 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005983 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005984 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005985 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005986 set x [xc $row $col]
5987 set y [yc $row]
5988 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005989 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005990 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
5991 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01005992 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005993 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005994 # triangle pointing left for left-side commits
5995 set t [$canv create polygon \
5996 [expr {$x - $orad}] $y \
5997 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
5998 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01005999 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006000 } else {
6001 # triangle pointing right for right-side commits
6002 set t [$canv create polygon \
6003 [expr {$x + $orad - 1}] $y \
6004 [expr {$x - $orad}] [expr {$y - $orad}] \
6005 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006006 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006007 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006008 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006009 $canv raise $t
6010 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006011 set rmx [llength [lindex $rowidlist $row]]
6012 set olds [lindex $parentlist $row]
6013 if {$olds ne {}} {
6014 set nextids [lindex $rowidlist [expr {$row + 1}]]
6015 foreach p $olds {
6016 set i [lsearch -exact $nextids $p]
6017 if {$i > $rmx} {
6018 set rmx $i
6019 }
6020 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006021 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006022 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006023 set rowtextx($row) $xt
6024 set idpos($id) [list $x $xt $y]
6025 if {[info exists idtags($id)] || [info exists idheads($id)]
6026 || [info exists idotherrefs($id)]} {
6027 set xt [drawtags $id $x $xt $y]
6028 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006029 if {[lindex $commitinfo($id) 6] > 0} {
6030 set xt [drawnotesign $xt $y]
6031 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006032 set headline [lindex $commitinfo($id) 0]
6033 set name [lindex $commitinfo($id) 1]
6034 set date [lindex $commitinfo($id) 2]
6035 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006036 set font mainfont
6037 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006038 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006039 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006040 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006041 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006042 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006043 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006044 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006045 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006046 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006047 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
6048 -text $headline -font $font -tags text]
6049 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6050 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
6051 -text $name -font $nfont -tags text]
6052 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
6053 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006054 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006055 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006056 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006057 if {[info exists markedid] && $markedid eq $id} {
6058 make_idmark $id
6059 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006060 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006061 if {$xr > $canvxmax} {
6062 set canvxmax $xr
6063 setcanvscroll
6064 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006065}
6066
6067proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006068 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006069 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006070 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006071 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006072 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006073 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006074
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006075 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006076
6077 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006078 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006079 askvhighlight $row $id
6080 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006081 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006082 askfilehighlight $row $id
6083 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006084 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006085 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006086 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006087 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10006088 askrelhighlight $row $id
6089 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006090 if {![info exists iddrawn($id)]} {
6091 set col [lsearch -exact [lindex $rowidlist $row] $id]
6092 if {$col < 0} {
6093 puts "oops, row $row id $id not in list"
6094 return
6095 }
6096 if {![info exists commitinfo($id)]} {
6097 getcommit $id
6098 }
6099 assigncolor $id
6100 drawcmittext $id $row $col
6101 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10006102 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006103 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006104 if {$markingmatches} {
6105 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006106 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006107}
6108
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006109proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006110 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006111 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006112
6113 if {$row < 0} {
6114 set row 0
6115 }
6116 if {$endrow eq {}} {
6117 set endrow $row
6118 }
6119 if {$endrow >= $numcommits} {
6120 set endrow [expr {$numcommits - 1}]
6121 }
6122
Paul Mackerras03800812007-08-29 21:45:21 +10006123 set rl1 [expr {$row - $downarrowlen - 3}]
6124 if {$rl1 < 0} {
6125 set rl1 0
6126 }
6127 set ro1 [expr {$row - 3}]
6128 if {$ro1 < 0} {
6129 set ro1 0
6130 }
6131 set r2 [expr {$endrow + $uparrowlen + 3}]
6132 if {$r2 > $numcommits} {
6133 set r2 $numcommits
6134 }
6135 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006136 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10006137 if {$rl1 < $r} {
6138 layoutrows $rl1 $r
6139 }
6140 set rl1 [expr {$r + 1}]
6141 }
6142 }
6143 if {$rl1 < $r} {
6144 layoutrows $rl1 $r
6145 }
6146 optimize_rows $ro1 0 $r2
6147 if {$need_redisplay || $nrows_drawn > 2000} {
6148 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006149 }
6150
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006151 # make the lines join to already-drawn rows either side
6152 set r [expr {$row - 1}]
6153 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
6154 set r $row
6155 }
6156 set er [expr {$endrow + 1}]
6157 if {$er >= $numcommits ||
6158 ![info exists iddrawn([lindex $displayorder $er])]} {
6159 set er $endrow
6160 }
6161 for {} {$r <= $er} {incr r} {
6162 set id [lindex $displayorder $r]
6163 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006164 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006165 if {$r == $er} break
6166 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006167 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006168 drawparentlinks $id $r
6169
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006170 set rowids [lindex $rowidlist $r]
6171 foreach lid $rowids {
6172 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006173 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006174 if {$lid eq $id} {
6175 # see if this is the first child of any of its parents
6176 foreach p [lindex $parentlist $r] {
6177 if {[lsearch -exact $rowids $p] < 0} {
6178 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006179 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006180 }
6181 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006182 } else {
6183 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006184 }
6185 }
6186 }
6187}
6188
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006189proc undolayout {row} {
6190 global uparrowlen mingaplen downarrowlen
6191 global rowidlist rowisopt rowfinal need_redisplay
6192
6193 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6194 if {$r < 0} {
6195 set r 0
6196 }
6197 if {[llength $rowidlist] > $r} {
6198 incr r -1
6199 set rowidlist [lrange $rowidlist 0 $r]
6200 set rowfinal [lrange $rowfinal 0 $r]
6201 set rowisopt [lrange $rowisopt 0 $r]
6202 set need_redisplay 1
6203 run drawvisible
6204 }
6205}
6206
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006207proc drawvisible {} {
6208 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006209 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006210
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006211 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006212 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006213 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006214 set f0 [lindex $fs 0]
6215 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006216 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006217 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006218
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006219 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11006220 if {[commitinview $targetid $curview]} {
6221 set r [rowofcommit $targetid]
6222 if {$r != $targetrow} {
6223 # Fix up the scrollregion and change the scrolling position
6224 # now that our target row has moved.
6225 set diff [expr {($r - $targetrow) * $linespc}]
6226 set targetrow $r
6227 setcanvscroll
6228 set ymax [lindex [$canv cget -scrollregion] 3]
6229 incr y0 $diff
6230 incr y1 $diff
6231 set f0 [expr {$y0 / $ymax}]
6232 set f1 [expr {$y1 / $ymax}]
6233 allcanvs yview moveto $f0
6234 $cscroll set $f0 $f1
6235 set need_redisplay 1
6236 }
6237 } else {
6238 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006239 }
6240 }
6241
6242 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6243 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6244 if {$endrow >= $vrowmod($curview)} {
6245 update_arcrows $curview
6246 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006247 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006248 $row <= $selectedline && $selectedline <= $endrow} {
6249 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006250 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006251 set targetrow [expr {int(($row + $endrow) / 2)}]
6252 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006253 if {[info exists targetrow]} {
6254 if {$targetrow >= $numcommits} {
6255 set targetrow [expr {$numcommits - 1}]
6256 }
6257 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006258 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006259 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006260}
6261
6262proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006263 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006264 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006265 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006266
6267 allcanvs delete all
6268 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006269 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10006270 catch {unset linehtag}
6271 catch {unset linentag}
6272 catch {unset linedtag}
Paul Mackerras28593d32008-11-13 23:01:46 +11006273 set boldids {}
6274 set boldnameids {}
Paul Mackerras908c3582006-05-20 09:38:11 +10006275 catch {unset vhighlights}
6276 catch {unset fhighlights}
6277 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10006278 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10006279 set need_redisplay 0
6280 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006281}
6282
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006283proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006284 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006285
6286 set cross {}
6287 set ccross {}
6288 foreach {s e} [rowranges $id] {
6289 if {$e >= $numcommits} {
6290 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006291 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006292 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006293 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006294 set x [lsearch -exact [lindex $rowidlist $row] $id]
6295 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006296 set olds [lindex $parentlist $row]
6297 set kid [lindex $displayorder $row]
6298 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6299 if {$kidx < 0} continue
6300 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6301 foreach p $olds {
6302 set px [lsearch -exact $nextrow $p]
6303 if {$px < 0} continue
6304 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6305 if {[lsearch -exact $ccross $p] >= 0} continue
6306 if {$x == $px + ($kidx < $px? -1: 1)} {
6307 lappend ccross $p
6308 } elseif {[lsearch -exact $cross $p] < 0} {
6309 lappend cross $p
6310 }
6311 }
6312 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006313 }
6314 }
6315 return [concat $ccross {{}} $cross]
6316}
6317
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006318proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006319 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006320 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006321
Paul Mackerras418c4c72006-02-07 09:10:18 +11006322 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006323 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006324 if {[info exists children($curview,$id)]} {
6325 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006326 } else {
6327 set kids {}
6328 }
6329 if {[llength $kids] == 1} {
6330 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006331 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006332 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006333 set colormap($id) $colormap($child)
6334 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006335 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006336 }
6337 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006338 set origbad {}
6339 foreach x [findcrossings $id] {
6340 if {$x eq {}} {
6341 # delimiter between corner crossings and other crossings
6342 if {[llength $badcolors] >= $ncolors - 1} break
6343 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006344 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006345 if {[info exists colormap($x)]
6346 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6347 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006348 }
6349 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006350 if {[llength $badcolors] >= $ncolors} {
6351 set badcolors $origbad
6352 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006353 set origbad $badcolors
6354 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006355 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006356 if {[info exists colormap($child)]
6357 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6358 lappend badcolors $colormap($child)
6359 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006360 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006361 if {[info exists colormap($p)]
6362 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6363 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006364 }
6365 }
6366 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006367 if {[llength $badcolors] >= $ncolors} {
6368 set badcolors $origbad
6369 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006370 }
6371 for {set i 0} {$i <= $ncolors} {incr i} {
6372 set c [lindex $colors $nextcolor]
6373 if {[incr nextcolor] >= $ncolors} {
6374 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006375 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006376 if {[lsearch -exact $badcolors $c]} break
6377 }
6378 set colormap($id) $c
6379}
6380
Paul Mackerrasa823a912005-06-21 10:01:38 +10006381proc bindline {t id} {
6382 global canv
6383
Paul Mackerrasa823a912005-06-21 10:01:38 +10006384 $canv bind $t <Enter> "lineenter %x %y $id"
6385 $canv bind $t <Motion> "linemotion %x %y $id"
6386 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006387 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006388}
6389
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006390proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006391 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006392 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006393 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006394 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6395 global tagbgcolor tagfgcolor tagoutlinecolor
6396 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006397
6398 set marks {}
6399 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006400 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006401 if {[info exists idtags($id)]} {
6402 set marks $idtags($id)
6403 set ntags [llength $marks]
6404 }
6405 if {[info exists idheads($id)]} {
6406 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006407 set nheads [llength $idheads($id)]
6408 }
6409 if {[info exists idotherrefs($id)]} {
6410 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006411 }
6412 if {$marks eq {}} {
6413 return $xt
6414 }
6415
6416 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006417 set yt [expr {$y1 - 0.5 * $linespc}]
6418 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006419 set xvals {}
6420 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006421 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006422 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006423 incr i
6424 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006425 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006426 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006427 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006428 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006429 lappend xvals $xt
6430 lappend wvals $wid
6431 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
6432 }
6433 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006434 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006435 $canv lower $t
6436 foreach tag $marks x $xvals wid $wvals {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006437 set tag_quoted [string map {% %%} $tag]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006438 set xl [expr {$x + $delta}]
6439 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006440 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006441 if {[incr ntags -1] >= 0} {
6442 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006443 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6444 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006445 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6446 -tags tag.$id]
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006447 $canv bind $t <1> [list showtag $tag_quoted 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006448 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006449 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006450 # draw a head or other ref
6451 if {[incr nheads -1] >= 0} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006452 set col $headbgcolor
Paul Mackerras8a485712006-07-06 10:21:23 +10006453 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006454 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006455 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006456 } else {
6457 set col "#ddddff"
6458 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006459 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006460 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006461 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006462 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006463 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006464 set xi [expr {$x + 1}]
6465 set yti [expr {$yt + 1}]
6466 set xri [expr {$x + $rwid}]
6467 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006468 -width 0 -fill $remotebgcolor -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006469 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006470 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006471 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006472 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006473 if {$ntags >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006474 $canv bind $t <1> [list showtag $tag_quoted 1]
Paul Mackerras10299152006-08-02 09:52:01 +10006475 } elseif {$nheads >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006476 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
Paul Mackerras106288c2005-08-19 23:11:39 +10006477 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006478 }
6479 return $xt
6480}
6481
Raphael Zimmerer36242492011-04-19 22:37:09 +02006482proc drawnotesign {xt y} {
6483 global linespc canv fgcolor
6484
6485 set orad [expr {$linespc / 3}]
6486 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
6487 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6488 -fill yellow -outline $fgcolor -width 1 -tags circle]
6489 set xt [expr {$xt + $orad * 3}]
6490 return $xt
6491}
6492
Paul Mackerras8d858d12005-08-05 09:52:16 +10006493proc xcoord {i level ln} {
6494 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006495
Paul Mackerras8d858d12005-08-05 09:52:16 +10006496 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6497 if {$i > 0 && $i == $level} {
6498 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6499 } elseif {$i > $level} {
6500 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6501 }
6502 return $x
6503}
6504
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006505proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006506 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006507
6508 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10006509 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006510 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006511}
6512
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006513# Don't change the text pane cursor if it is currently the hand cursor,
6514# showing that we are over a sha1 ID link.
6515proc settextcursor {c} {
6516 global ctext curtextcursor
6517
6518 if {[$ctext cget -cursor] == $curtextcursor} {
6519 $ctext config -cursor $c
6520 }
6521 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006522}
6523
Paul Mackerrasa137a902007-10-23 21:12:49 +10006524proc nowbusy {what {name {}}} {
6525 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006526
6527 if {[array names isbusy] eq {}} {
6528 . config -cursor watch
6529 settextcursor watch
6530 }
6531 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006532 set busyname($what) $name
6533 if {$name ne {}} {
6534 $statusw conf -text $name
6535 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006536}
6537
6538proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006539 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006540
Paul Mackerrasa137a902007-10-23 21:12:49 +10006541 catch {
6542 unset isbusy($what)
6543 if {$busyname($what) ne {} &&
6544 [$statusw cget -text] eq $busyname($what)} {
6545 $statusw conf -text {}
6546 }
6547 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006548 if {[array names isbusy] eq {}} {
6549 . config -cursor $maincursor
6550 settextcursor $textcursor
6551 }
6552}
6553
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006554proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006555 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006556 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006557 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006558 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006559 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006560 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006561 set f [string tolower $f]
6562 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006563 }
6564 set matches {}
6565 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006566 set l [string length $fs]
6567 while {[set j [string first $fs $f $i]] >= 0} {
6568 lappend matches [list $j [expr {$j+$l-1}]]
6569 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006570 }
6571 }
6572 return $matches
6573}
6574
Paul Mackerrascca5d942007-10-27 21:16:56 +10006575proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006576 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006577 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006578
Paul Mackerrascca5d942007-10-27 21:16:56 +10006579 if {[info exists find_dirn]} {
6580 if {$find_dirn == $dirn} return
6581 stopfinding
6582 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006583 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006584 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006585 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006586 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006587 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006588 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006589 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006590 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006591 nowbusy finding [mc "Searching"]
6592 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006593 after cancel do_file_hl $fh_serial
6594 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006595 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006596 set find_dirn $dirn
6597 set findallowwrap $wrap
6598 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006599}
6600
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006601proc stopfinding {} {
6602 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006603
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006604 if {[info exists find_dirn]} {
6605 unset find_dirn
6606 unset findcurline
6607 notbusy finding
6608 set fprogcoord 0
6609 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006610 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006611 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006612}
6613
6614proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006615 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006616 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006617 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006618 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006619
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006620 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006621 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006622 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006623 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006624 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006625 set moretodo 0
6626 if {$find_dirn > 0} {
6627 incr l
6628 if {$l >= $numcommits} {
6629 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006630 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006631 if {$l <= $findstartline} {
6632 set lim [expr {$findstartline + 1}]
6633 } else {
6634 set lim $numcommits
6635 set moretodo $findallowwrap
6636 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006637 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006638 if {$l == 0} {
6639 set l $numcommits
6640 }
6641 incr l -1
6642 if {$l >= $findstartline} {
6643 set lim [expr {$findstartline - 1}]
6644 } else {
6645 set lim -1
6646 set moretodo $findallowwrap
6647 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006648 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006649 set n [expr {($lim - $l) * $find_dirn}]
6650 if {$n > 500} {
6651 set n 500
6652 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006653 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006654 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6655 update_arcrows $curview
6656 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006657 set found 0
6658 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006659 set ai [bsearch $vrownum($curview) $l]
6660 set a [lindex $varcorder($curview) $ai]
6661 set arow [lindex $vrownum($curview) $ai]
6662 set ids [lindex $varccommits($curview,$a)]
6663 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006664 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006665 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006666 if {$l < $arow || $l >= $arowend} {
6667 incr ai $find_dirn
6668 set a [lindex $varcorder($curview) $ai]
6669 set arow [lindex $vrownum($curview) $ai]
6670 set ids [lindex $varccommits($curview,$a)]
6671 set arowend [expr {$arow + [llength $ids]}]
6672 }
6673 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006674 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006675 if {![info exists commitdata($id)] ||
6676 ![doesmatch $commitdata($id)]} {
6677 continue
6678 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006679 if {![info exists commitinfo($id)]} {
6680 getcommit $id
6681 }
6682 set info $commitinfo($id)
6683 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04006684 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01006685 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006686 [doesmatch $f]} {
6687 set found 1
6688 break
6689 }
6690 }
6691 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006692 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006693 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006694 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006695 if {$l < $arow || $l >= $arowend} {
6696 incr ai $find_dirn
6697 set a [lindex $varcorder($curview) $ai]
6698 set arow [lindex $vrownum($curview) $ai]
6699 set ids [lindex $varccommits($curview,$a)]
6700 set arowend [expr {$arow + [llength $ids]}]
6701 }
6702 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006703 if {![info exists fhighlights($id)]} {
6704 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006705 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006706 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006707 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006708 set found $domore
6709 break
6710 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006711 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006712 if {$domore} {
6713 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006714 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006715 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006716 }
6717 }
6718 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006719 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006720 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006721 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006722 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006723 set fprogcoord 0
6724 adjustprogress
6725 if {$found} {
6726 findselectline $l
6727 } else {
6728 bell
6729 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006730 return 0
6731 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006732 if {!$domore} {
6733 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006734 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006735 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006736 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006737 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006738 if {$n < 0} {
6739 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006740 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006741 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6742 adjustprogress
6743 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006744}
6745
6746proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006747 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006748
Paul Mackerras8b39e042008-12-02 09:02:46 +11006749 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006750 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006751 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006752 if {$markingmatches &&
6753 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006754 # highlight the matches in the comments
6755 set f [$ctext get 1.0 $commentend]
6756 set matches [findmatches $f]
6757 foreach match $matches {
6758 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006759 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006760 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6761 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006762 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006763 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006764}
6765
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006766# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006767proc markmatches {canv l str tag matches font row} {
6768 global selectedline
6769
Paul Mackerras98f350e2005-05-15 05:56:51 +00006770 set bbox [$canv bbox $tag]
6771 set x0 [lindex $bbox 0]
6772 set y0 [lindex $bbox 1]
6773 set y1 [lindex $bbox 3]
6774 foreach match $matches {
6775 set start [lindex $match 0]
6776 set end [lindex $match 1]
6777 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006778 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6779 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6780 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6781 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006782 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006783 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006784 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006785 $canv raise $t secsel
6786 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006787 }
6788}
6789
6790proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006791 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006792
Paul Mackerras98f350e2005-05-15 05:56:51 +00006793 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006794 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006795 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006796}
6797
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006798proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006799 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006800 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006801 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006802 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006803 set yfrac [lindex [$canv yview] 0]
6804 set y [expr {$y + $yfrac * $ymax}]
6805 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6806 if {$l < 0} {
6807 set l 0
6808 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006809 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006810 set xmax [lindex [$canv cget -scrollregion] 2]
6811 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6812 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006813 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006814 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006815 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006816}
6817
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006818proc commit_descriptor {p} {
6819 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10006820 if {![info exists commitinfo($p)]} {
6821 getcommit $p
6822 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006823 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10006824 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006825 set l [lindex $commitinfo($p) 0]
6826 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006827 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006828}
6829
Paul Mackerras106288c2005-08-19 23:11:39 +10006830# append some text to the ctext widget, and make any SHA1 ID
6831# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006832proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006833 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10006834
6835 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006836 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01006837 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10006838 foreach l $links {
6839 set s [lindex $l 0]
6840 set e [lindex $l 1]
6841 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10006842 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10006843 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006844 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10006845 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006846 incr linknum
6847 }
Paul Mackerras97645682007-08-23 22:24:38 +10006848}
6849
6850proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006851 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006852 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10006853
Jim Meyering6c9e2d12011-12-10 16:08:57 +01006854 if {[string range $id 0 1] eq "-g"} {
6855 set id [string range $id 2 end]
6856 }
6857
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006858 set known 0
6859 if {[string length $id] < 40} {
6860 set matches [longid $id]
6861 if {[llength $matches] > 0} {
6862 if {[llength $matches] > 1} return
6863 set known 1
6864 set id [lindex $matches 0]
6865 }
6866 } else {
6867 set known [commitinview $id $curview]
6868 }
6869 if {$known} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006870 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006871 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10006872 $ctext tag bind $lk <Enter> {linkcursor %W 1}
6873 $ctext tag bind $lk <Leave> {linkcursor %W -1}
6874 } else {
6875 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006876 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10006877 }
6878}
6879
Paul Mackerras6f63fc12009-04-21 22:22:31 +10006880proc appendshortlink {id {pre {}} {post {}}} {
6881 global ctext linknum
6882
6883 $ctext insert end $pre
6884 $ctext tag delete link$linknum
6885 $ctext insert end [string range $id 0 7] link$linknum
6886 $ctext insert end $post
6887 setlink $id link$linknum
6888 incr linknum
6889}
6890
Paul Mackerras97645682007-08-23 22:24:38 +10006891proc makelink {id} {
6892 global pendinglinks
6893
6894 if {![info exists pendinglinks($id)]} return
6895 foreach lk $pendinglinks($id) {
6896 setlink $id $lk
6897 }
6898 unset pendinglinks($id)
6899}
6900
6901proc linkcursor {w inc} {
6902 global linkentercount curtextcursor
6903
6904 if {[incr linkentercount $inc] > 0} {
6905 $w configure -cursor hand2
6906 } else {
6907 $w configure -cursor $curtextcursor
6908 if {$linkentercount < 0} {
6909 set linkentercount 0
6910 }
6911 }
Paul Mackerras106288c2005-08-19 23:11:39 +10006912}
6913
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006914proc viewnextline {dir} {
6915 global canv linespc
6916
6917 $canv delete hover
6918 set ymax [lindex [$canv cget -scrollregion] 3]
6919 set wnow [$canv yview]
6920 set wtop [expr {[lindex $wnow 0] * $ymax}]
6921 set newtop [expr {$wtop + $dir * $linespc}]
6922 if {$newtop < 0} {
6923 set newtop 0
6924 } elseif {$newtop > $ymax} {
6925 set newtop $ymax
6926 }
6927 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
6928}
6929
Paul Mackerrasef030b82006-06-04 11:50:38 +10006930# add a list of tag or branch names at position pos
6931# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10006932proc appendrefs {pos ids var} {
Paul Mackerras386befb2013-01-02 15:25:29 +11006933 global ctext linknum curview $var maxrefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006934
Paul Mackerrasef030b82006-06-04 11:50:38 +10006935 if {[catch {$ctext index $pos}]} {
6936 return 0
6937 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006938 $ctext conf -state normal
6939 $ctext delete $pos "$pos lineend"
6940 set tags {}
6941 foreach id $ids {
6942 foreach tag [set $var\($id\)] {
6943 lappend tags [list $tag $id]
6944 }
6945 }
Paul Mackerras386befb2013-01-02 15:25:29 +11006946
6947 set sep {}
6948 set tags [lsort -index 0 -decreasing $tags]
6949 set nutags 0
6950
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006951 if {[llength $tags] > $maxrefs} {
Paul Mackerras386befb2013-01-02 15:25:29 +11006952 # If we are displaying heads, and there are too many,
6953 # see if there are some important heads to display.
6954 # Currently this means "master" and the current head.
6955 set itags {}
6956 if {$var eq "idheads"} {
6957 set utags {}
6958 foreach ti $tags {
6959 set hname [lindex $ti 0]
6960 set id [lindex $ti 1]
6961 if {($hname eq "master" || $id eq $mainheadid) &&
6962 [llength $itags] < $maxrefs} {
6963 lappend itags $ti
6964 } else {
6965 lappend utags $ti
6966 }
6967 }
6968 set tags $utags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006969 }
Paul Mackerras386befb2013-01-02 15:25:29 +11006970 if {$itags ne {}} {
6971 set str [mc "and many more"]
6972 set sep " "
6973 } else {
6974 set str [mc "many"]
6975 }
6976 $ctext insert $pos "$str ([llength $tags])"
6977 set nutags [llength $tags]
6978 set tags $itags
6979 }
6980
6981 foreach ti $tags {
6982 set id [lindex $ti 1]
6983 set lk link$linknum
6984 incr linknum
6985 $ctext tag delete $lk
6986 $ctext insert $pos $sep
6987 $ctext insert $pos [lindex $ti 0] $lk
6988 setlink $id $lk
6989 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006990 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11006991 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10006992 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11006993 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006994}
6995
6996# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10006997proc dispneartags {delay} {
6998 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006999
Paul Mackerras94b4a692008-05-20 20:51:06 +10007000 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007001 after cancel dispnexttag
7002 if {$delay} {
7003 after 200 dispnexttag
7004 set tagphase -1
7005 } else {
7006 after idle dispnexttag
7007 set tagphase 0
7008 }
7009}
7010
7011proc dispnexttag {} {
7012 global selectedline currentid showneartags tagphase ctext
7013
Paul Mackerras94b4a692008-05-20 20:51:06 +10007014 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007015 switch -- $tagphase {
7016 0 {
7017 set dtags [desctags $currentid]
7018 if {$dtags ne {}} {
7019 appendrefs precedes $dtags idtags
7020 }
7021 }
7022 1 {
7023 set atags [anctags $currentid]
7024 if {$atags ne {}} {
7025 appendrefs follows $atags idtags
7026 }
7027 }
7028 2 {
7029 set dheads [descheads $currentid]
7030 if {$dheads ne {}} {
7031 if {[appendrefs branch $dheads idheads] > 1
7032 && [$ctext get "branch -3c"] eq "h"} {
7033 # turn "Branch" into "Branches"
7034 $ctext conf -state normal
7035 $ctext insert "branch -2c" "es"
7036 $ctext conf -state disabled
7037 }
7038 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007039 }
7040 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007041 if {[incr tagphase] <= 2} {
7042 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007043 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007044}
7045
Paul Mackerras28593d32008-11-13 23:01:46 +11007046proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007047 global linehtag linentag linedtag canv canv2 canv3
7048
Paul Mackerras28593d32008-11-13 23:01:46 +11007049 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007050 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007051 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007052 -tags secsel -fill [$canv cget -selectbackground]]
7053 $canv lower $t
7054 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007055 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007056 -tags secsel -fill [$canv2 cget -selectbackground]]
7057 $canv2 lower $t
7058 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007059 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007060 -tags secsel -fill [$canv3 cget -selectbackground]]
7061 $canv3 lower $t
7062}
7063
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007064proc make_idmark {id} {
7065 global linehtag canv fgcolor
7066
7067 if {![info exists linehtag($id)]} return
7068 $canv delete markid
7069 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
7070 -tags markid -outline $fgcolor]
7071 $canv raise $t
7072}
7073
Paul Mackerras8a897742008-10-27 21:36:25 +11007074proc selectline {l isnew {desired_loc {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007075 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007076 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007077 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007078 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007079 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007080 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007081 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007082 global autoselect autosellen jump_to_here
Paul Mackerrasd6982062005-08-06 22:06:06 +10007083
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007084 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00007085 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007086 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007087 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007088 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007089 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007090 set id [commitonrow $l]
7091 set targetid $id
7092 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007093 set selectedline $l
7094 set currentid $id
7095 if {$lastscrollrows < $numcommits} {
7096 setcanvscroll
7097 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007098
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007099 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007100 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007101 set ytop [expr {$y - $linespc - 1}]
7102 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007103 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007104 set wtop [expr {[lindex $wnow 0] * $ymax}]
7105 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007106 set wh [expr {$wbot - $wtop}]
7107 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007108 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00007109 if {$ybot < $wtop} {
7110 set newtop [expr {$y - $wh / 2.0}]
7111 } else {
7112 set newtop $ytop
7113 if {$newtop > $wtop - $linespc} {
7114 set newtop [expr {$wtop - $linespc}]
7115 }
Paul Mackerras17386062005-05-18 22:51:00 +00007116 }
Paul Mackerras58422152005-05-19 10:56:42 +00007117 } elseif {$ybot > $wbot} {
7118 if {$ytop > $wbot} {
7119 set newtop [expr {$y - $wh / 2.0}]
7120 } else {
7121 set newtop [expr {$ybot - $wh}]
7122 if {$newtop < $wtop + $linespc} {
7123 set newtop [expr {$wtop + $linespc}]
7124 }
Paul Mackerras17386062005-05-18 22:51:00 +00007125 }
Paul Mackerras58422152005-05-19 10:56:42 +00007126 }
7127 if {$newtop != $wtop} {
7128 if {$newtop < 0} {
7129 set newtop 0
7130 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007131 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007132 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007133 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007134
Paul Mackerras28593d32008-11-13 23:01:46 +11007135 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007136
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007137 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007138 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007139 }
7140
Paul Mackerras98f350e2005-05-15 05:56:51 +00007141 $sha1entry delete 0 end
7142 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007143 if {$autoselect} {
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007144 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007145 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007146 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007147
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007148 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007149 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007150 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007151 if {![info exists commitinfo($id)]} {
7152 getcommit $id
7153 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007154 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007155 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007156 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007157 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007158 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007159 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007160 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007161 foreach tag $idtags($id) {
7162 $ctext insert end " $tag"
7163 }
7164 $ctext insert end "\n"
7165 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007166
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007167 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007168 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007169 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007170 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007171 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007172 if {$np >= $mergemax} {
7173 set tag mmax
7174 } else {
7175 set tag m$np
7176 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007177 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007178 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007179 incr np
7180 }
7181 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007182 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007183 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007184 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007185 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007186
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007187 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007188 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007189 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007190
7191 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007192 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007193 if {$showneartags} {
7194 if {![info exists allcommits]} {
7195 getallcommits
7196 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007197 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10007198 $ctext mark set branch "end -1c"
7199 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007200 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007201 $ctext mark set follows "end -1c"
7202 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007203 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007204 $ctext mark set precedes "end -1c"
7205 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007206 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007207 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007208 }
7209 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007210 set comment [lindex $info 5]
7211 if {[string first "\r" $comment] >= 0} {
7212 set comment [string map {"\r" "\n "} $comment]
7213 }
7214 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007215
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007216 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007217 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007218 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007219
Paul Mackerras8a897742008-10-27 21:36:25 +11007220 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007221 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007222 if {$cmitmode eq "tree"} {
7223 gettree $id
7224 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11007225 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007226 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007227 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007228 }
7229}
7230
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007231proc selfirstline {} {
7232 unmarkmatches
7233 selectline 0 1
7234}
7235
7236proc sellastline {} {
7237 global numcommits
7238 unmarkmatches
7239 set l [expr {$numcommits - 1}]
7240 selectline $l 1
7241}
7242
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007243proc selnextline {dir} {
7244 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007245 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007246 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007247 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007248 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007249 selectline $l 1
7250}
7251
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007252proc selnextpage {dir} {
7253 global canv linespc selectedline numcommits
7254
7255 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7256 if {$lpp < 1} {
7257 set lpp 1
7258 }
7259 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007260 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007261 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007262 set l [expr {$selectedline + $dir * $lpp}]
7263 if {$l < 0} {
7264 set l 0
7265 } elseif {$l >= $numcommits} {
7266 set l [expr $numcommits - 1]
7267 }
7268 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007269 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007270}
7271
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007272proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007273 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007274
Paul Mackerras94b4a692008-05-20 20:51:06 +10007275 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007276 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007277 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007278 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007279}
7280
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007281proc reselectline {} {
7282 global selectedline
7283
Paul Mackerras94b4a692008-05-20 20:51:06 +10007284 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007285 selectline $selectedline 0
7286 }
7287}
7288
Paul Mackerras354af6b2008-11-23 13:14:23 +11007289proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007290 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007291
Paul Mackerras354af6b2008-11-23 13:14:23 +11007292 unset_posvars
7293 save_position
7294 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007295 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10007296 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007297 return
7298 }
7299
7300 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007301 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007302 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007303 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007304 }
7305 incr historyindex
7306 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007307 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007308 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007309 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007310 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007311 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007312}
7313
Paul Mackerras354af6b2008-11-23 13:14:23 +11007314# save the scrolling position of the diff display pane
7315proc save_position {} {
7316 global historyindex history
7317
7318 if {$historyindex < 1} return
7319 set hi [expr {$historyindex - 1}]
7320 set fn [lindex $history $hi 2]
7321 if {$fn ne {}} {
7322 lset history $hi 3 [eval $fn]
7323 }
7324}
7325
7326proc unset_posvars {} {
7327 global last_posvars
7328
7329 if {[info exists last_posvars]} {
7330 foreach {var val} $last_posvars {
7331 global $var
7332 catch {unset $var}
7333 }
7334 unset last_posvars
7335 }
7336}
7337
Paul Mackerras2516dae2006-04-21 10:35:31 +10007338proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007339 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007340
7341 set view [lindex $elt 0]
7342 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007343 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007344 if {$curview != $view} {
7345 showview $view
7346 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007347 unset_posvars
7348 foreach {var val} $pv {
7349 global $var
7350 set $var $val
7351 }
7352 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007353 eval $cmd
7354}
7355
Paul Mackerrasd6982062005-08-06 22:06:06 +10007356proc goback {} {
7357 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007358 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007359
7360 if {$historyindex > 1} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007361 save_position
Paul Mackerrasd6982062005-08-06 22:06:06 +10007362 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10007363 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007364 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007365 }
7366 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007367 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007368 }
7369}
7370
7371proc goforw {} {
7372 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007373 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007374
7375 if {$historyindex < [llength $history]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007376 save_position
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007377 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10007378 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10007379 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007380 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007381 }
7382 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007383 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007384 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007385}
7386
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007387proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007388 global treefilelist treeidlist diffids diffmergeid treepending
7389 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007390
7391 set diffids $id
7392 catch {unset diffmergeid}
7393 if {![info exists treefilelist($id)]} {
7394 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007395 if {$id eq $nullid} {
7396 set cmd [list | git ls-files]
7397 } elseif {$id eq $nullid2} {
7398 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007399 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007400 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007401 }
7402 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007403 return
7404 }
7405 set treepending $id
7406 set treefilelist($id) {}
7407 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007408 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007409 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007410 }
7411 } else {
7412 setfilelist $id
7413 }
7414}
7415
7416proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007417 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007418
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007419 set nl 0
7420 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007421 if {$diffids eq $nullid} {
7422 set fname $line
7423 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007424 set i [string first "\t" $line]
7425 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007426 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007427 set line [string range $line 0 [expr {$i-1}]]
7428 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7429 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007430 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007431 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007432 if {[string index $fname 0] eq "\""} {
7433 set fname [lindex $fname 0]
7434 }
7435 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007436 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007437 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007438 if {![eof $gtf]} {
7439 return [expr {$nl >= 1000? 2: 1}]
7440 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007441 close $gtf
7442 unset treepending
7443 if {$cmitmode ne "tree"} {
7444 if {![info exists diffmergeid]} {
7445 gettreediffs $diffids
7446 }
7447 } elseif {$id ne $diffids} {
7448 gettree $diffids
7449 } else {
7450 setfilelist $id
7451 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007452 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007453}
7454
7455proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007456 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007457 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007458 global ctext commentend
7459
7460 set i [lsearch -exact $treefilelist($diffids) $f]
7461 if {$i < 0} {
7462 puts "oops, $f not in list for id $diffids"
7463 return
7464 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007465 if {$diffids eq $nullid} {
7466 if {[catch {set bf [open $f r]} err]} {
7467 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007468 return
7469 }
7470 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007471 set blob [lindex $treeidlist($diffids) $i]
7472 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7473 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007474 return
7475 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007476 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007477 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007478 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007479 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007480 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007481 lappend ctext_file_names $f
7482 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007483 $ctext insert end "\n"
7484 $ctext insert end "$f\n" filesep
7485 $ctext config -state disabled
7486 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007487 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007488}
7489
7490proc getblobline {bf id} {
7491 global diffids cmitmode ctext
7492
7493 if {$id ne $diffids || $cmitmode ne "tree"} {
7494 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007495 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007496 }
7497 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007498 set nl 0
7499 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007500 $ctext insert end "$line\n"
7501 }
7502 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007503 global jump_to_here ctext_file_names commentend
7504
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007505 # delete last newline
7506 $ctext delete "end - 2c" "end - 1c"
7507 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007508 if {$jump_to_here ne {} &&
7509 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7510 set lnum [expr {[lindex $jump_to_here 1] +
7511 [lindex [split $commentend .] 0]}]
7512 mark_ctext_line $lnum
7513 }
Stefan Haller120ea892010-11-14 13:21:50 +01007514 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007515 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007516 }
7517 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007518 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007519}
7520
Paul Mackerras8a897742008-10-27 21:36:25 +11007521proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007522 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007523
7524 $ctext tag delete omark
7525 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007526 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007527 $ctext see $lnum.0
7528}
7529
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007530proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007531 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007532 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007533 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007534
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007535 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007536 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007537 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007538 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007539 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007540 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007541}
7542
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007543proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007544 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007545
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007546 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007547 set diffids $ids
7548 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10007549 if {![info exists treediffs($ids)] ||
7550 [lsearch -exact $ids $nullid] >= 0 ||
7551 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007552 if {![info exists treepending]} {
7553 gettreediffs $ids
7554 }
7555 } else {
7556 addtocflist $ids
7557 }
7558}
7559
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007560# If the filename (name) is under any of the passed filter paths
7561# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007562proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007563 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007564 foreach p $filter {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007565 set fq_p [file normalize $p]
7566 set fq_n [file normalize [file join $worktree $name]]
7567 if {[string match [file normalize $fq_p]* $fq_n]} {
7568 return 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10007569 }
7570 }
7571 return 0
7572}
7573
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007574proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007575 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007576
Paul Mackerras74a40c72007-10-24 10:16:56 +10007577 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007578 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007579}
7580
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007581proc diffcmd {ids flags} {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007582 global log_showroot nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007583
7584 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007585 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007586 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007587 if {[llength $ids] > 1 && $j < 0} {
7588 # comparing working directory with some specific revision
7589 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007590 if {$i == 0} {
7591 lappend cmd -R [lindex $ids 1]
7592 } else {
7593 lappend cmd [lindex $ids 0]
7594 }
7595 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007596 # comparing working directory with index
7597 set cmd [concat | git diff-files $flags]
7598 if {$j == 1} {
7599 lappend cmd -R
7600 }
7601 }
7602 } elseif {$j >= 0} {
7603 set cmd [concat | git diff-index --cached $flags]
7604 if {[llength $ids] > 1} {
7605 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007606 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007607 lappend cmd -R [lindex $ids 1]
7608 } else {
7609 lappend cmd [lindex $ids 0]
7610 }
7611 } else {
7612 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007613 lappend cmd HEAD
7614 }
7615 } else {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007616 if {$log_showroot} {
7617 lappend flags --root
7618 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007619 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007620 }
7621 return $cmd
7622}
7623
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007624proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007625 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007626
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007627 set cmd [diffcmd $ids {--no-commit-id}]
7628 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7629 set cmd [concat $cmd -- $vfilelimit($curview)]
7630 }
7631 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007632
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007633 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007634 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007635 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007636 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007637}
7638
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007639proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007640 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007641 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007642
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007643 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007644 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007645 set max 1000
7646 if {$perfile_attrs} {
7647 # cache_gitattr is slow, and even slower on win32 where we
7648 # have to invoke it for only about 30 paths at a time
7649 set max 500
7650 if {[tk windowingsystem] == "win32"} {
7651 set max 120
7652 }
7653 }
7654 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007655 set i [string first "\t" $line]
7656 if {$i >= 0} {
7657 set file [string range $line [expr {$i+1}] end]
7658 if {[string index $file 0] eq "\""} {
7659 set file [lindex $file 0]
7660 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007661 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007662 if {$file ne [lindex $treediff end]} {
7663 lappend treediff $file
7664 lappend sublist $file
7665 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007666 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007667 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007668 if {$perfile_attrs} {
7669 cache_gitattr encoding $sublist
7670 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007671 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007672 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007673 }
7674 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007675 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007676 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007677 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007678 gettree $diffids
7679 } elseif {$ids != $diffids} {
7680 if {![info exists diffmergeid]} {
7681 gettreediffs $diffids
7682 }
7683 } else {
7684 addtocflist $ids
7685 }
7686 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007687}
7688
Steffen Prohaska890fae72007-08-12 12:05:46 +02007689# empty string or positive integer
7690proc diffcontextvalidate {v} {
7691 return [regexp {^(|[1-9][0-9]*)$} $v]
7692}
7693
7694proc diffcontextchange {n1 n2 op} {
7695 global diffcontextstring diffcontext
7696
7697 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007698 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007699 set diffcontext $diffcontextstring
7700 reselectline
7701 }
7702 }
7703}
7704
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007705proc changeignorespace {} {
7706 reselectline
7707}
7708
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007709proc changeworddiff {name ix op} {
7710 reselectline
7711}
7712
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007713proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007714 global blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007715 global diffinhdr treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007716 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007717 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007718 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007719 global limitdiffs vfilelimit curview
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007720 global diffencoding targetline diffnparents
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007721 global git_version currdiffsubmod
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007722
Paul Mackerrasa8138732009-05-16 21:06:01 +10007723 set textconv {}
7724 if {[package vcompare $git_version "1.6.1"] >= 0} {
7725 set textconv "--textconv"
7726 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01007727 set submodule {}
7728 if {[package vcompare $git_version "1.6.6"] >= 0} {
7729 set submodule "--submodule"
7730 }
7731 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007732 if {$ignorespace} {
7733 append cmd " -w"
7734 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007735 if {$worddiff ne [mc "Line diff"]} {
7736 append cmd " --word-diff=porcelain"
7737 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007738 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7739 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007740 }
7741 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007742 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007743 return
7744 }
Paul Mackerras8a897742008-10-27 21:36:25 +11007745 set targetline {}
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007746 set diffnparents 0
Paul Mackerras4f2c2642005-07-17 11:11:44 -04007747 set diffinhdr 0
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007748 set diffencoding [get_path_encoding {}]
Pat Thoyts681c3292009-03-16 10:24:40 +00007749 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007750 set blobdifffd($ids) $bdf
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007751 set currdiffsubmod ""
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007752 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007753}
7754
Paul Mackerras354af6b2008-11-23 13:14:23 +11007755proc savecmitpos {} {
7756 global ctext cmitmode
7757
7758 if {$cmitmode eq "tree"} {
7759 return {}
7760 }
7761 return [list target_scrollpos [$ctext index @0,0]]
7762}
7763
7764proc savectextpos {} {
7765 global ctext
7766
7767 return [list target_scrollpos [$ctext index @0,0]]
7768}
7769
7770proc maybe_scroll_ctext {ateof} {
7771 global ctext target_scrollpos
7772
7773 if {![info exists target_scrollpos]} return
7774 if {!$ateof} {
7775 set nlines [expr {[winfo height $ctext]
7776 / [font metrics textfont -linespace]}]
7777 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
7778 }
7779 $ctext yview $target_scrollpos
7780 unset target_scrollpos
7781}
7782
Paul Mackerras89b11d32006-05-02 19:55:31 +10007783proc setinlist {var i val} {
7784 global $var
7785
7786 while {[llength [set $var]] < $i} {
7787 lappend $var {}
7788 }
7789 if {[llength [set $var]] == $i} {
7790 lappend $var $val
7791 } else {
7792 lset $var $i $val
7793 }
7794}
7795
Paul Mackerras9396cd32007-06-23 20:28:15 +10007796proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007797 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11007798 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10007799
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007800 set fname [encoding convertfrom $fname]
7801 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007802 set i [lsearch -exact $treediffs($ids) $fname]
7803 if {$i >= 0} {
7804 setinlist difffilestart $i $curdiffstart
7805 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11007806 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10007807 set l [expr {(78 - [string length $fname]) / 2}]
7808 set pad [string range "----------------------------------------" 1 $l]
7809 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11007810 set targetline {}
7811 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
7812 set targetline [lindex $jump_to_here 1]
7813 }
7814 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007815}
7816
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007817proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007818 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04007819 global diffnexthead diffnextnote difffilestart
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007820 global ctext_file_names ctext_file_lines
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007821 global diffinhdr treediffs mergemax diffnparents
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007822 global diffencoding jump_to_here targetline diffline currdiffsubmod
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007823 global worddiff
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007824
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007825 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007826 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007827 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
7828 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10007829 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007830 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10007831 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007832 if {![string compare -length 5 "diff " $line]} {
7833 if {![regexp {^diff (--cc|--git) } $line m type]} {
7834 set line [encoding convertfrom $line]
7835 $ctext insert end "$line\n" hunksep
7836 continue
7837 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007838 # start of a new file
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007839 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007840 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10007841 set curdiffstart [$ctext index "end - 1c"]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007842 lappend ctext_file_names ""
7843 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007844 $ctext insert end "\n" filesep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007845
7846 if {$type eq "--cc"} {
7847 # start of a new file in a merge diff
7848 set fname [string range $line 10 end]
7849 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
7850 lappend treediffs($ids) $fname
7851 add_flist [list $fname]
7852 }
7853
Paul Mackerras9396cd32007-06-23 20:28:15 +10007854 } else {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007855 set line [string range $line 11 end]
7856 # If the name hasn't changed the length will be odd,
7857 # the middle char will be a space, and the two bits either
7858 # side will be a/name and b/name, or "a/name" and "b/name".
7859 # If the name has changed we'll get "rename from" and
7860 # "rename to" or "copy from" and "copy to" lines following
7861 # this, and we'll use them to get the filenames.
7862 # This complexity is necessary because spaces in the
7863 # filename(s) don't get escaped.
7864 set l [string length $line]
7865 set i [expr {$l / 2}]
7866 if {!(($l & 1) && [string index $line $i] eq " " &&
7867 [string range $line 2 [expr {$i - 1}]] eq \
7868 [string range $line [expr {$i + 3}] end])} {
7869 continue
7870 }
7871 # unescape if quoted and chop off the a/ from the front
7872 if {[string index $line 0] eq "\""} {
7873 set fname [string range [lindex $line 0] 2 end]
7874 } else {
7875 set fname [string range $line 2 [expr {$i - 1}]]
7876 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007877 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007878 makediffhdr $fname $ids
7879
Paul Mackerras48a81b72008-11-04 21:09:00 +11007880 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
7881 set fname [encoding convertfrom [string range $line 16 end]]
7882 $ctext insert end "\n"
7883 set curdiffstart [$ctext index "end - 1c"]
7884 lappend ctext_file_names $fname
7885 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7886 $ctext insert end "$line\n" filesep
7887 set i [lsearch -exact $treediffs($ids) $fname]
7888 if {$i >= 0} {
7889 setinlist difffilestart $i $curdiffstart
7890 }
7891
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007892 } elseif {![string compare -length 2 "@@" $line]} {
7893 regexp {^@@+} $line ats
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007894 set line [encoding convertfrom $diffencoding $line]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007895 $ctext insert end "$line\n" hunksep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007896 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
7897 set diffline $nl
7898 }
7899 set diffnparents [expr {[string length $ats] - 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007900 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007901
Jens Lehmann5c838d22009-10-28 12:40:45 +01007902 } elseif {![string compare -length 10 "Submodule " $line]} {
7903 # start of a new submodule
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007904 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
7905 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
7906 } else {
7907 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
7908 }
7909 if {$currdiffsubmod != $fname} {
Jens Lehmann5c838d22009-10-28 12:40:45 +01007910 $ctext insert end "\n"; # Add newline after commit message
7911 }
7912 set curdiffstart [$ctext index "end - 1c"]
7913 lappend ctext_file_names ""
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007914 if {$currdiffsubmod != $fname} {
7915 lappend ctext_file_lines $fname
7916 makediffhdr $fname $ids
7917 set currdiffsubmod $fname
7918 $ctext insert end "\n$line\n" filesep
7919 } else {
7920 $ctext insert end "$line\n" filesep
7921 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01007922 } elseif {![string compare -length 3 " >" $line]} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007923 set $currdiffsubmod ""
Kirill Smelkov1f2cecf2010-01-05 15:44:54 +03007924 set line [encoding convertfrom $diffencoding $line]
Jens Lehmann5c838d22009-10-28 12:40:45 +01007925 $ctext insert end "$line\n" dresult
7926 } elseif {![string compare -length 3 " <" $line]} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02007927 set $currdiffsubmod ""
Kirill Smelkov1f2cecf2010-01-05 15:44:54 +03007928 set line [encoding convertfrom $diffencoding $line]
Jens Lehmann5c838d22009-10-28 12:40:45 +01007929 $ctext insert end "$line\n" d0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007930 } elseif {$diffinhdr} {
Johannes Sixt5e85ec42007-10-02 16:16:54 +02007931 if {![string compare -length 12 "rename from " $line]} {
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007932 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007933 if {[string index $fname 0] eq "\""} {
7934 set fname [lindex $fname 0]
7935 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007936 set fname [encoding convertfrom $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007937 set i [lsearch -exact $treediffs($ids) $fname]
7938 if {$i >= 0} {
7939 setinlist difffilestart $i $curdiffstart
7940 }
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007941 } elseif {![string compare -length 10 $line "rename to "] ||
7942 ![string compare -length 8 $line "copy to "]} {
7943 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007944 if {[string index $fname 0] eq "\""} {
7945 set fname [lindex $fname 0]
7946 }
7947 makediffhdr $fname $ids
7948 } elseif {[string compare -length 3 $line "---"] == 0} {
7949 # do nothing
7950 continue
7951 } elseif {[string compare -length 3 $line "+++"] == 0} {
7952 set diffinhdr 0
7953 continue
7954 }
7955 $ctext insert end "$line\n" filesep
7956
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007957 } else {
Pat Thoyts681c3292009-03-16 10:24:40 +00007958 set line [string map {\x1A ^Z} \
7959 [encoding convertfrom $diffencoding $line]]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007960 # parse the prefix - one ' ', '-' or '+' for each parent
7961 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
7962 set tag [expr {$diffnparents > 1? "m": "d"}]
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007963 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
7964 set words_pre_markup ""
7965 set words_post_markup ""
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007966 if {[string trim $prefix " -+"] eq {}} {
7967 # prefix only has " ", "-" and "+" in it: normal diff line
7968 set num [string first "-" $prefix]
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007969 if {$dowords} {
7970 set line [string range $line 1 end]
7971 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007972 if {$num >= 0} {
7973 # removed line, first parent with line is $num
7974 if {$num >= $mergemax} {
7975 set num "max"
7976 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007977 if {$dowords && $worddiff eq [mc "Markup words"]} {
7978 $ctext insert end "\[-$line-\]" $tag$num
7979 } else {
7980 $ctext insert end "$line" $tag$num
7981 }
7982 if {!$dowords} {
7983 $ctext insert end "\n" $tag$num
7984 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007985 } else {
7986 set tags {}
7987 if {[string first "+" $prefix] >= 0} {
7988 # added line
7989 lappend tags ${tag}result
7990 if {$diffnparents > 1} {
7991 set num [string first " " $prefix]
7992 if {$num >= 0} {
7993 if {$num >= $mergemax} {
7994 set num "max"
7995 }
7996 lappend tags m$num
7997 }
7998 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007999 set words_pre_markup "{+"
8000 set words_post_markup "+}"
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008001 }
8002 if {$targetline ne {}} {
8003 if {$diffline == $targetline} {
8004 set seehere [$ctext index "end - 1 chars"]
8005 set targetline {}
8006 } else {
8007 incr diffline
8008 }
8009 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008010 if {$dowords && $worddiff eq [mc "Markup words"]} {
8011 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8012 } else {
8013 $ctext insert end "$line" $tags
8014 }
8015 if {!$dowords} {
8016 $ctext insert end "\n" $tags
8017 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008018 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008019 } elseif {$dowords && $prefix eq "~"} {
8020 $ctext insert end "\n" {}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008021 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10008022 # "\ No newline at end of file",
8023 # or something else we don't recognize
8024 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008025 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008026 }
8027 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008028 if {[info exists seehere]} {
8029 mark_ctext_line [lindex [split $seehere .] 0]
8030 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008031 maybe_scroll_ctext [eof $bdf]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008032 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008033 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008034 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008035 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008036 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008037 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008038}
8039
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008040proc changediffdisp {} {
8041 global ctext diffelide
8042
8043 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008044 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008045}
8046
Stefan Hallerb9671352012-09-19 20:17:27 +02008047proc highlightfile {cline} {
8048 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008049
Stefan Hallerce837c92012-10-04 22:50:16 +02008050 if {![info exists cflist_top]} return
8051
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008052 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8053 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8054 $cflist see $cline.0
8055 set cflist_top $cline
8056}
8057
Stefan Hallerb9671352012-09-19 20:17:27 +02008058proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008059 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008060
Stefan Haller978904b2012-10-04 22:50:17 +02008061 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008062 if {![info exists difffilestart]} return
8063
8064 set top [lindex [split $topidx .] 0]
8065 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
8066 highlightfile 0
8067 } else {
8068 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
8069 }
8070}
8071
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008072proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008073 global difffilestart ctext cmitmode
8074
8075 if {$cmitmode eq "tree"} return
8076 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008077 set here [$ctext index @0,0]
8078 foreach loc $difffilestart {
8079 if {[$ctext compare $loc >= $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008080 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008081 return
8082 }
8083 set prev $loc
8084 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008085 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008086}
8087
Paul Mackerras39ad8572005-05-19 12:35:53 +00008088proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008089 global difffilestart ctext cmitmode
8090
8091 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008092 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008093 foreach loc $difffilestart {
8094 if {[$ctext compare $loc > $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008095 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008096 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008097 }
8098 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008099}
8100
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008101proc clear_ctext {{first 1.0}} {
8102 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008103 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008104 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008105
Paul Mackerras1902c272006-05-25 21:25:13 +10008106 set l [lindex [split $first .] 0]
8107 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
8108 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008109 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008110 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
8111 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008112 }
8113 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008114 if {$first eq "1.0"} {
8115 catch {unset pendinglinks}
8116 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008117 set ctext_file_names {}
8118 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008119}
8120
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008121proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008122 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008123
8124 if {$firstab ne {} && $have_tk85} {
8125 set firsttabstop $firstab
8126 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008127 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008128 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10008129 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8130 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008131 } elseif {$have_tk85 || $tabstop != 8} {
8132 $ctext conf -tabs [expr {$tabstop * $w}]
8133 } else {
8134 $ctext conf -tabs {}
8135 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008136}
8137
8138proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008139 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008140
Paul Mackerras1902c272006-05-25 21:25:13 +10008141 if {[catch {$ctext index anchor}]} {
8142 # no anchor set, use start of selection, or of visible area
8143 set sel [$ctext tag ranges sel]
8144 if {$sel ne {}} {
8145 $ctext mark set anchor [lindex $sel 0]
8146 } elseif {$searchdirn eq "-forwards"} {
8147 $ctext mark set anchor @0,0
8148 } else {
8149 $ctext mark set anchor @0,[winfo height $ctext]
8150 }
8151 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008152 if {$searchstring ne {}} {
Stefan Haller30441a62012-09-22 09:40:25 +02008153 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
Paul Mackerras1902c272006-05-25 21:25:13 +10008154 if {$here ne {}} {
8155 $ctext see $here
Stefan Haller30441a62012-09-22 09:40:25 +02008156 set mend "$here + $mlen c"
8157 $ctext tag remove sel 1.0 end
8158 $ctext tag add sel $here $mend
Stefan Hallerb9671352012-09-19 20:17:27 +02008159 suppress_highlighting_file_for_current_scrollpos
8160 highlightfile_for_scrollpos $here
Paul Mackerras1902c272006-05-25 21:25:13 +10008161 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008162 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008163 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008164}
8165
8166proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008167 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008168
8169 focus $sstring
8170 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008171 set searchdirn -forwards
8172 if {$searchstring ne {}} {
8173 set sel [$ctext tag ranges sel]
8174 if {$sel ne {}} {
8175 set start "[lindex $sel 0] + 1c"
8176 } elseif {[catch {set start [$ctext index anchor]}]} {
8177 set start "@0,0"
8178 }
8179 set match [$ctext search -count mlen -- $searchstring $start]
8180 $ctext tag remove sel 1.0 end
8181 if {$match eq {}} {
8182 bell
8183 return
8184 }
8185 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008186 suppress_highlighting_file_for_current_scrollpos
8187 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008188 set mend "$match + $mlen c"
8189 $ctext tag add sel $match $mend
8190 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008191 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008192 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008193}
8194
8195proc dosearchback {} {
8196 global sstring ctext searchstring searchdirn
8197
8198 focus $sstring
8199 $sstring icursor end
8200 set searchdirn -backwards
8201 if {$searchstring ne {}} {
8202 set sel [$ctext tag ranges sel]
8203 if {$sel ne {}} {
8204 set start [lindex $sel 0]
8205 } elseif {[catch {set start [$ctext index anchor]}]} {
8206 set start @0,[winfo height $ctext]
8207 }
8208 set match [$ctext search -backwards -count ml -- $searchstring $start]
8209 $ctext tag remove sel 1.0 end
8210 if {$match eq {}} {
8211 bell
8212 return
8213 }
8214 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008215 suppress_highlighting_file_for_current_scrollpos
8216 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008217 set mend "$match + $ml c"
8218 $ctext tag add sel $match $mend
8219 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008220 rehighlight_search_results
8221 }
8222}
8223
8224proc rehighlight_search_results {} {
8225 global ctext searchstring
8226
8227 $ctext tag remove found 1.0 end
8228 $ctext tag remove currentsearchhit 1.0 end
8229
8230 if {$searchstring ne {}} {
8231 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008232 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008233}
8234
8235proc searchmark {first last} {
8236 global ctext searchstring
8237
Stefan Hallerc4614992012-09-22 09:40:24 +02008238 set sel [$ctext tag ranges sel]
8239
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008240 set mend $first.0
8241 while {1} {
8242 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8243 if {$match eq {}} break
8244 set mend "$match + $mlen c"
Stefan Hallerc4614992012-09-22 09:40:24 +02008245 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8246 $ctext tag add currentsearchhit $match $mend
8247 } else {
8248 $ctext tag add found $match $mend
8249 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008250 }
8251}
8252
8253proc searchmarkvisible {doall} {
8254 global ctext smarktop smarkbot
8255
8256 set topline [lindex [split [$ctext index @0,0] .] 0]
8257 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8258 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
8259 # no overlap with previous
8260 searchmark $topline $botline
8261 set smarktop $topline
8262 set smarkbot $botline
8263 } else {
8264 if {$topline < $smarktop} {
8265 searchmark $topline [expr {$smarktop-1}]
8266 set smarktop $topline
8267 }
8268 if {$botline > $smarkbot} {
8269 searchmark [expr {$smarkbot+1}] $botline
8270 set smarkbot $botline
8271 }
8272 }
8273}
8274
Stefan Hallerb9671352012-09-19 20:17:27 +02008275proc suppress_highlighting_file_for_current_scrollpos {} {
8276 global ctext suppress_highlighting_file_for_this_scrollpos
8277
8278 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8279}
8280
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008281proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008282 global searchstring cmitmode ctext
8283 global suppress_highlighting_file_for_this_scrollpos
8284
Stefan Haller978904b2012-10-04 22:50:17 +02008285 set topidx [$ctext index @0,0]
8286 if {![info exists suppress_highlighting_file_for_this_scrollpos]
8287 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8288 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008289 }
8290
8291 catch {unset suppress_highlighting_file_for_this_scrollpos}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008292
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008293 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008294 if {$searchstring ne {}} {
8295 searchmarkvisible 0
8296 }
8297}
8298
Paul Mackerras1d10f362005-05-15 12:55:47 +00008299proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008300 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008301 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008302
Paul Mackerras9c311b32007-10-04 22:27:13 +10008303 set linespc [font metrics mainfont -linespace]
8304 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008305 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8306 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008307 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008308 set xspc1(0) $linespc
8309 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008310}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008311
Paul Mackerras1d10f362005-05-15 12:55:47 +00008312proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008313 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008314 global selectedline
8315
8316 set ymax [lindex [$canv cget -scrollregion] 3]
8317 if {$ymax eq {} || $ymax == 0} return
8318 set span [$canv yview]
8319 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008320 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008321 allcanvs yview moveto [lindex $span 0]
8322 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008323 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008324 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008325 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008326 }
8327}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008328
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008329proc parsefont {f n} {
8330 global fontattr
8331
8332 set fontattr($f,family) [lindex $n 0]
8333 set s [lindex $n 1]
8334 if {$s eq {} || $s == 0} {
8335 set s 10
8336 } elseif {$s < 0} {
8337 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008338 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008339 set fontattr($f,size) $s
8340 set fontattr($f,weight) normal
8341 set fontattr($f,slant) roman
8342 foreach style [lrange $n 2 end] {
8343 switch -- $style {
8344 "normal" -
8345 "bold" {set fontattr($f,weight) $style}
8346 "roman" -
8347 "italic" {set fontattr($f,slant) $style}
8348 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008349 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008350}
8351
8352proc fontflags {f {isbold 0}} {
8353 global fontattr
8354
8355 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
8356 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8357 -slant $fontattr($f,slant)]
8358}
8359
8360proc fontname {f} {
8361 global fontattr
8362
8363 set n [list $fontattr($f,family) $fontattr($f,size)]
8364 if {$fontattr($f,weight) eq "bold"} {
8365 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008366 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008367 if {$fontattr($f,slant) eq "italic"} {
8368 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008369 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008370 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008371}
8372
Paul Mackerras1d10f362005-05-15 12:55:47 +00008373proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008374 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008375 global stopped entries fontattr
8376
Paul Mackerras1d10f362005-05-15 12:55:47 +00008377 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008378 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008379 incr s $inc
8380 if {$s < 1} {
8381 set s 1
8382 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008383 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008384 font config mainfont -size $s
8385 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008386 set mainfont [fontname mainfont]
8387 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008388 incr s $inc
8389 if {$s < 1} {
8390 set s 1
8391 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008392 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008393 font config textfont -size $s
8394 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008395 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008396 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008397 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008398 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008399}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008400
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008401proc clearsha1 {} {
8402 global sha1entry sha1string
8403 if {[string length $sha1string] == 40} {
8404 $sha1entry delete 0 end
8405 }
8406}
8407
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008408proc sha1change {n1 n2 op} {
8409 global sha1string currentid sha1but
8410 if {$sha1string == {}
8411 || ([info exists currentid] && $sha1string == $currentid)} {
8412 set state disabled
8413 } else {
8414 set state normal
8415 }
8416 if {[$sha1but cget -state] == $state} return
8417 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008418 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008419 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008420 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008421 }
8422}
8423
8424proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008425 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008426
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008427 if {$sha1string == {}
8428 || ([info exists currentid] && $sha1string == $currentid)} return
8429 if {[info exists tagids($sha1string)]} {
8430 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008431 } elseif {[info exists headids($sha1string)]} {
8432 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008433 } else {
8434 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008435 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008436 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008437 if {$matches ne {}} {
8438 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008439 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008440 return
8441 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008442 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008443 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008444 } else {
8445 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8446 error_popup [mc "Revision %s is not known" $sha1string]
8447 return
8448 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008449 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008450 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008451 if {[commitinview $id $curview]} {
8452 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008453 return
8454 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008455 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008456 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008457 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008458 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008459 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008460 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008461}
8462
Paul Mackerras84ba7342005-06-17 00:12:26 +00008463proc lineenter {x y id} {
8464 global hoverx hovery hoverid hovertimer
8465 global commitinfo canv
8466
Paul Mackerras8ed16482006-03-02 22:56:44 +11008467 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008468 set hoverx $x
8469 set hovery $y
8470 set hoverid $id
8471 if {[info exists hovertimer]} {
8472 after cancel $hovertimer
8473 }
8474 set hovertimer [after 500 linehover]
8475 $canv delete hover
8476}
8477
8478proc linemotion {x y id} {
8479 global hoverx hovery hoverid hovertimer
8480
8481 if {[info exists hoverid] && $id == $hoverid} {
8482 set hoverx $x
8483 set hovery $y
8484 if {[info exists hovertimer]} {
8485 after cancel $hovertimer
8486 }
8487 set hovertimer [after 500 linehover]
8488 }
8489}
8490
8491proc lineleave {id} {
8492 global hoverid hovertimer canv
8493
8494 if {[info exists hoverid] && $id == $hoverid} {
8495 $canv delete hover
8496 if {[info exists hovertimer]} {
8497 after cancel $hovertimer
8498 unset hovertimer
8499 }
8500 unset hoverid
8501 }
8502}
8503
8504proc linehover {} {
8505 global hoverx hovery hoverid hovertimer
8506 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008507 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8508
Paul Mackerras9c311b32007-10-04 22:27:13 +10008509 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008510
8511 set text [lindex $commitinfo($hoverid) 0]
8512 set ymax [lindex [$canv cget -scrollregion] 3]
8513 if {$ymax == {}} return
8514 set yfrac [lindex [$canv yview] 0]
8515 set x [expr {$hoverx + 2 * $linespc}]
8516 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8517 set x0 [expr {$x - 2 * $lthickness}]
8518 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008519 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008520 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8521 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008522 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8523 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008524 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008525 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008526 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008527 $canv raise $t
8528}
8529
Paul Mackerras9843c302005-08-30 10:57:11 +10008530proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008531 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008532
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008533 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008534 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008535 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008536 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008537 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008538 if {abs([yc $row] - $y) < $thresh} {
8539 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008540 }
8541 }
8542 return {}
8543}
8544
Paul Mackerrasf6342482006-02-28 10:02:03 +11008545proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008546 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008547
Paul Mackerrasf6342482006-02-28 10:02:03 +11008548 # 1 <-> 2, 3 <-> 4, etc...
8549 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008550 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008551 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008552 set ymax [lindex [$canv cget -scrollregion] 3]
8553 if {$ymax eq {} || $ymax <= 0} return
8554 set view [$canv yview]
8555 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8556 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8557 if {$yfrac < 0} {
8558 set yfrac 0
8559 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008560 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008561}
8562
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008563proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008564 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008565
Paul Mackerras8ed16482006-03-02 22:56:44 +11008566 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008567 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008568 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008569 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008570 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008571 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008572 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008573 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008574 if {$isnew} {
8575 set ymax [lindex [$canv cget -scrollregion] 3]
8576 if {$ymax eq {}} return
8577 set yfrac [lindex [$canv yview] 0]
8578 set y [expr {$y + $yfrac * $ymax}]
8579 }
8580 set dirn [clickisonarrow $id $y]
8581 if {$dirn ne {}} {
8582 arrowjump $id $dirn $y
8583 return
8584 }
8585
8586 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008587 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008588 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008589 # fill the details pane with info about this line
8590 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008591 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008592 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008593 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008594 $ctext insert end $id link0
8595 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008596 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008597 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008598 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008599 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008600 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008601 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008602 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008603 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008604 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008605 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008606 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008607 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008608 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008609 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008610 $ctext insert end $child link$i
8611 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008612 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008613 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008614 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008615 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008616 }
8617 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008618 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008619 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008620 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008621}
8622
Paul Mackerras9843c302005-08-30 10:57:11 +10008623proc normalline {} {
8624 global thickerline
8625 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008626 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008627 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008628 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008629 }
8630}
8631
Paul Mackerras354af6b2008-11-23 13:14:23 +11008632proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008633 global curview
8634 if {[commitinview $id $curview]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008635 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008636 }
8637}
8638
8639proc mstime {} {
8640 global startmstime
8641 if {![info exists startmstime]} {
8642 set startmstime [clock clicks -milliseconds]
8643 }
8644 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8645}
8646
8647proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008648 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008649 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008650
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008651 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008652 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008653 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008654 set state disabled
8655 } else {
8656 set state normal
8657 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008658 if {[info exists markedid] && $markedid ne $id} {
8659 set mstate normal
8660 } else {
8661 set mstate disabled
8662 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008663 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008664 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008665 if {$mainhead ne {}} {
Johannes Sixtda12e592008-12-03 13:43:20 +01008666 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008667 } else {
8668 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
8669 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008670 $menu entryconfigure 9 -state $mstate
8671 $menu entryconfigure 10 -state $mstate
8672 $menu entryconfigure 11 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008673 } else {
8674 set menu $fakerowmenu
8675 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008676 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8677 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8678 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11008679 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
8680 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008681 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008682}
8683
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008684proc markhere {} {
8685 global rowmenuid markedid canv
8686
8687 set markedid $rowmenuid
8688 make_idmark $markedid
8689}
8690
8691proc gotomark {} {
8692 global markedid
8693
8694 if {[info exists markedid]} {
8695 selbyid $markedid
8696 }
8697}
8698
8699proc replace_by_kids {l r} {
8700 global curview children
8701
8702 set id [commitonrow $r]
8703 set l [lreplace $l 0 0]
8704 foreach kid $children($curview,$id) {
8705 lappend l [rowofcommit $kid]
8706 }
8707 return [lsort -integer -decreasing -unique $l]
8708}
8709
8710proc find_common_desc {} {
8711 global markedid rowmenuid curview children
8712
8713 if {![info exists markedid]} return
8714 if {![commitinview $markedid $curview] ||
8715 ![commitinview $rowmenuid $curview]} return
8716 #set t1 [clock clicks -milliseconds]
8717 set l1 [list [rowofcommit $markedid]]
8718 set l2 [list [rowofcommit $rowmenuid]]
8719 while 1 {
8720 set r1 [lindex $l1 0]
8721 set r2 [lindex $l2 0]
8722 if {$r1 eq {} || $r2 eq {}} break
8723 if {$r1 == $r2} {
8724 selectline $r1 1
8725 break
8726 }
8727 if {$r1 > $r2} {
8728 set l1 [replace_by_kids $l1 $r1]
8729 } else {
8730 set l2 [replace_by_kids $l2 $r2]
8731 }
8732 }
8733 #set t2 [clock clicks -milliseconds]
8734 #puts "took [expr {$t2-$t1}]ms"
8735}
8736
Paul Mackerras010509f2009-04-09 22:10:20 +10008737proc compare_commits {} {
8738 global markedid rowmenuid curview children
8739
8740 if {![info exists markedid]} return
8741 if {![commitinview $markedid $curview]} return
8742 addtohistory [list do_cmp_commits $markedid $rowmenuid]
8743 do_cmp_commits $markedid $rowmenuid
8744}
8745
8746proc getpatchid {id} {
8747 global patchids
8748
8749 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008750 set cmd [diffcmd [list $id] {-p --root}]
8751 # trim off the initial "|"
8752 set cmd [lrange $cmd 1 end]
8753 if {[catch {
8754 set x [eval exec $cmd | git patch-id]
8755 set patchids($id) [lindex $x 0]
8756 }]} {
8757 set patchids($id) "error"
8758 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008759 }
8760 return $patchids($id)
8761}
8762
8763proc do_cmp_commits {a b} {
8764 global ctext curview parents children patchids commitinfo
8765
8766 $ctext conf -state normal
8767 clear_ctext
8768 init_flist {}
8769 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10008770 set skipa 0
8771 set skipb 0
8772 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008773 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008774 set skipa 1
8775 } else {
8776 set patcha [getpatchid $a]
8777 }
8778 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008779 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008780 set skipb 1
8781 } else {
8782 set patchb [getpatchid $b]
8783 }
8784 if {!$skipa && !$skipb} {
8785 set heada [lindex $commitinfo($a) 0]
8786 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008787 if {$patcha eq "error"} {
8788 appendshortlink $a [mc "Error getting patch ID for "] \
8789 [mc " - stopping\n"]
8790 break
8791 }
8792 if {$patchb eq "error"} {
8793 appendshortlink $b [mc "Error getting patch ID for "] \
8794 [mc " - stopping\n"]
8795 break
8796 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008797 if {$patcha eq $patchb} {
8798 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008799 appendshortlink $a [mc "Commit "]
8800 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008801 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008802 appendshortlink $a [mc "Commit "] " $heada\n"
8803 appendshortlink $b [mc " is the same patch as\n "] \
8804 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008805 }
8806 set skipa 1
8807 set skipb 1
8808 } else {
8809 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008810 appendshortlink $a [mc "Commit "] " $heada\n"
8811 appendshortlink $b [mc " differs from\n "] \
8812 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008813 $ctext insert end [mc "Diff of commits:\n\n"]
8814 $ctext conf -state disabled
8815 update
8816 diffcommits $a $b
8817 return
Paul Mackerras010509f2009-04-09 22:10:20 +10008818 }
8819 }
8820 if {$skipa} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10008821 set kids [real_children $curview,$a]
8822 if {[llength $kids] != 1} {
Paul Mackerras010509f2009-04-09 22:10:20 +10008823 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008824 appendshortlink $a [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10008825 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10008826 break
8827 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10008828 set a [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10008829 }
8830 if {$skipb} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10008831 set kids [real_children $curview,$b]
8832 if {[llength $kids] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008833 appendshortlink $b [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10008834 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10008835 break
8836 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10008837 set b [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10008838 }
8839 }
8840 $ctext conf -state disabled
8841}
8842
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008843proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02008844 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008845
8846 set tmpdir [gitknewtmpdir]
8847 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
8848 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
8849 if {[catch {
8850 exec git diff-tree -p --pretty $a >$fna
8851 exec git diff-tree -p --pretty $b >$fnb
8852 } err]} {
8853 error_popup [mc "Error writing commit to file: %s" $err]
8854 return
8855 }
8856 if {[catch {
8857 set fd [open "| diff -U$diffcontext $fna $fnb" r]
8858 } err]} {
8859 error_popup [mc "Error diffing commits: %s" $err]
8860 return
8861 }
8862 set diffids [list commits $a $b]
8863 set blobdifffd($diffids) $fd
8864 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02008865 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008866 filerun $fd [list getblobdiffline $fd $diffids]
8867}
8868
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008869proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008870 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008871
Paul Mackerras94b4a692008-05-20 20:51:06 +10008872 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008873 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008874 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008875 set newid $rowmenuid
8876 } else {
8877 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008878 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008879 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008880 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008881 doseldiff $oldid $newid
8882}
8883
Paul Mackerras6febded2012-03-23 22:07:27 +11008884proc diffvsmark {dirn} {
8885 global rowmenuid markedid
8886
8887 if {![info exists markedid]} return
8888 if {$dirn} {
8889 set oldid $markedid
8890 set newid $rowmenuid
8891 } else {
8892 set oldid $rowmenuid
8893 set newid $markedid
8894 }
8895 addtohistory [list doseldiff $oldid $newid] savectextpos
8896 doseldiff $oldid $newid
8897}
8898
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008899proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008900 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008901 global commitinfo
8902
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008903 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008904 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01008905 init_flist [mc "Top"]
8906 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008907 $ctext insert end $oldid link0
8908 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008909 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008910 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008911 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008912 $ctext insert end $newid link1
8913 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008914 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008915 $ctext insert end [lindex $commitinfo($newid) 0]
8916 $ctext insert end "\n"
8917 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008918 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11008919 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008920}
8921
Paul Mackerras74daedb2005-06-27 19:27:32 +10008922proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01008923 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10008924
8925 if {![info exists currentid]} return
8926 set oldid $currentid
8927 set oldhead [lindex $commitinfo($oldid) 0]
8928 set newid $rowmenuid
8929 set newhead [lindex $commitinfo($newid) 0]
8930 set top .patch
8931 set patchtop $top
8932 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01008933 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008934 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01008935 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008936 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01008937 ${NS}::label $top.from -text [mc "From:"]
8938 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10008939 $top.fromsha1 insert 0 $oldid
8940 $top.fromsha1 conf -state readonly
8941 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01008942 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10008943 $top.fromhead insert 0 $oldhead
8944 $top.fromhead conf -state readonly
8945 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01008946 ${NS}::label $top.to -text [mc "To:"]
8947 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10008948 $top.tosha1 insert 0 $newid
8949 $top.tosha1 conf -state readonly
8950 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01008951 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10008952 $top.tohead insert 0 $newhead
8953 $top.tohead conf -state readonly
8954 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01008955 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
8956 grid $top.rev x -pady 10 -padx 5
8957 ${NS}::label $top.flab -text [mc "Output file:"]
8958 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10008959 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
8960 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008961 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01008962 ${NS}::frame $top.buts
8963 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
8964 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008965 bind $top <Key-Return> mkpatchgo
8966 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10008967 grid $top.buts.gen $top.buts.can
8968 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8969 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8970 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008971 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10008972}
8973
8974proc mkpatchrev {} {
8975 global patchtop
8976
8977 set oldid [$patchtop.fromsha1 get]
8978 set oldhead [$patchtop.fromhead get]
8979 set newid [$patchtop.tosha1 get]
8980 set newhead [$patchtop.tohead get]
8981 foreach e [list fromsha1 fromhead tosha1 tohead] \
8982 v [list $newid $newhead $oldid $oldhead] {
8983 $patchtop.$e conf -state normal
8984 $patchtop.$e delete 0 end
8985 $patchtop.$e insert 0 $v
8986 $patchtop.$e conf -state readonly
8987 }
8988}
8989
8990proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10008991 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10008992
8993 set oldid [$patchtop.fromsha1 get]
8994 set newid [$patchtop.tosha1 get]
8995 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10008996 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10008997 # trim off the initial "|"
8998 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008999 lappend cmd >$fname &
9000 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009001 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009002 }
9003 catch {destroy $patchtop}
9004 unset patchtop
9005}
9006
9007proc mkpatchcan {} {
9008 global patchtop
9009
9010 catch {destroy $patchtop}
9011 unset patchtop
9012}
9013
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009014proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009015 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009016
9017 set top .maketag
9018 set mktagtop $top
9019 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009020 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009021 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009022 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009023 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009024 ${NS}::label $top.id -text [mc "ID:"]
9025 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009026 $top.sha1 insert 0 $rowmenuid
9027 $top.sha1 conf -state readonly
9028 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009029 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009030 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9031 $top.head conf -state readonly
9032 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009033 ${NS}::label $top.tlab -text [mc "Tag name:"]
9034 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009035 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009036 ${NS}::label $top.op -text [mc "Tag message is optional"]
9037 grid $top.op -columnspan 2 -sticky we
9038 ${NS}::label $top.mlab -text [mc "Tag message:"]
9039 ${NS}::entry $top.msg -width 60
9040 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009041 ${NS}::frame $top.buts
9042 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9043 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009044 bind $top <Key-Return> mktaggo
9045 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009046 grid $top.buts.gen $top.buts.can
9047 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9048 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9049 grid $top.buts - -pady 10 -sticky ew
9050 focus $top.tag
9051}
9052
9053proc domktag {} {
9054 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009055
9056 set id [$mktagtop.sha1 get]
9057 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009058 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009059 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009060 error_popup [mc "No tag name specified"] $mktagtop
9061 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009062 }
9063 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009064 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9065 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009066 }
9067 if {[catch {
Dave Dulsondfb891e2010-01-03 14:55:52 +00009068 if {$msg != {}} {
9069 exec git tag -a -m $msg $tag $id
9070 } else {
9071 exec git tag $tag $id
9072 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009073 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009074 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9075 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009076 }
9077
9078 set tagids($tag) $id
9079 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009080 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009081 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009082 dispneartags 0
9083 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009084 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009085}
9086
9087proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009088 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009089 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009090 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009091
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009092 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009093 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009094 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009095 if {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009096 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009097 } else {
9098 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
9099 }
9100 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009101 $canv delete tag.$id
9102 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009103 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9104 set text [$canv itemcget $linehtag($id) -text]
9105 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009106 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009107 if {$xr > $canvxmax} {
9108 set canvxmax $xr
9109 setcanvscroll
9110 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009111 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11009112 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009113 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009114 if {[info exists markedid] && $markedid eq $id} {
9115 make_idmark $id
9116 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009117}
9118
9119proc mktagcan {} {
9120 global mktagtop
9121
9122 catch {destroy $mktagtop}
9123 unset mktagtop
9124}
9125
9126proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009127 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009128 mktagcan
9129}
9130
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009131proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009132 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009133
9134 set top .writecommit
9135 set wrcomtop $top
9136 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009137 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009138 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009139 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009140 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009141 ${NS}::label $top.id -text [mc "ID:"]
9142 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009143 $top.sha1 insert 0 $rowmenuid
9144 $top.sha1 conf -state readonly
9145 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009146 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009147 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9148 $top.head conf -state readonly
9149 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009150 ${NS}::label $top.clab -text [mc "Command:"]
9151 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009152 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009153 ${NS}::label $top.flab -text [mc "Output file:"]
9154 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009155 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9156 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009157 ${NS}::frame $top.buts
9158 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9159 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009160 bind $top <Key-Return> wrcomgo
9161 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009162 grid $top.buts.gen $top.buts.can
9163 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9164 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9165 grid $top.buts - -pady 10 -sticky ew
9166 focus $top.fname
9167}
9168
9169proc wrcomgo {} {
9170 global wrcomtop
9171
9172 set id [$wrcomtop.sha1 get]
9173 set cmd "echo $id | [$wrcomtop.cmd get]"
9174 set fname [$wrcomtop.fname get]
9175 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009176 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009177 }
9178 catch {destroy $wrcomtop}
9179 unset wrcomtop
9180}
9181
9182proc wrcomcan {} {
9183 global wrcomtop
9184
9185 catch {destroy $wrcomtop}
9186 unset wrcomtop
9187}
9188
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009189proc mkbranch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009190 global rowmenuid mkbrtop NS
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009191
9192 set top .makebranch
9193 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009194 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009195 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009196 ${NS}::label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009197 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009198 ${NS}::label $top.id -text [mc "ID:"]
9199 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009200 $top.sha1 insert 0 $rowmenuid
9201 $top.sha1 conf -state readonly
9202 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009203 ${NS}::label $top.nlab -text [mc "Name:"]
9204 ${NS}::entry $top.name -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009205 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009206 ${NS}::frame $top.buts
9207 ${NS}::button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
9208 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009209 bind $top <Key-Return> [list mkbrgo $top]
9210 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009211 grid $top.buts.go $top.buts.can
9212 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9213 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9214 grid $top.buts - -pady 10 -sticky ew
9215 focus $top.name
9216}
9217
9218proc mkbrgo {top} {
9219 global headids idheads
9220
9221 set name [$top.name get]
9222 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009223 set cmdargs {}
9224 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009225 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009226 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009227 return
9228 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009229 if {[info exists headids($name)]} {
9230 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009231 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009232 return
9233 }
9234 set old_id $headids($name)
9235 lappend cmdargs -f
9236 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009237 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009238 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009239 nowbusy newbranch
9240 update
9241 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009242 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009243 } err]} {
9244 notbusy newbranch
9245 error_popup $err
9246 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009247 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009248 if {$old_id ne {}} {
9249 movehead $id $name
9250 movedhead $id $name
9251 redrawtags $old_id
9252 redrawtags $id
9253 } else {
9254 set headids($name) $id
9255 lappend idheads($id) $name
9256 addedhead $id $name
9257 redrawtags $id
9258 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009259 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009260 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009261 }
9262}
9263
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009264proc exec_citool {tool_args {baseid {}}} {
9265 global commitinfo env
9266
9267 set save_env [array get env GIT_AUTHOR_*]
9268
9269 if {$baseid ne {}} {
9270 if {![info exists commitinfo($baseid)]} {
9271 getcommit $baseid
9272 }
9273 set author [lindex $commitinfo($baseid) 1]
9274 set date [lindex $commitinfo($baseid) 2]
9275 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9276 $author author name email]
9277 && $date ne {}} {
9278 set env(GIT_AUTHOR_NAME) $name
9279 set env(GIT_AUTHOR_EMAIL) $email
9280 set env(GIT_AUTHOR_DATE) $date
9281 }
9282 }
9283
9284 eval exec git citool $tool_args &
9285
9286 array unset env GIT_AUTHOR_*
9287 array set env $save_env
9288}
9289
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009290proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009291 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009292 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009293 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009294
Paul Mackerrase11f1232007-06-16 20:29:25 +10009295 set oldhead [exec git rev-parse HEAD]
9296 set dheads [descheads $rowmenuid]
9297 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009298 set ok [confirm_popup [mc "Commit %s is already\
9299 included in branch %s -- really re-apply it?" \
9300 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009301 if {!$ok} return
9302 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009303 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009304 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009305 # Unfortunately git-cherry-pick writes stuff to stderr even when
9306 # no error occurs, and exec takes that as an indication of error...
9307 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
9308 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009309 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11009310 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9311 $err msg fname]} {
9312 error_popup [mc "Cherry-pick failed because of local changes\
9313 to file '%s'.\nPlease commit, reset or stash\
9314 your changes and try again." $fname]
9315 } elseif {[regexp -line \
Anders Kaseorgb74307f2011-01-19 14:45:00 -05009316 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
Paul Mackerras887a7912008-11-08 21:37:09 +11009317 $err]} {
9318 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9319 conflict.\nDo you wish to run git citool to\
9320 resolve it?"]]} {
9321 # Force citool to read MERGE_MSG
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009322 file delete [file join $gitdir "GITGUI_MSG"]
Paul Mackerras887a7912008-11-08 21:37:09 +11009323 exec_citool {} $rowmenuid
9324 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009325 } else {
9326 error_popup $err
9327 }
Paul Mackerras887a7912008-11-08 21:37:09 +11009328 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009329 return
9330 }
9331 set newhead [exec git rev-parse HEAD]
9332 if {$newhead eq $oldhead} {
9333 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01009334 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009335 return
9336 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009337 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009338 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11009339 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009340 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009341 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009342 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009343 movedhead $newhead $mainhead
9344 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009345 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009346 redrawtags $oldhead
9347 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11009348 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009349 }
9350 notbusy cherrypick
9351}
9352
Knut Franke8f3ff932013-04-27 16:36:13 +02009353proc revert {} {
9354 global rowmenuid curview
9355 global mainhead mainheadid
9356 global gitdir
9357
9358 set oldhead [exec git rev-parse HEAD]
9359 set dheads [descheads $rowmenuid]
9360 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9361 set ok [confirm_popup [mc "Commit %s is not\
9362 included in branch %s -- really revert it?" \
9363 [string range $rowmenuid 0 7] $mainhead]]
9364 if {!$ok} return
9365 }
9366 nowbusy revert [mc "Reverting"]
9367 update
9368
9369 if [catch {exec git revert --no-edit $rowmenuid} err] {
9370 notbusy revert
9371 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9372 $err match files] {
9373 regsub {\n( |\t)+} $files "\n" files
9374 error_popup [mc "Revert failed because of local changes to\
9375 the following files:%s Please commit, reset or stash \
9376 your changes and try again." $files]
9377 } elseif [regexp {error: could not revert} $err] {
9378 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9379 Do you wish to run git citool to resolve it?"]] {
9380 # Force citool to read MERGE_MSG
9381 file delete [file join $gitdir "GITGUI_MSG"]
9382 exec_citool {} $rowmenuid
9383 }
9384 } else { error_popup $err }
9385 run updatecommits
9386 return
9387 }
9388
9389 set newhead [exec git rev-parse HEAD]
9390 if { $newhead eq $oldhead } {
9391 notbusy revert
9392 error_popup [mc "No changes committed"]
9393 return
9394 }
9395
9396 addnewchild $newhead $oldhead
9397
9398 if [commitinview $oldhead $curview] {
9399 # XXX this isn't right if we have a path limit...
9400 insertrow $newhead $oldhead $curview
9401 if {$mainhead ne {}} {
9402 movehead $newhead $mainhead
9403 movedhead $newhead $mainhead
9404 }
9405 set mainheadid $newhead
9406 redrawtags $oldhead
9407 redrawtags $newhead
9408 selbyid $newhead
9409 }
9410
9411 notbusy revert
9412}
9413
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009414proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009415 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009416
9417 set confirm_ok 0
9418 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009419 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009420 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009421 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009422 ${NS}::label $w.m -text \
9423 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009424 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009425 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009426 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009427 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009428 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009429 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009430 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009431 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009432 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009433 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009434 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009435 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009436 pack $w.f -side top -fill x -padx 4
9437 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009438 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009439 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009440 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009441 pack $w.cancel -side right -fill x -padx 20 -pady 20
9442 bind $w <Visibility> "grab $w; focus $w"
9443 tkwait window $w
9444 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009445 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10009446 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009447 error_popup $err
9448 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009449 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10009450 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009451 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11009452 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009453 }
9454}
9455
Paul Mackerrasa137a902007-10-23 21:12:49 +10009456proc readresetstat {fd} {
9457 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009458
9459 if {[gets $fd line] >= 0} {
9460 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10009461 set rprogcoord [expr {1.0 * $m / $n}]
9462 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009463 }
9464 return 1
9465 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009466 set rprogcoord 0
9467 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009468 notbusy reset
9469 if {[catch {close $fd} err]} {
9470 error_popup $err
9471 }
9472 set oldhead $mainheadid
9473 set newhead [exec git rev-parse HEAD]
9474 if {$newhead ne $oldhead} {
9475 movehead $newhead $mainhead
9476 movedhead $newhead $mainhead
9477 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009478 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10009479 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009480 }
9481 if {$showlocalchanges} {
9482 doshowlocalchanges
9483 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009484 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009485}
9486
Paul Mackerras10299152006-08-02 09:52:01 +10009487# context menu for a head
9488proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10009489 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10009490
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009491 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009492 set headmenuid $id
9493 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10009494 set state normal
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309495 if {[string match "remotes/*" $head]} {
9496 set state disabled
9497 }
Paul Mackerras00609462007-06-17 17:08:35 +10009498 if {$head eq $mainhead} {
9499 set state disabled
9500 }
9501 $headctxmenu entryconfigure 0 -state $state
9502 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10009503 tk_popup $headctxmenu $x $y
9504}
9505
9506proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009507 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009508 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009509
9510 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01009511 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009512 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009513 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009514 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10009515 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10009516 } err]} {
9517 notbusy checkout
9518 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10009519 if {$showlocalchanges} {
9520 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009521 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009522 } else {
9523 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009524 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009525}
9526
9527proc readcheckoutstat {fd newhead newheadid} {
9528 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009529 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009530
9531 if {[gets $fd line] >= 0} {
9532 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9533 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9534 adjustprogress
9535 }
9536 return 1
9537 }
9538 set progresscoords {0 0}
9539 adjustprogress
9540 notbusy checkout
9541 if {[catch {close $fd} err]} {
9542 error_popup $err
9543 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009544 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009545 set mainhead $newhead
9546 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11009547 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009548 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009549 redrawtags $newheadid
9550 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009551 if {$showlocalchanges} {
9552 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009553 }
9554}
9555
9556proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009557 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10009558 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10009559
9560 set head $headmenuhead
9561 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10009562 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10009563 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009564 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10009565 return
9566 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009567 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10009568 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10009569 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01009570 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
9571 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10009572 }
9573 nowbusy rmbranch
9574 update
9575 if {[catch {exec git branch -D $head} err]} {
9576 notbusy rmbranch
9577 error_popup $err
9578 return
9579 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009580 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009581 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10009582 redrawtags $id
9583 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10009584 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009585 run refill_reflist
9586}
9587
9588# Display a list of tags and heads
9589proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009590 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +10009591 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10009592
9593 set top .showrefs
9594 set showrefstop $top
9595 if {[winfo exists $top]} {
9596 raise $top
9597 refill_reflist
9598 return
9599 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009600 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009601 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009602 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10009603 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10009604 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10009605 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
9606 -width 30 -height 20 -cursor $maincursor \
9607 -spacing1 1 -spacing3 1 -state disabled
9608 $top.list tag configure highlight -background $selectbgcolor
9609 lappend bglist $top.list
9610 lappend fglist $top.list
Pat Thoytsd93f1712009-04-17 01:24:35 +01009611 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
9612 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +10009613 grid $top.list $top.ysb -sticky nsew
9614 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +01009615 ${NS}::frame $top.f
9616 ${NS}::label $top.f.l -text "[mc "Filter"]: "
9617 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009618 set reflistfilter "*"
9619 trace add variable reflistfilter write reflistfilter_change
9620 pack $top.f.e -side right -fill x -expand 1
9621 pack $top.f.l -side left
9622 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01009623 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009624 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10009625 grid $top.close -
9626 grid columnconfigure $top 0 -weight 1
9627 grid rowconfigure $top 0 -weight 1
9628 bind $top.list <1> {break}
9629 bind $top.list <B1-Motion> {break}
9630 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
9631 set reflist {}
9632 refill_reflist
9633}
9634
9635proc sel_reflist {w x y} {
9636 global showrefstop reflist headids tagids otherrefids
9637
9638 if {![winfo exists $showrefstop]} return
9639 set l [lindex [split [$w index "@$x,$y"] "."] 0]
9640 set ref [lindex $reflist [expr {$l-1}]]
9641 set n [lindex $ref 0]
9642 switch -- [lindex $ref 1] {
9643 "H" {selbyid $headids($n)}
9644 "T" {selbyid $tagids($n)}
9645 "o" {selbyid $otherrefids($n)}
9646 }
9647 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
9648}
9649
9650proc unsel_reflist {} {
9651 global showrefstop
9652
9653 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9654 $showrefstop.list tag remove highlight 0.0 end
9655}
9656
9657proc reflistfilter_change {n1 n2 op} {
9658 global reflistfilter
9659
9660 after cancel refill_reflist
9661 after 200 refill_reflist
9662}
9663
9664proc refill_reflist {} {
9665 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009666 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10009667
9668 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9669 set refs {}
9670 foreach n [array names headids] {
9671 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009672 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009673 lappend refs [list $n H]
9674 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009675 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009676 }
9677 }
9678 }
9679 foreach n [array names tagids] {
9680 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009681 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009682 lappend refs [list $n T]
9683 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009684 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009685 }
9686 }
9687 }
9688 foreach n [array names otherrefids] {
9689 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009690 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009691 lappend refs [list $n o]
9692 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009693 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009694 }
9695 }
9696 }
9697 set refs [lsort -index 0 $refs]
9698 if {$refs eq $reflist} return
9699
9700 # Update the contents of $showrefstop.list according to the
9701 # differences between $reflist (old) and $refs (new)
9702 $showrefstop.list conf -state normal
9703 $showrefstop.list insert end "\n"
9704 set i 0
9705 set j 0
9706 while {$i < [llength $reflist] || $j < [llength $refs]} {
9707 if {$i < [llength $reflist]} {
9708 if {$j < [llength $refs]} {
9709 set cmp [string compare [lindex $reflist $i 0] \
9710 [lindex $refs $j 0]]
9711 if {$cmp == 0} {
9712 set cmp [string compare [lindex $reflist $i 1] \
9713 [lindex $refs $j 1]]
9714 }
9715 } else {
9716 set cmp -1
9717 }
9718 } else {
9719 set cmp 1
9720 }
9721 switch -- $cmp {
9722 -1 {
9723 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
9724 incr i
9725 }
9726 0 {
9727 incr i
9728 incr j
9729 }
9730 1 {
9731 set l [expr {$j + 1}]
9732 $showrefstop.list image create $l.0 -align baseline \
9733 -image reficon-[lindex $refs $j 1] -padx 2
9734 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
9735 incr j
9736 }
9737 }
9738 }
9739 set reflist $refs
9740 # delete last newline
9741 $showrefstop.list delete end-2c end-1c
9742 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10009743}
9744
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009745# Stuff for finding nearby tags
9746proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009747 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
9748 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009749 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009750
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009751 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009752 set nextarc 0
9753 set allcommits 0
9754 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009755 set allcwait 0
9756 set cachedarcs 0
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009757 set allccache [file join $gitdir "gitk.cache"]
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009758 if {![catch {
9759 set f [open $allccache r]
9760 set allcwait 1
9761 getcache $f
9762 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009763 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009764
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009765 if {$allcwait} {
9766 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009767 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009768 set cmd [list | git rev-list --parents]
9769 set allcupdate [expr {$seeds ne {}}]
9770 if {!$allcupdate} {
9771 set ids "--all"
9772 } else {
9773 set refs [concat [array names idheads] [array names idtags] \
9774 [array names idotherrefs]]
9775 set ids {}
9776 set tagobjs {}
9777 foreach name [array names tagobjid] {
9778 lappend tagobjs $tagobjid($name)
9779 }
9780 foreach id [lsort -unique $refs] {
9781 if {![info exists allparents($id)] &&
9782 [lsearch -exact $tagobjs $id] < 0} {
9783 lappend ids $id
9784 }
9785 }
9786 if {$ids ne {}} {
9787 foreach id $seeds {
9788 lappend ids "^$id"
9789 }
9790 }
9791 }
9792 if {$ids ne {}} {
9793 set fd [open [concat $cmd $ids] r]
9794 fconfigure $fd -blocking 0
9795 incr allcommits
9796 nowbusy allcommits
9797 filerun $fd [list getallclines $fd]
9798 } else {
9799 dispneartags 0
9800 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009801}
9802
Paul Mackerrase11f1232007-06-16 20:29:25 +10009803# Since most commits have 1 parent and 1 child, we group strings of
9804# such commits into "arcs" joining branch/merge points (BMPs), which
9805# are commits that either don't have 1 parent or don't have 1 child.
9806#
9807# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
9808# arcout(id) - outgoing arcs for BMP
9809# arcids(a) - list of IDs on arc including end but not start
9810# arcstart(a) - BMP ID at start of arc
9811# arcend(a) - BMP ID at end of arc
9812# growing(a) - arc a is still growing
9813# arctags(a) - IDs out of arcids (excluding end) that have tags
9814# archeads(a) - IDs out of arcids (excluding end) that have heads
9815# The start of an arc is at the descendent end, so "incoming" means
9816# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009817
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009818proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009819 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009820 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009821 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +01009822
Paul Mackerrase11f1232007-06-16 20:29:25 +10009823 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009824 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009825 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10009826 if {[info exists allparents($id)]} {
9827 # seen it already
9828 continue
9829 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009830 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009831 set olds [lrange $line 1 end]
9832 set allparents($id) $olds
9833 if {![info exists allchildren($id)]} {
9834 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10009835 set arcnos($id) {}
9836 lappend seeds $id
9837 } else {
9838 set a $arcnos($id)
9839 if {[llength $olds] == 1 && [llength $a] == 1} {
9840 lappend arcids($a) $id
9841 if {[info exists idtags($id)]} {
9842 lappend arctags($a) $id
9843 }
9844 if {[info exists idheads($id)]} {
9845 lappend archeads($a) $id
9846 }
9847 if {[info exists allparents($olds)]} {
9848 # seen parent already
9849 if {![info exists arcout($olds)]} {
9850 splitarc $olds
9851 }
9852 lappend arcids($a) $olds
9853 set arcend($a) $olds
9854 unset growing($a)
9855 }
9856 lappend allchildren($olds) $id
9857 lappend arcnos($olds) $a
9858 continue
9859 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009860 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009861 foreach a $arcnos($id) {
9862 lappend arcids($a) $id
9863 set arcend($a) $id
9864 unset growing($a)
9865 }
9866
9867 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009868 foreach p $olds {
9869 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10009870 set a [incr nextarc]
9871 set arcstart($a) $id
9872 set archeads($a) {}
9873 set arctags($a) {}
9874 set archeads($a) {}
9875 set arcids($a) {}
9876 lappend ao $a
9877 set growing($a) 1
9878 if {[info exists allparents($p)]} {
9879 # seen it already, may need to make a new branch
9880 if {![info exists arcout($p)]} {
9881 splitarc $p
9882 }
9883 lappend arcids($a) $p
9884 set arcend($a) $p
9885 unset growing($a)
9886 }
9887 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009888 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009889 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009890 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009891 if {$nid > 0} {
9892 global cached_dheads cached_dtags cached_atags
9893 catch {unset cached_dheads}
9894 catch {unset cached_dtags}
9895 catch {unset cached_atags}
9896 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009897 if {![eof $fd]} {
9898 return [expr {$nid >= 1000? 2: 1}]
9899 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009900 set cacheok 1
9901 if {[catch {
9902 fconfigure $fd -blocking 1
9903 close $fd
9904 } err]} {
9905 # got an error reading the list of commits
9906 # if we were updating, try rereading the whole thing again
9907 if {$allcupdate} {
9908 incr allcommits -1
9909 dropcache $err
9910 return
9911 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009912 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009913 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +01009914 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009915 set cacheok 0
9916 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009917 if {[incr allcommits -1] == 0} {
9918 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009919 if {$cacheok} {
9920 run savecache
9921 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009922 }
9923 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009924 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10009925}
9926
9927proc recalcarc {a} {
9928 global arctags archeads arcids idtags idheads
9929
9930 set at {}
9931 set ah {}
9932 foreach id [lrange $arcids($a) 0 end-1] {
9933 if {[info exists idtags($id)]} {
9934 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009935 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009936 if {[info exists idheads($id)]} {
9937 lappend ah $id
9938 }
9939 }
9940 set arctags($a) $at
9941 set archeads($a) $ah
9942}
9943
9944proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009945 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +10009946 global arcstart arcend arcout allparents growing
9947
9948 set a $arcnos($p)
9949 if {[llength $a] != 1} {
9950 puts "oops splitarc called but [llength $a] arcs already"
9951 return
9952 }
9953 set a [lindex $a 0]
9954 set i [lsearch -exact $arcids($a) $p]
9955 if {$i < 0} {
9956 puts "oops splitarc $p not in arc $a"
9957 return
9958 }
9959 set na [incr nextarc]
9960 if {[info exists arcend($a)]} {
9961 set arcend($na) $arcend($a)
9962 } else {
9963 set l [lindex $allparents([lindex $arcids($a) end]) 0]
9964 set j [lsearch -exact $arcnos($l) $a]
9965 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
9966 }
9967 set tail [lrange $arcids($a) [expr {$i+1}] end]
9968 set arcids($a) [lrange $arcids($a) 0 $i]
9969 set arcend($a) $p
9970 set arcstart($na) $p
9971 set arcout($p) $na
9972 set arcids($na) $tail
9973 if {[info exists growing($a)]} {
9974 set growing($na) 1
9975 unset growing($a)
9976 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009977
9978 foreach id $tail {
9979 if {[llength $arcnos($id)] == 1} {
9980 set arcnos($id) $na
9981 } else {
9982 set j [lsearch -exact $arcnos($id) $a]
9983 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
9984 }
9985 }
9986
9987 # reconstruct tags and heads lists
9988 if {$arctags($a) ne {} || $archeads($a) ne {}} {
9989 recalcarc $a
9990 recalcarc $na
9991 } else {
9992 set arctags($na) {}
9993 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009994 }
9995}
9996
Paul Mackerrase11f1232007-06-16 20:29:25 +10009997# Update things for a new commit added that is a child of one
9998# existing commit. Used when cherry-picking.
9999proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010000 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010001 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010002 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010003
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010004 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010005 set allparents($id) [list $p]
10006 set allchildren($id) {}
10007 set arcnos($id) {}
10008 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010009 lappend allchildren($p) $id
10010 set a [incr nextarc]
10011 set arcstart($a) $id
10012 set archeads($a) {}
10013 set arctags($a) {}
10014 set arcids($a) [list $p]
10015 set arcend($a) $p
10016 if {![info exists arcout($p)]} {
10017 splitarc $p
10018 }
10019 lappend arcnos($p) $a
10020 set arcout($id) [list $a]
10021}
10022
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010023# This implements a cache for the topology information.
10024# The cache saves, for each arc, the start and end of the arc,
10025# the ids on the arc, and the outgoing arcs from the end.
10026proc readcache {f} {
10027 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10028 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10029 global allcwait
10030
10031 set a $nextarc
10032 set lim $cachedarcs
10033 if {$lim - $a > 500} {
10034 set lim [expr {$a + 500}]
10035 }
10036 if {[catch {
10037 if {$a == $lim} {
10038 # finish reading the cache and setting up arctags, etc.
10039 set line [gets $f]
10040 if {$line ne "1"} {error "bad final version"}
10041 close $f
10042 foreach id [array names idtags] {
10043 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10044 [llength $allparents($id)] == 1} {
10045 set a [lindex $arcnos($id) 0]
10046 if {$arctags($a) eq {}} {
10047 recalcarc $a
10048 }
10049 }
10050 }
10051 foreach id [array names idheads] {
10052 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10053 [llength $allparents($id)] == 1} {
10054 set a [lindex $arcnos($id) 0]
10055 if {$archeads($a) eq {}} {
10056 recalcarc $a
10057 }
10058 }
10059 }
10060 foreach id [lsort -unique $possible_seeds] {
10061 if {$arcnos($id) eq {}} {
10062 lappend seeds $id
10063 }
10064 }
10065 set allcwait 0
10066 } else {
10067 while {[incr a] <= $lim} {
10068 set line [gets $f]
10069 if {[llength $line] != 3} {error "bad line"}
10070 set s [lindex $line 0]
10071 set arcstart($a) $s
10072 lappend arcout($s) $a
10073 if {![info exists arcnos($s)]} {
10074 lappend possible_seeds $s
10075 set arcnos($s) {}
10076 }
10077 set e [lindex $line 1]
10078 if {$e eq {}} {
10079 set growing($a) 1
10080 } else {
10081 set arcend($a) $e
10082 if {![info exists arcout($e)]} {
10083 set arcout($e) {}
10084 }
10085 }
10086 set arcids($a) [lindex $line 2]
10087 foreach id $arcids($a) {
10088 lappend allparents($s) $id
10089 set s $id
10090 lappend arcnos($id) $a
10091 }
10092 if {![info exists allparents($s)]} {
10093 set allparents($s) {}
10094 }
10095 set arctags($a) {}
10096 set archeads($a) {}
10097 }
10098 set nextarc [expr {$a - 1}]
10099 }
10100 } err]} {
10101 dropcache $err
10102 return 0
10103 }
10104 if {!$allcwait} {
10105 getallcommits
10106 }
10107 return $allcwait
10108}
10109
10110proc getcache {f} {
10111 global nextarc cachedarcs possible_seeds
10112
10113 if {[catch {
10114 set line [gets $f]
10115 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10116 # make sure it's an integer
10117 set cachedarcs [expr {int([lindex $line 1])}]
10118 if {$cachedarcs < 0} {error "bad number of arcs"}
10119 set nextarc 0
10120 set possible_seeds {}
10121 run readcache $f
10122 } err]} {
10123 dropcache $err
10124 }
10125 return 0
10126}
10127
10128proc dropcache {err} {
10129 global allcwait nextarc cachedarcs seeds
10130
10131 #puts "dropping cache ($err)"
10132 foreach v {arcnos arcout arcids arcstart arcend growing \
10133 arctags archeads allparents allchildren} {
10134 global $v
10135 catch {unset $v}
10136 }
10137 set allcwait 0
10138 set nextarc 0
10139 set cachedarcs 0
10140 set seeds {}
10141 getallcommits
10142}
10143
10144proc writecache {f} {
10145 global cachearc cachedarcs allccache
10146 global arcstart arcend arcnos arcids arcout
10147
10148 set a $cachearc
10149 set lim $cachedarcs
10150 if {$lim - $a > 1000} {
10151 set lim [expr {$a + 1000}]
10152 }
10153 if {[catch {
10154 while {[incr a] <= $lim} {
10155 if {[info exists arcend($a)]} {
10156 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10157 } else {
10158 puts $f [list $arcstart($a) {} $arcids($a)]
10159 }
10160 }
10161 } err]} {
10162 catch {close $f}
10163 catch {file delete $allccache}
10164 #puts "writing cache failed ($err)"
10165 return 0
10166 }
10167 set cachearc [expr {$a - 1}]
10168 if {$a > $cachedarcs} {
10169 puts $f "1"
10170 close $f
10171 return 0
10172 }
10173 return 1
10174}
10175
10176proc savecache {} {
10177 global nextarc cachedarcs cachearc allccache
10178
10179 if {$nextarc == $cachedarcs} return
10180 set cachearc 0
10181 set cachedarcs $nextarc
10182 catch {
10183 set f [open $allccache w]
10184 puts $f [list 1 $cachedarcs]
10185 run writecache $f
10186 }
10187}
10188
Paul Mackerrase11f1232007-06-16 20:29:25 +100010189# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10190# or 0 if neither is true.
10191proc anc_or_desc {a b} {
10192 global arcout arcstart arcend arcnos cached_isanc
10193
10194 if {$arcnos($a) eq $arcnos($b)} {
10195 # Both are on the same arc(s); either both are the same BMP,
10196 # or if one is not a BMP, the other is also not a BMP or is
10197 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +100010198 # Or both can be BMPs with no incoming arcs.
10199 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010200 return 0
10201 }
10202 # assert {[llength $arcnos($a)] == 1}
10203 set arc [lindex $arcnos($a) 0]
10204 set i [lsearch -exact $arcids($arc) $a]
10205 set j [lsearch -exact $arcids($arc) $b]
10206 if {$i < 0 || $i > $j} {
10207 return 1
10208 } else {
10209 return -1
10210 }
10211 }
10212
10213 if {![info exists arcout($a)]} {
10214 set arc [lindex $arcnos($a) 0]
10215 if {[info exists arcend($arc)]} {
10216 set aend $arcend($arc)
10217 } else {
10218 set aend {}
10219 }
10220 set a $arcstart($arc)
10221 } else {
10222 set aend $a
10223 }
10224 if {![info exists arcout($b)]} {
10225 set arc [lindex $arcnos($b) 0]
10226 if {[info exists arcend($arc)]} {
10227 set bend $arcend($arc)
10228 } else {
10229 set bend {}
10230 }
10231 set b $arcstart($arc)
10232 } else {
10233 set bend $b
10234 }
10235 if {$a eq $bend} {
10236 return 1
10237 }
10238 if {$b eq $aend} {
10239 return -1
10240 }
10241 if {[info exists cached_isanc($a,$bend)]} {
10242 if {$cached_isanc($a,$bend)} {
10243 return 1
10244 }
10245 }
10246 if {[info exists cached_isanc($b,$aend)]} {
10247 if {$cached_isanc($b,$aend)} {
10248 return -1
10249 }
10250 if {[info exists cached_isanc($a,$bend)]} {
10251 return 0
10252 }
10253 }
10254
10255 set todo [list $a $b]
10256 set anc($a) a
10257 set anc($b) b
10258 for {set i 0} {$i < [llength $todo]} {incr i} {
10259 set x [lindex $todo $i]
10260 if {$anc($x) eq {}} {
10261 continue
10262 }
10263 foreach arc $arcnos($x) {
10264 set xd $arcstart($arc)
10265 if {$xd eq $bend} {
10266 set cached_isanc($a,$bend) 1
10267 set cached_isanc($b,$aend) 0
10268 return 1
10269 } elseif {$xd eq $aend} {
10270 set cached_isanc($b,$aend) 1
10271 set cached_isanc($a,$bend) 0
10272 return -1
10273 }
10274 if {![info exists anc($xd)]} {
10275 set anc($xd) $anc($x)
10276 lappend todo $xd
10277 } elseif {$anc($xd) ne $anc($x)} {
10278 set anc($xd) {}
10279 }
10280 }
10281 }
10282 set cached_isanc($a,$bend) 0
10283 set cached_isanc($b,$aend) 0
10284 return 0
10285}
10286
10287# This identifies whether $desc has an ancestor that is
10288# a growing tip of the graph and which is not an ancestor of $anc
10289# and returns 0 if so and 1 if not.
10290# If we subsequently discover a tag on such a growing tip, and that
10291# turns out to be a descendent of $anc (which it could, since we
10292# don't necessarily see children before parents), then $desc
10293# isn't a good choice to display as a descendent tag of
10294# $anc (since it is the descendent of another tag which is
10295# a descendent of $anc). Similarly, $anc isn't a good choice to
10296# display as a ancestor tag of $desc.
10297#
10298proc is_certain {desc anc} {
10299 global arcnos arcout arcstart arcend growing problems
10300
10301 set certain {}
10302 if {[llength $arcnos($anc)] == 1} {
10303 # tags on the same arc are certain
10304 if {$arcnos($desc) eq $arcnos($anc)} {
10305 return 1
10306 }
10307 if {![info exists arcout($anc)]} {
10308 # if $anc is partway along an arc, use the start of the arc instead
10309 set a [lindex $arcnos($anc) 0]
10310 set anc $arcstart($a)
10311 }
10312 }
10313 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
10314 set x $desc
10315 } else {
10316 set a [lindex $arcnos($desc) 0]
10317 set x $arcend($a)
10318 }
10319 if {$x == $anc} {
10320 return 1
10321 }
10322 set anclist [list $x]
10323 set dl($x) 1
10324 set nnh 1
10325 set ngrowanc 0
10326 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
10327 set x [lindex $anclist $i]
10328 if {$dl($x)} {
10329 incr nnh -1
10330 }
10331 set done($x) 1
10332 foreach a $arcout($x) {
10333 if {[info exists growing($a)]} {
10334 if {![info exists growanc($x)] && $dl($x)} {
10335 set growanc($x) 1
10336 incr ngrowanc
10337 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010338 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010339 set y $arcend($a)
10340 if {[info exists dl($y)]} {
10341 if {$dl($y)} {
10342 if {!$dl($x)} {
10343 set dl($y) 0
10344 if {![info exists done($y)]} {
10345 incr nnh -1
10346 }
10347 if {[info exists growanc($x)]} {
10348 incr ngrowanc -1
10349 }
10350 set xl [list $y]
10351 for {set k 0} {$k < [llength $xl]} {incr k} {
10352 set z [lindex $xl $k]
10353 foreach c $arcout($z) {
10354 if {[info exists arcend($c)]} {
10355 set v $arcend($c)
10356 if {[info exists dl($v)] && $dl($v)} {
10357 set dl($v) 0
10358 if {![info exists done($v)]} {
10359 incr nnh -1
10360 }
10361 if {[info exists growanc($v)]} {
10362 incr ngrowanc -1
10363 }
10364 lappend xl $v
10365 }
10366 }
10367 }
10368 }
10369 }
10370 }
10371 } elseif {$y eq $anc || !$dl($x)} {
10372 set dl($y) 0
10373 lappend anclist $y
10374 } else {
10375 set dl($y) 1
10376 lappend anclist $y
10377 incr nnh
10378 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010379 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010380 }
10381 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010382 foreach x [array names growanc] {
10383 if {$dl($x)} {
10384 return 0
10385 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010386 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010387 }
10388 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010389}
10390
Paul Mackerrase11f1232007-06-16 20:29:25 +100010391proc validate_arctags {a} {
10392 global arctags idtags
10393
10394 set i -1
10395 set na $arctags($a)
10396 foreach id $arctags($a) {
10397 incr i
10398 if {![info exists idtags($id)]} {
10399 set na [lreplace $na $i $i]
10400 incr i -1
10401 }
10402 }
10403 set arctags($a) $na
10404}
10405
10406proc validate_archeads {a} {
10407 global archeads idheads
10408
10409 set i -1
10410 set na $archeads($a)
10411 foreach id $archeads($a) {
10412 incr i
10413 if {![info exists idheads($id)]} {
10414 set na [lreplace $na $i $i]
10415 incr i -1
10416 }
10417 }
10418 set archeads($a) $na
10419}
10420
10421# Return the list of IDs that have tags that are descendents of id,
10422# ignoring IDs that are descendents of IDs already reported.
10423proc desctags {id} {
10424 global arcnos arcstart arcids arctags idtags allparents
10425 global growing cached_dtags
10426
10427 if {![info exists allparents($id)]} {
10428 return {}
10429 }
10430 set t1 [clock clicks -milliseconds]
10431 set argid $id
10432 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10433 # part-way along an arc; check that arc first
10434 set a [lindex $arcnos($id) 0]
10435 if {$arctags($a) ne {}} {
10436 validate_arctags $a
10437 set i [lsearch -exact $arcids($a) $id]
10438 set tid {}
10439 foreach t $arctags($a) {
10440 set j [lsearch -exact $arcids($a) $t]
10441 if {$j >= $i} break
10442 set tid $t
10443 }
10444 if {$tid ne {}} {
10445 return $tid
10446 }
10447 }
10448 set id $arcstart($a)
10449 if {[info exists idtags($id)]} {
10450 return $id
10451 }
10452 }
10453 if {[info exists cached_dtags($id)]} {
10454 return $cached_dtags($id)
10455 }
10456
10457 set origid $id
10458 set todo [list $id]
10459 set queued($id) 1
10460 set nc 1
10461 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10462 set id [lindex $todo $i]
10463 set done($id) 1
10464 set ta [info exists hastaggedancestor($id)]
10465 if {!$ta} {
10466 incr nc -1
10467 }
10468 # ignore tags on starting node
10469 if {!$ta && $i > 0} {
10470 if {[info exists idtags($id)]} {
10471 set tagloc($id) $id
10472 set ta 1
10473 } elseif {[info exists cached_dtags($id)]} {
10474 set tagloc($id) $cached_dtags($id)
10475 set ta 1
10476 }
10477 }
10478 foreach a $arcnos($id) {
10479 set d $arcstart($a)
10480 if {!$ta && $arctags($a) ne {}} {
10481 validate_arctags $a
10482 if {$arctags($a) ne {}} {
10483 lappend tagloc($id) [lindex $arctags($a) end]
10484 }
10485 }
10486 if {$ta || $arctags($a) ne {}} {
10487 set tomark [list $d]
10488 for {set j 0} {$j < [llength $tomark]} {incr j} {
10489 set dd [lindex $tomark $j]
10490 if {![info exists hastaggedancestor($dd)]} {
10491 if {[info exists done($dd)]} {
10492 foreach b $arcnos($dd) {
10493 lappend tomark $arcstart($b)
10494 }
10495 if {[info exists tagloc($dd)]} {
10496 unset tagloc($dd)
10497 }
10498 } elseif {[info exists queued($dd)]} {
10499 incr nc -1
10500 }
10501 set hastaggedancestor($dd) 1
10502 }
10503 }
10504 }
10505 if {![info exists queued($d)]} {
10506 lappend todo $d
10507 set queued($d) 1
10508 if {![info exists hastaggedancestor($d)]} {
10509 incr nc
10510 }
10511 }
10512 }
10513 }
10514 set tags {}
10515 foreach id [array names tagloc] {
10516 if {![info exists hastaggedancestor($id)]} {
10517 foreach t $tagloc($id) {
10518 if {[lsearch -exact $tags $t] < 0} {
10519 lappend tags $t
10520 }
10521 }
10522 }
10523 }
10524 set t2 [clock clicks -milliseconds]
10525 set loopix $i
10526
10527 # remove tags that are descendents of other tags
10528 for {set i 0} {$i < [llength $tags]} {incr i} {
10529 set a [lindex $tags $i]
10530 for {set j 0} {$j < $i} {incr j} {
10531 set b [lindex $tags $j]
10532 set r [anc_or_desc $a $b]
10533 if {$r == 1} {
10534 set tags [lreplace $tags $j $j]
10535 incr j -1
10536 incr i -1
10537 } elseif {$r == -1} {
10538 set tags [lreplace $tags $i $i]
10539 incr i -1
10540 break
10541 }
10542 }
10543 }
10544
10545 if {[array names growing] ne {}} {
10546 # graph isn't finished, need to check if any tag could get
10547 # eclipsed by another tag coming later. Simply ignore any
10548 # tags that could later get eclipsed.
10549 set ctags {}
10550 foreach t $tags {
10551 if {[is_certain $t $origid]} {
10552 lappend ctags $t
10553 }
10554 }
10555 if {$tags eq $ctags} {
10556 set cached_dtags($origid) $tags
10557 } else {
10558 set tags $ctags
10559 }
10560 } else {
10561 set cached_dtags($origid) $tags
10562 }
10563 set t3 [clock clicks -milliseconds]
10564 if {0 && $t3 - $t1 >= 100} {
10565 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
10566 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10567 }
10568 return $tags
10569}
10570
10571proc anctags {id} {
10572 global arcnos arcids arcout arcend arctags idtags allparents
10573 global growing cached_atags
10574
10575 if {![info exists allparents($id)]} {
10576 return {}
10577 }
10578 set t1 [clock clicks -milliseconds]
10579 set argid $id
10580 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10581 # part-way along an arc; check that arc first
10582 set a [lindex $arcnos($id) 0]
10583 if {$arctags($a) ne {}} {
10584 validate_arctags $a
10585 set i [lsearch -exact $arcids($a) $id]
10586 foreach t $arctags($a) {
10587 set j [lsearch -exact $arcids($a) $t]
10588 if {$j > $i} {
10589 return $t
10590 }
10591 }
10592 }
10593 if {![info exists arcend($a)]} {
10594 return {}
10595 }
10596 set id $arcend($a)
10597 if {[info exists idtags($id)]} {
10598 return $id
10599 }
10600 }
10601 if {[info exists cached_atags($id)]} {
10602 return $cached_atags($id)
10603 }
10604
10605 set origid $id
10606 set todo [list $id]
10607 set queued($id) 1
10608 set taglist {}
10609 set nc 1
10610 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10611 set id [lindex $todo $i]
10612 set done($id) 1
10613 set td [info exists hastaggeddescendent($id)]
10614 if {!$td} {
10615 incr nc -1
10616 }
10617 # ignore tags on starting node
10618 if {!$td && $i > 0} {
10619 if {[info exists idtags($id)]} {
10620 set tagloc($id) $id
10621 set td 1
10622 } elseif {[info exists cached_atags($id)]} {
10623 set tagloc($id) $cached_atags($id)
10624 set td 1
10625 }
10626 }
10627 foreach a $arcout($id) {
10628 if {!$td && $arctags($a) ne {}} {
10629 validate_arctags $a
10630 if {$arctags($a) ne {}} {
10631 lappend tagloc($id) [lindex $arctags($a) 0]
10632 }
10633 }
10634 if {![info exists arcend($a)]} continue
10635 set d $arcend($a)
10636 if {$td || $arctags($a) ne {}} {
10637 set tomark [list $d]
10638 for {set j 0} {$j < [llength $tomark]} {incr j} {
10639 set dd [lindex $tomark $j]
10640 if {![info exists hastaggeddescendent($dd)]} {
10641 if {[info exists done($dd)]} {
10642 foreach b $arcout($dd) {
10643 if {[info exists arcend($b)]} {
10644 lappend tomark $arcend($b)
10645 }
10646 }
10647 if {[info exists tagloc($dd)]} {
10648 unset tagloc($dd)
10649 }
10650 } elseif {[info exists queued($dd)]} {
10651 incr nc -1
10652 }
10653 set hastaggeddescendent($dd) 1
10654 }
10655 }
10656 }
10657 if {![info exists queued($d)]} {
10658 lappend todo $d
10659 set queued($d) 1
10660 if {![info exists hastaggeddescendent($d)]} {
10661 incr nc
10662 }
10663 }
10664 }
10665 }
10666 set t2 [clock clicks -milliseconds]
10667 set loopix $i
10668 set tags {}
10669 foreach id [array names tagloc] {
10670 if {![info exists hastaggeddescendent($id)]} {
10671 foreach t $tagloc($id) {
10672 if {[lsearch -exact $tags $t] < 0} {
10673 lappend tags $t
10674 }
10675 }
10676 }
10677 }
10678
10679 # remove tags that are ancestors of other tags
10680 for {set i 0} {$i < [llength $tags]} {incr i} {
10681 set a [lindex $tags $i]
10682 for {set j 0} {$j < $i} {incr j} {
10683 set b [lindex $tags $j]
10684 set r [anc_or_desc $a $b]
10685 if {$r == -1} {
10686 set tags [lreplace $tags $j $j]
10687 incr j -1
10688 incr i -1
10689 } elseif {$r == 1} {
10690 set tags [lreplace $tags $i $i]
10691 incr i -1
10692 break
10693 }
10694 }
10695 }
10696
10697 if {[array names growing] ne {}} {
10698 # graph isn't finished, need to check if any tag could get
10699 # eclipsed by another tag coming later. Simply ignore any
10700 # tags that could later get eclipsed.
10701 set ctags {}
10702 foreach t $tags {
10703 if {[is_certain $origid $t]} {
10704 lappend ctags $t
10705 }
10706 }
10707 if {$tags eq $ctags} {
10708 set cached_atags($origid) $tags
10709 } else {
10710 set tags $ctags
10711 }
10712 } else {
10713 set cached_atags($origid) $tags
10714 }
10715 set t3 [clock clicks -milliseconds]
10716 if {0 && $t3 - $t1 >= 100} {
10717 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
10718 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10719 }
10720 return $tags
10721}
10722
10723# Return the list of IDs that have heads that are descendents of id,
10724# including id itself if it has a head.
10725proc descheads {id} {
10726 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010727 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100010728
10729 if {![info exists allparents($id)]} {
10730 return {}
10731 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010732 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010733 if {![info exists arcout($id)]} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010734 # part-way along an arc; check it first
10735 set a [lindex $arcnos($id) 0]
10736 if {$archeads($a) ne {}} {
10737 validate_archeads $a
10738 set i [lsearch -exact $arcids($a) $id]
10739 foreach t $archeads($a) {
10740 set j [lsearch -exact $arcids($a) $t]
10741 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010742 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100010743 }
10744 }
10745 set id $arcstart($a)
10746 }
10747 set origid $id
10748 set todo [list $id]
10749 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010750 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010751 for {set i 0} {$i < [llength $todo]} {incr i} {
10752 set id [lindex $todo $i]
10753 if {[info exists cached_dheads($id)]} {
10754 set ret [concat $ret $cached_dheads($id)]
10755 } else {
10756 if {[info exists idheads($id)]} {
10757 lappend ret $id
10758 }
10759 foreach a $arcnos($id) {
10760 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100010761 validate_archeads $a
10762 if {$archeads($a) ne {}} {
10763 set ret [concat $ret $archeads($a)]
10764 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010765 }
10766 set d $arcstart($a)
10767 if {![info exists seen($d)]} {
10768 lappend todo $d
10769 set seen($d) 1
10770 }
10771 }
10772 }
10773 }
10774 set ret [lsort -unique $ret]
10775 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010776 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010777}
10778
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010779proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010780 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010781
Paul Mackerrase11f1232007-06-16 20:29:25 +100010782 if {![info exists arcnos($id)]} return
10783 if {![info exists arcout($id)]} {
10784 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010785 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010786 catch {unset cached_dtags}
10787 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010788}
10789
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010790proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010791 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010792
Paul Mackerrase11f1232007-06-16 20:29:25 +100010793 if {![info exists arcnos($hid)]} return
10794 if {![info exists arcout($hid)]} {
10795 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010796 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010797 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010798}
10799
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010800proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010801 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010802
Paul Mackerrase11f1232007-06-16 20:29:25 +100010803 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +100010804}
10805
Paul Mackerrase11f1232007-06-16 20:29:25 +100010806proc movedhead {hid head} {
10807 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010808
Paul Mackerrase11f1232007-06-16 20:29:25 +100010809 if {![info exists arcnos($hid)]} return
10810 if {![info exists arcout($hid)]} {
10811 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010812 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010813 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010814}
10815
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010816proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070010817 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100010818 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010819
Paul Mackerrase11f1232007-06-16 20:29:25 +100010820 foreach id [concat [array names idheads] [array names idtags]] {
10821 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
10822 set a [lindex $arcnos($id) 0]
10823 if {![info exists donearc($a)]} {
10824 recalcarc $a
10825 set donearc($a) 1
10826 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010827 }
10828 }
David Aguilar587277f2012-09-08 12:53:16 -070010829 catch {unset cached_tagcontent}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010830 catch {unset cached_dtags}
10831 catch {unset cached_atags}
10832 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010833}
10834
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010835proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110010836 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010837
10838 set refids [concat [array names idtags] \
10839 [array names idheads] [array names idotherrefs]]
10840 foreach id $refids {
10841 if {![info exists ref($id)]} {
10842 set ref($id) [listrefs $id]
10843 }
10844 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110010845 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010846 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010847 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010848 set refids [lsort -unique [concat $refids [array names idtags] \
10849 [array names idheads] [array names idotherrefs]]]
10850 foreach id $refids {
10851 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010852 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010853 redrawtags $id
10854 }
10855 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010856 if {$oldmainhead ne $mainheadid} {
10857 redrawtags $oldmainhead
10858 redrawtags $mainheadid
10859 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010860 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010861}
10862
Junio C Hamano2e1ded42006-06-11 09:50:47 -070010863proc listrefs {id} {
10864 global idtags idheads idotherrefs
10865
10866 set x {}
10867 if {[info exists idtags($id)]} {
10868 set x $idtags($id)
10869 }
10870 set y {}
10871 if {[info exists idheads($id)]} {
10872 set y $idheads($id)
10873 }
10874 set z {}
10875 if {[info exists idotherrefs($id)]} {
10876 set z $idotherrefs($id)
10877 }
10878 return [list $x $y $z]
10879}
10880
Paul Mackerras106288c2005-08-19 23:11:39 +100010881proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070010882 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100010883
10884 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +110010885 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100010886 }
10887 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100010888 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010889 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100010890 set linknum 0
David Aguilar587277f2012-09-08 12:53:16 -070010891 if {![info exists cached_tagcontent($tag)]} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +100010892 catch {
Anand Kumria685316c2013-04-29 06:20:48 +010010893 set cached_tagcontent($tag) [exec git cat-file -p $tag]
Paul Mackerras62d3ea62006-09-11 10:36:53 +100010894 }
10895 }
David Aguilar587277f2012-09-08 12:53:16 -070010896 if {[info exists cached_tagcontent($tag)]} {
10897 set text $cached_tagcontent($tag)
Paul Mackerras106288c2005-08-19 23:11:39 +100010898 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010899 set text "[mc "Tag"]: $tag\n[mc "Id"]: $tagids($tag)"
Paul Mackerras106288c2005-08-19 23:11:39 +100010900 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +040010901 appendwithlinks $text {}
Pat Thoytsa80e82f2009-11-14 13:21:09 +000010902 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100010903 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100010904 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100010905}
10906
Paul Mackerras1d10f362005-05-15 12:55:47 +000010907proc doquit {} {
10908 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010010909 global gitktmpdir
10910
Paul Mackerras1d10f362005-05-15 12:55:47 +000010911 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050010912 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000010913 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010010914
10915 if {[info exists gitktmpdir]} {
10916 catch {file delete -force $gitktmpdir}
10917 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000010918}
10919
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010920proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010010921 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010922
10923 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010010924 ${NS}::button $top.${font}but -text $which \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010925 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010010926 ${NS}::label $top.$font -relief flat -font $font \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010927 -text $fontattr($font,family) -justify left
10928 grid x $top.${font}but $top.$font -sticky w
10929}
10930
10931proc choosefont {font which} {
10932 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010010933 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010934
10935 set fontparam(which) $which
10936 set fontparam(font) $font
10937 set fontparam(family) [font actual $font -family]
10938 set fontparam(size) $fontattr($font,size)
10939 set fontparam(weight) $fontattr($font,weight)
10940 set fontparam(slant) $fontattr($font,slant)
10941 set top .gitkfont
10942 set fonttop $top
10943 if {![winfo exists $top]} {
10944 font create sample
10945 eval font config sample [font actual $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010010946 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010947 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010010948 wm title $top [mc "Gitk font chooser"]
Pat Thoytsd93f1712009-04-17 01:24:35 +010010949 ${NS}::label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010950 pack $top.l -side top
10951 set fontlist [lsort [font families]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010010952 ${NS}::frame $top.f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010953 listbox $top.f.fam -listvariable fontlist \
10954 -yscrollcommand [list $top.f.sb set]
10955 bind $top.f.fam <<ListboxSelect>> selfontfam
Pat Thoytsd93f1712009-04-17 01:24:35 +010010956 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010957 pack $top.f.sb -side right -fill y
10958 pack $top.f.fam -side left -fill both -expand 1
10959 pack $top.f -side top -fill both -expand 1
Pat Thoytsd93f1712009-04-17 01:24:35 +010010960 ${NS}::frame $top.g
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010961 spinbox $top.g.size -from 4 -to 40 -width 4 \
10962 -textvariable fontparam(size) \
10963 -validatecommand {string is integer -strict %s}
10964 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010965 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010966 -variable fontparam(weight) -onvalue bold -offvalue normal
10967 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010968 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010969 -variable fontparam(slant) -onvalue italic -offvalue roman
10970 pack $top.g.size $top.g.bold $top.g.ital -side left
10971 pack $top.g -side top
10972 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
10973 -background white
10974 $top.c create text 100 25 -anchor center -text $which -font sample \
10975 -fill black -tags text
10976 bind $top.c <Configure> [list centertext $top.c]
10977 pack $top.c -side top -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +010010978 ${NS}::frame $top.buts
10979 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
10980 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010981 bind $top <Key-Return> fontok
10982 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010983 grid $top.buts.ok $top.buts.can
10984 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10985 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10986 pack $top.buts -side bottom -fill x
10987 trace add variable fontparam write chg_fontparam
10988 } else {
10989 raise $top
10990 $top.c itemconf text -text $which
10991 }
10992 set i [lsearch -exact $fontlist $fontparam(family)]
10993 if {$i >= 0} {
10994 $top.f.fam selection set $i
10995 $top.f.fam see $i
10996 }
10997}
10998
10999proc centertext {w} {
11000 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11001}
11002
11003proc fontok {} {
11004 global fontparam fontpref prefstop
11005
11006 set f $fontparam(font)
11007 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11008 if {$fontparam(weight) eq "bold"} {
11009 lappend fontpref($f) "bold"
11010 }
11011 if {$fontparam(slant) eq "italic"} {
11012 lappend fontpref($f) "italic"
11013 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011014 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011015 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011016
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011017 fontcan
11018}
11019
11020proc fontcan {} {
11021 global fonttop fontparam
11022
11023 if {[info exists fonttop]} {
11024 catch {destroy $fonttop}
11025 catch {font delete sample}
11026 unset fonttop
11027 unset fontparam
11028 }
11029}
11030
Pat Thoytsd93f1712009-04-17 01:24:35 +010011031if {[package vsatisfies [package provide Tk] 8.6]} {
11032 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11033 # function to make use of it.
11034 proc choosefont {font which} {
11035 tk fontchooser configure -title $which -font $font \
11036 -command [list on_choosefont $font $which]
11037 tk fontchooser show
11038 }
11039 proc on_choosefont {font which newfont} {
11040 global fontparam
11041 puts stderr "$font $newfont"
11042 array set f [font actual $newfont]
11043 set fontparam(which) $which
11044 set fontparam(font) $font
11045 set fontparam(family) $f(-family)
11046 set fontparam(size) $f(-size)
11047 set fontparam(weight) $f(-weight)
11048 set fontparam(slant) $f(-slant)
11049 fontok
11050 }
11051}
11052
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011053proc selfontfam {} {
11054 global fonttop fontparam
11055
11056 set i [$fonttop.f.fam curselection]
11057 if {$i ne {}} {
11058 set fontparam(family) [$fonttop.f.fam get $i]
11059 }
11060}
11061
11062proc chg_fontparam {v sub op} {
11063 global fontparam
11064
11065 font config sample -$sub $fontparam($sub)
11066}
11067
Pat Thoyts44acce02011-12-13 14:56:49 +000011068# Create a property sheet tab page
11069proc create_prefs_page {w} {
11070 global NS
11071 set parent [join [lrange [split $w .] 0 end-1] .]
11072 if {[winfo class $parent] eq "TNotebook"} {
11073 ${NS}::frame $w
11074 } else {
11075 ${NS}::labelframe $w
11076 }
11077}
11078
11079proc prefspage_general {notebook} {
11080 global NS maxwidth maxgraphpct showneartags showlocalchanges
11081 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011082 global hideremotes want_ttk have_ttk maxrefs
Pat Thoyts44acce02011-12-13 14:56:49 +000011083
11084 set page [create_prefs_page $notebook.general]
11085
11086 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11087 grid $page.ldisp - -sticky w -pady 10
11088 ${NS}::label $page.spacer -text " "
11089 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11090 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11091 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
11092 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11093 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11094 grid x $page.maxpctl $page.maxpct -sticky w
11095 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
11096 -variable showlocalchanges
11097 grid x $page.showlocal -sticky w
11098 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
11099 -variable autoselect
11100 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11101 grid x $page.autoselect $page.autosellen -sticky w
11102 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
11103 -variable hideremotes
11104 grid x $page.hideremotes -sticky w
11105
11106 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11107 grid $page.ddisp - -sticky w -pady 10
11108 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11109 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11110 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011111 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Pat Thoyts44acce02011-12-13 14:56:49 +000011112 -variable showneartags
11113 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011114 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11115 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11116 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011117 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
11118 -variable limitdiffs
11119 grid x $page.ldiff -sticky w
11120 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
11121 -variable perfile_attrs
11122 grid x $page.lattr -sticky w
11123
11124 ${NS}::entry $page.extdifft -textvariable extdifftool
11125 ${NS}::frame $page.extdifff
11126 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11127 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11128 pack $page.extdifff.l $page.extdifff.b -side left
11129 pack configure $page.extdifff.l -padx 10
11130 grid x $page.extdifff $page.extdifft -sticky ew
11131
11132 ${NS}::label $page.lgen -text [mc "General options"]
11133 grid $page.lgen - -sticky w -pady 10
11134 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
11135 -text [mc "Use themed widgets"]
11136 if {$have_ttk} {
11137 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
11138 } else {
11139 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
11140 }
11141 grid x $page.want_ttk $page.ttk_note -sticky w
11142 return $page
11143}
11144
11145proc prefspage_colors {notebook} {
11146 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
11147
11148 set page [create_prefs_page $notebook.colors]
11149
11150 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11151 grid $page.cdisp - -sticky w -pady 10
11152 label $page.ui -padx 40 -relief sunk -background $uicolor
11153 ${NS}::button $page.uibut -text [mc "Interface"] \
11154 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11155 grid x $page.uibut $page.ui -sticky w
11156 label $page.bg -padx 40 -relief sunk -background $bgcolor
11157 ${NS}::button $page.bgbut -text [mc "Background"] \
11158 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
11159 grid x $page.bgbut $page.bg -sticky w
11160 label $page.fg -padx 40 -relief sunk -background $fgcolor
11161 ${NS}::button $page.fgbut -text [mc "Foreground"] \
11162 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
11163 grid x $page.fgbut $page.fg -sticky w
11164 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11165 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
11166 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11167 [list $ctext tag conf d0 -foreground]]
11168 grid x $page.diffoldbut $page.diffold -sticky w
11169 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11170 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
11171 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11172 [list $ctext tag conf dresult -foreground]]
11173 grid x $page.diffnewbut $page.diffnew -sticky w
11174 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11175 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
11176 -command [list choosecolor diffcolors 2 $page.hunksep \
11177 [mc "diff hunk header"] \
11178 [list $ctext tag conf hunksep -foreground]]
11179 grid x $page.hunksepbut $page.hunksep -sticky w
11180 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11181 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
11182 -command [list choosecolor markbgcolor {} $page.markbgsep \
11183 [mc "marked line background"] \
11184 [list $ctext tag conf omark -background]]
11185 grid x $page.markbgbut $page.markbgsep -sticky w
11186 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11187 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
11188 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
11189 grid x $page.selbgbut $page.selbgsep -sticky w
11190 return $page
11191}
11192
11193proc prefspage_fonts {notebook} {
11194 global NS
11195 set page [create_prefs_page $notebook.fonts]
11196 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11197 grid $page.cfont - -sticky w -pady 10
11198 mkfontdisp mainfont $page [mc "Main font"]
11199 mkfontdisp textfont $page [mc "Diff display font"]
11200 mkfontdisp uifont $page [mc "User interface font"]
11201 return $page
11202}
11203
Paul Mackerras712fcc02005-11-30 09:28:16 +110011204proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011205 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011206 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011207 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011208 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011209 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011210
Paul Mackerras712fcc02005-11-30 09:28:16 +110011211 set top .gitkprefs
11212 set prefstop $top
11213 if {[winfo exists $top]} {
11214 raise $top
11215 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011216 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011217 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011218 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110011219 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011220 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011221 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011222 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011223 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011224
Pat Thoyts44acce02011-12-13 14:56:49 +000011225 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
11226 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011227 } else {
Pat Thoyts44acce02011-12-13 14:56:49 +000011228 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011229 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011230
Pat Thoyts44acce02011-12-13 14:56:49 +000011231 lappend pages [prefspage_general $notebook] [mc "General"]
11232 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11233 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011234 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011235 foreach {page title} $pages {
11236 if {$use_notebook} {
11237 $notebook add $page -text $title
11238 } else {
11239 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11240 -text $title -command [list raise $page]]
11241 $page configure -text $title
11242 grid $btn -row 0 -column [incr col] -sticky w
11243 grid $page -row 1 -column 0 -sticky news -columnspan 100
11244 }
11245 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011246
Pat Thoyts44acce02011-12-13 14:56:49 +000011247 if {!$use_notebook} {
11248 grid columnconfigure $notebook 0 -weight 1
11249 grid rowconfigure $notebook 1 -weight 1
11250 raise [lindex $pages 0]
11251 }
11252
11253 grid $notebook -sticky news -padx 2 -pady 2
11254 grid rowconfigure $top 0 -weight 1
11255 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011256
Pat Thoytsd93f1712009-04-17 01:24:35 +010011257 ${NS}::frame $top.buts
11258 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11259 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011260 bind $top <Key-Return> prefsok
11261 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011262 grid $top.buts.ok $top.buts.can
11263 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11264 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11265 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011266 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011267 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011268}
11269
Thomas Arcila314f5de2008-03-24 12:55:36 +010011270proc choose_extdiff {} {
11271 global extdifftool
11272
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011273 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011274 if {$prog ne {}} {
11275 set extdifftool $prog
11276 }
11277}
11278
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011279proc choosecolor {v vi w x cmd} {
11280 global $v
11281
11282 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011283 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011284 if {$c eq {}} return
11285 $w conf -background $c
11286 lset $v $vi $c
11287 eval $cmd $c
11288}
11289
Mark Levedahl60378c02007-05-20 12:12:48 -040011290proc setselbg {c} {
11291 global bglist cflist
11292 foreach w $bglist {
11293 $w configure -selectbackground $c
11294 }
11295 $cflist tag configure highlight \
11296 -background [$cflist cget -selectbackground]
11297 allcanvs itemconf secsel -fill $c
11298}
11299
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011300# This sets the background color and the color scheme for the whole UI.
11301# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11302# if we don't specify one ourselves, which makes the checkbuttons and
11303# radiobuttons look bad. This chooses white for selectColor if the
11304# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011305proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011306 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011307 set bg [winfo rgb . $c]
11308 set selc black
11309 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
11310 set selc white
11311 }
11312 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011313}
11314
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011315proc setbg {c} {
11316 global bglist
11317
11318 foreach w $bglist {
11319 $w conf -background $c
11320 }
11321}
11322
11323proc setfg {c} {
11324 global fglist canv
11325
11326 foreach w $fglist {
11327 $w conf -foreground $c
11328 }
11329 allcanvs itemconf text -fill $c
11330 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011331 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011332}
11333
Paul Mackerras712fcc02005-11-30 09:28:16 +110011334proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011335 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011336
Paul Mackerras3de07112007-10-23 22:40:50 +100011337 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011338 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras94503912007-10-23 10:33:38 +100011339 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110011340 set $v $oldprefs($v)
11341 }
11342 catch {destroy $prefstop}
11343 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011344 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011345}
11346
11347proc prefsok {} {
11348 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011349 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011350 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011351 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011352 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011353
11354 catch {destroy $prefstop}
11355 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011356 fontcan
11357 set fontchanged 0
11358 if {$mainfont ne $fontpref(mainfont)} {
11359 set mainfont $fontpref(mainfont)
11360 parsefont mainfont $mainfont
11361 eval font configure mainfont [fontflags mainfont]
11362 eval font configure mainfontbold [fontflags mainfont 1]
11363 setcoords
11364 set fontchanged 1
11365 }
11366 if {$textfont ne $fontpref(textfont)} {
11367 set textfont $fontpref(textfont)
11368 parsefont textfont $textfont
11369 eval font configure textfont [fontflags textfont]
11370 eval font configure textfontbold [fontflags textfont 1]
11371 }
11372 if {$uifont ne $fontpref(uifont)} {
11373 set uifont $fontpref(uifont)
11374 parsefont uifont $uifont
11375 eval font configure uifont [fontflags uifont]
11376 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011377 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011378 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
11379 if {$showlocalchanges} {
11380 doshowlocalchanges
11381 } else {
11382 dohidelocalchanges
11383 }
11384 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011385 if {$limitdiffs != $oldprefs(limitdiffs) ||
11386 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11387 # treediffs elements are limited by path;
11388 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras74a40c72007-10-24 10:16:56 +100011389 catch {unset treediffs}
11390 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011391 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011392 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11393 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011394 } elseif {$showneartags != $oldprefs(showneartags) ||
11395 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011396 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011397 }
Thomas Rastffe15292009-08-03 23:53:36 +020011398 if {$hideremotes != $oldprefs(hideremotes)} {
11399 rereadrefs
11400 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011401}
11402
11403proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011404 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011405 if {$d ne {}} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -050011406 set d [clock format [lindex $d 0] -format $datetimeformat]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011407 }
11408 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011409}
11410
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011411# This list of encoding names and aliases is distilled from
11412# http://www.iana.org/assignments/character-sets.
11413# Not all of them are supported by Tcl.
11414set encoding_aliases {
11415 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11416 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11417 { ISO-10646-UTF-1 csISO10646UTF1 }
11418 { ISO_646.basic:1983 ref csISO646basic1983 }
11419 { INVARIANT csINVARIANT }
11420 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11421 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11422 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11423 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11424 { NATS-DANO iso-ir-9-1 csNATSDANO }
11425 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11426 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11427 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11428 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11429 { ISO-2022-KR csISO2022KR }
11430 { EUC-KR csEUCKR }
11431 { ISO-2022-JP csISO2022JP }
11432 { ISO-2022-JP-2 csISO2022JP2 }
11433 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11434 csISO13JISC6220jp }
11435 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11436 { IT iso-ir-15 ISO646-IT csISO15Italian }
11437 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11438 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11439 { greek7-old iso-ir-18 csISO18Greek7Old }
11440 { latin-greek iso-ir-19 csISO19LatinGreek }
11441 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11442 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11443 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11444 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11445 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11446 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11447 { INIS iso-ir-49 csISO49INIS }
11448 { INIS-8 iso-ir-50 csISO50INIS8 }
11449 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11450 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11451 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11452 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
11453 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
11454 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
11455 csISO60Norwegian1 }
11456 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
11457 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
11458 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
11459 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
11460 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
11461 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
11462 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
11463 { greek7 iso-ir-88 csISO88Greek7 }
11464 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
11465 { iso-ir-90 csISO90 }
11466 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
11467 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
11468 csISO92JISC62991984b }
11469 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
11470 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
11471 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
11472 csISO95JIS62291984handadd }
11473 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
11474 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
11475 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
11476 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
11477 CP819 csISOLatin1 }
11478 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
11479 { T.61-7bit iso-ir-102 csISO102T617bit }
11480 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
11481 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
11482 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
11483 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
11484 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
11485 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
11486 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
11487 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
11488 arabic csISOLatinArabic }
11489 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
11490 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
11491 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
11492 greek greek8 csISOLatinGreek }
11493 { T.101-G2 iso-ir-128 csISO128T101G2 }
11494 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
11495 csISOLatinHebrew }
11496 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
11497 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
11498 { CSN_369103 iso-ir-139 csISO139CSN369103 }
11499 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
11500 { ISO_6937-2-add iso-ir-142 csISOTextComm }
11501 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
11502 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
11503 csISOLatinCyrillic }
11504 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
11505 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
11506 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
11507 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
11508 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
11509 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
11510 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
11511 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
11512 { ISO_10367-box iso-ir-155 csISO10367Box }
11513 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
11514 { latin-lap lap iso-ir-158 csISO158Lap }
11515 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
11516 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
11517 { us-dk csUSDK }
11518 { dk-us csDKUS }
11519 { JIS_X0201 X0201 csHalfWidthKatakana }
11520 { KSC5636 ISO646-KR csKSC5636 }
11521 { ISO-10646-UCS-2 csUnicode }
11522 { ISO-10646-UCS-4 csUCS4 }
11523 { DEC-MCS dec csDECMCS }
11524 { hp-roman8 roman8 r8 csHPRoman8 }
11525 { macintosh mac csMacintosh }
11526 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
11527 csIBM037 }
11528 { IBM038 EBCDIC-INT cp038 csIBM038 }
11529 { IBM273 CP273 csIBM273 }
11530 { IBM274 EBCDIC-BE CP274 csIBM274 }
11531 { IBM275 EBCDIC-BR cp275 csIBM275 }
11532 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
11533 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
11534 { IBM280 CP280 ebcdic-cp-it csIBM280 }
11535 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
11536 { IBM284 CP284 ebcdic-cp-es csIBM284 }
11537 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
11538 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
11539 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
11540 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
11541 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
11542 { IBM424 cp424 ebcdic-cp-he csIBM424 }
11543 { IBM437 cp437 437 csPC8CodePage437 }
11544 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
11545 { IBM775 cp775 csPC775Baltic }
11546 { IBM850 cp850 850 csPC850Multilingual }
11547 { IBM851 cp851 851 csIBM851 }
11548 { IBM852 cp852 852 csPCp852 }
11549 { IBM855 cp855 855 csIBM855 }
11550 { IBM857 cp857 857 csIBM857 }
11551 { IBM860 cp860 860 csIBM860 }
11552 { IBM861 cp861 861 cp-is csIBM861 }
11553 { IBM862 cp862 862 csPC862LatinHebrew }
11554 { IBM863 cp863 863 csIBM863 }
11555 { IBM864 cp864 csIBM864 }
11556 { IBM865 cp865 865 csIBM865 }
11557 { IBM866 cp866 866 csIBM866 }
11558 { IBM868 CP868 cp-ar csIBM868 }
11559 { IBM869 cp869 869 cp-gr csIBM869 }
11560 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
11561 { IBM871 CP871 ebcdic-cp-is csIBM871 }
11562 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
11563 { IBM891 cp891 csIBM891 }
11564 { IBM903 cp903 csIBM903 }
11565 { IBM904 cp904 904 csIBBM904 }
11566 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
11567 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
11568 { IBM1026 CP1026 csIBM1026 }
11569 { EBCDIC-AT-DE csIBMEBCDICATDE }
11570 { EBCDIC-AT-DE-A csEBCDICATDEA }
11571 { EBCDIC-CA-FR csEBCDICCAFR }
11572 { EBCDIC-DK-NO csEBCDICDKNO }
11573 { EBCDIC-DK-NO-A csEBCDICDKNOA }
11574 { EBCDIC-FI-SE csEBCDICFISE }
11575 { EBCDIC-FI-SE-A csEBCDICFISEA }
11576 { EBCDIC-FR csEBCDICFR }
11577 { EBCDIC-IT csEBCDICIT }
11578 { EBCDIC-PT csEBCDICPT }
11579 { EBCDIC-ES csEBCDICES }
11580 { EBCDIC-ES-A csEBCDICESA }
11581 { EBCDIC-ES-S csEBCDICESS }
11582 { EBCDIC-UK csEBCDICUK }
11583 { EBCDIC-US csEBCDICUS }
11584 { UNKNOWN-8BIT csUnknown8BiT }
11585 { MNEMONIC csMnemonic }
11586 { MNEM csMnem }
11587 { VISCII csVISCII }
11588 { VIQR csVIQR }
11589 { KOI8-R csKOI8R }
11590 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
11591 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
11592 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
11593 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
11594 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
11595 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
11596 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
11597 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
11598 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
11599 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
11600 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
11601 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
11602 { IBM1047 IBM-1047 }
11603 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
11604 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
11605 { UNICODE-1-1 csUnicode11 }
11606 { CESU-8 csCESU-8 }
11607 { BOCU-1 csBOCU-1 }
11608 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
11609 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
11610 l8 }
11611 { ISO-8859-15 ISO_8859-15 Latin-9 }
11612 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
11613 { GBK CP936 MS936 windows-936 }
11614 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011615 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011616 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
11617 EUC-JP }
11618 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
11619 { ISO-10646-UCS-Basic csUnicodeASCII }
11620 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
11621 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
11622 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
11623 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
11624 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
11625 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
11626 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
11627 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
11628 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
11629 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
11630 { Adobe-Standard-Encoding csAdobeStandardEncoding }
11631 { Ventura-US csVenturaUS }
11632 { Ventura-International csVenturaInternational }
11633 { PC8-Danish-Norwegian csPC8DanishNorwegian }
11634 { PC8-Turkish csPC8Turkish }
11635 { IBM-Symbols csIBMSymbols }
11636 { IBM-Thai csIBMThai }
11637 { HP-Legal csHPLegal }
11638 { HP-Pi-font csHPPiFont }
11639 { HP-Math8 csHPMath8 }
11640 { Adobe-Symbol-Encoding csHPPSMath }
11641 { HP-DeskTop csHPDesktop }
11642 { Ventura-Math csVenturaMath }
11643 { Microsoft-Publishing csMicrosoftPublishing }
11644 { Windows-31J csWindows31J }
11645 { GB2312 csGB2312 }
11646 { Big5 csBig5 }
11647}
11648
11649proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011650 global encoding_aliases tcl_encoding_cache
11651 if {[info exists tcl_encoding_cache($enc)]} {
11652 return $tcl_encoding_cache($enc)
11653 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011654 set names [encoding names]
11655 set lcnames [string tolower $names]
11656 set enc [string tolower $enc]
11657 set i [lsearch -exact $lcnames $enc]
11658 if {$i < 0} {
11659 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011660 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011661 set i [lsearch -exact $lcnames $encx]
11662 }
11663 }
11664 if {$i < 0} {
11665 foreach l $encoding_aliases {
11666 set ll [string tolower $l]
11667 if {[lsearch -exact $ll $enc] < 0} continue
11668 # look through the aliases for one that tcl knows about
11669 foreach e $ll {
11670 set i [lsearch -exact $lcnames $e]
11671 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011672 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011673 set i [lsearch -exact $lcnames $ex]
11674 }
11675 }
11676 if {$i >= 0} break
11677 }
11678 break
11679 }
11680 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011681 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011682 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011683 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011684 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011685 set tcl_encoding_cache($enc) $tclenc
11686 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011687}
11688
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011689proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011690 global path_attr_cache
11691 if {[info exists path_attr_cache($attr,$path)]} {
11692 set r $path_attr_cache($attr,$path)
11693 } else {
11694 set r "unspecified"
11695 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020011696 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011697 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011698 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011699 }
11700 if {$r eq "unspecified"} {
11701 return $default
11702 }
11703 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011704}
11705
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011706proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011707 global path_attr_cache
11708 set newlist {}
11709 foreach path $pathlist {
11710 if {![info exists path_attr_cache($attr,$path)]} {
11711 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011712 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011713 }
11714 set lim 1000
11715 if {[tk windowingsystem] == "win32"} {
11716 # windows has a 32k limit on the arguments to a command...
11717 set lim 30
11718 }
11719 while {$newlist ne {}} {
11720 set head [lrange $newlist 0 [expr {$lim - 1}]]
11721 set newlist [lrange $newlist $lim end]
11722 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
11723 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020011724 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011725 if {[string index $path 0] eq "\""} {
11726 set path [encoding convertfrom [lindex $path 0]]
11727 }
11728 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011729 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011730 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011731 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011732 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011733}
11734
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011735proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011736 global gui_encoding perfile_attrs
11737 set tcl_enc $gui_encoding
11738 if {$path ne {} && $perfile_attrs} {
11739 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
11740 if {$enc2 ne {}} {
11741 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011742 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011743 }
11744 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011745}
11746
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011747# First check that Tcl/Tk is recent enough
11748if {[catch {package require Tk 8.4} err]} {
Bernt Hansen8d849952009-11-02 07:41:00 -050011749 show_error {} . "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
11750 Gitk requires at least Tcl/Tk 8.4." list
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011751 exit 1
11752}
11753
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060011754# on OSX bring the current Wish process window to front
11755if {[tk windowingsystem] eq "aqua"} {
11756 exec osascript -e [format {
11757 tell application "System Events"
11758 set frontmost of processes whose unix id is %d to true
11759 end tell
11760 } [pid] ]
11761}
11762
Aske Olsson0ae10352012-05-10 12:13:43 +020011763# Unset GIT_TRACE var if set
11764if { [info exists ::env(GIT_TRACE)] } {
11765 unset ::env(GIT_TRACE)
11766}
11767
Paul Mackerras1d10f362005-05-15 12:55:47 +000011768# defaults...
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011769set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -080011770
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011771set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080011772catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110011773 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080011774}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030011775catch {
11776 set gitencoding [exec git config --get i18n.logoutputencoding]
11777}
Junio C Hamano671bc152005-11-27 16:12:51 -080011778if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011779 set gitencoding "utf-8"
11780}
11781set tclencoding [tcl_encoding $gitencoding]
11782if {$tclencoding == {}} {
11783 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080011784}
Paul Mackerras1d10f362005-05-15 12:55:47 +000011785
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011786set gui_encoding [encoding system]
11787catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011788 set enc [exec git config --get gui.encoding]
11789 if {$enc ne {}} {
11790 set tclenc [tcl_encoding $enc]
11791 if {$tclenc ne {}} {
11792 set gui_encoding $tclenc
11793 } else {
11794 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
11795 }
11796 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011797}
11798
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020011799set log_showroot true
11800catch {
11801 set log_showroot [exec git config --bool --get log.showroot]
11802}
11803
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011804if {[tk windowingsystem] eq "aqua"} {
11805 set mainfont {{Lucida Grande} 9}
11806 set textfont {Monaco 9}
11807 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060011808} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
11809 # fontconfig!
11810 set mainfont {sans 9}
11811 set textfont {monospace 9}
11812 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011813} else {
11814 set mainfont {Helvetica 9}
11815 set textfont {Courier 9}
11816 set uifont {Helvetica 9 bold}
11817}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040011818set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040011819set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100011820set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100011821set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110011822set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110011823set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100011824set uparrowlen 5
11825set downarrowlen 5
11826set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100011827set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040011828set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011829set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020011830set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100011831set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +100011832set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011833set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100011834set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011835set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050011836set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011837set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011838set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011839set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000011840
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011841if {[tk windowingsystem] eq "aqua"} {
11842 set extdifftool "opendiff"
11843} else {
11844 set extdifftool "meld"
11845}
Thomas Arcila314f5de2008-03-24 12:55:36 +010011846
Paul Mackerras1d10f362005-05-15 12:55:47 +000011847set colors {green red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000011848if {[tk windowingsystem] eq "win32"} {
11849 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010011850 set uifgcolor SystemButtonText
11851 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000011852 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010011853 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000011854 set selectbgcolor SystemHighlight
11855} else {
11856 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010011857 set uifgcolor black
11858 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000011859 set bgcolor white
11860 set fgcolor black
11861 set selectbgcolor gray85
11862}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011863set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020011864set diffcontext 3
Gauthier Östervall252c52d2013-03-27 14:40:51 +010011865set mergecolors {red blue green purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010011866set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020011867set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110011868set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000011869
Gauthier Östervall252c52d2013-03-27 14:40:51 +010011870set headbgcolor green
11871set headfgcolor black
11872set headoutlinecolor black
11873set remotebgcolor #ffddaa
11874set tagbgcolor yellow
11875set tagfgcolor black
11876set tagoutlinecolor black
11877set reflinecolor black
11878set filesepbgcolor #aaaaaa
11879set filesepfgcolor black
11880set linehoverbgcolor #ffff80
11881set linehoverfgcolor black
11882set linehoveroutlinecolor black
11883set mainheadcirclecolor yellow
11884set workingfilescirclecolor red
11885set indexcirclecolor green
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011886set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010011887set linkfgcolor blue
11888set circleoutlinecolor $fgcolor
11889set foundbgcolor yellow
11890set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011891
Paul Mackerrasd277e892008-09-21 18:11:37 -050011892# button for popping up context menus
11893if {[tk windowingsystem] eq "aqua"} {
11894 set ctxbut <Button-2>
11895} else {
11896 set ctxbut <Button-3>
11897}
11898
Christian Stimming663c3aa2007-11-07 18:40:59 +010011899## For msgcat loading, first locate the installation location.
11900if { [info exists ::env(GITK_MSGSDIR)] } {
11901 ## Msgsdir was manually set in the environment.
11902 set gitk_msgsdir $::env(GITK_MSGSDIR)
11903} else {
11904 ## Let's guess the prefix from argv0.
11905 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
11906 set gitk_libdir [file join $gitk_prefix share gitk lib]
11907 set gitk_msgsdir [file join $gitk_libdir msgs]
11908 unset gitk_prefix
11909}
11910
11911## Internationalization (i18n) through msgcat and gettext. See
11912## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
11913package require msgcat
11914namespace import ::msgcat::mc
11915## And eventually load the actual message catalog
11916::msgcat::mcload $gitk_msgsdir
11917
Paul Mackerras1d10f362005-05-15 12:55:47 +000011918catch {source ~/.gitk}
11919
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100011920parsefont mainfont $mainfont
11921eval font create mainfont [fontflags mainfont]
11922eval font create mainfontbold [fontflags mainfont 1]
11923
11924parsefont textfont $textfont
11925eval font create textfont [fontflags textfont]
11926eval font create textfontbold [fontflags textfont 1]
11927
11928parsefont uifont $uifont
11929eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000011930
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011931setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011932
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110011933setoptions
11934
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011935# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040011936if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011937 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020011938 exit 1
11939}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011940
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011941set selecthead {}
11942set selectheadid {}
11943
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011944set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011945set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011946set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010011947set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011948foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010011949 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100011950 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011951 "--" {
11952 set cmdline_files [lrange $argv [expr {$i + 1}] end]
11953 break
11954 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011955 "--select-commit=*" {
11956 set selecthead [string range $arg 16 end]
11957 }
Yann Dirson2d480852008-02-21 21:23:31 +010011958 "--argscmd=*" {
11959 set revtreeargscmd [string range $arg 10 end]
11960 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011961 default {
11962 lappend revtreeargs $arg
11963 }
11964 }
11965 incr i
11966}
11967
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011968if {$selecthead eq "HEAD"} {
11969 set selecthead {}
11970}
11971
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011972if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100011973 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011974 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011975 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011976 set cmdline_files [split $f "\n"]
11977 set n [llength $cmdline_files]
11978 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011979 # Unfortunately git rev-parse doesn't produce an error when
11980 # something is both a revision and a filename. To be consistent
11981 # with git log and git rev-list, check revtreeargs for filenames.
11982 foreach arg $revtreeargs {
11983 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011984 show_error {} . [mc "Ambiguous argument '%s': both revision\
11985 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011986 exit 1
11987 }
11988 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011989 } err]} {
11990 # unfortunately we get both stdout and stderr in $err,
11991 # so look for "fatal:".
11992 set i [string first "fatal:" $err]
11993 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070011994 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011995 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010011996 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011997 exit 1
11998 }
11999}
12000
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012001set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012002set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012003set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012004
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012005set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012006if {![info exists have_ttk]} {
12007 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012008}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012009set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012010set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012011
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012012regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012013
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012014set show_notes {}
12015if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12016 set show_notes "--show-notes"
12017}
12018
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012019set appname "gitk"
12020
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012021set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012022set history {}
12023set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012024set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012025set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012026set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012027set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012028set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012029set boldids {}
12030set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012031set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012032set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012033set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012034set need_redisplay 0
12035set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012036set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012037
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012038set nextviewnum 1
12039set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012040set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012041set selectedhlview [mc "None"]
12042set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012043set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012044set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012045set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012046set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012047set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012048
Paul Mackerras94b4a692008-05-20 20:51:06 +100012049set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012050set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012051set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012052set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012053set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012054set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012055set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012056set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012057set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012058set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012059if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012060 set cdup [exec git rev-parse --show-cdup]
12061}
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -040012062set worktree [exec git rev-parse --show-toplevel]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012063setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012064makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012065catch {
12066 image create photo gitlogo -width 16 -height 16
12067
12068 image create photo gitlogominus -width 4 -height 2
12069 gitlogominus put #C00000 -to 0 0 4 2
12070 gitlogo copy gitlogominus -to 1 5
12071 gitlogo copy gitlogominus -to 6 5
12072 gitlogo copy gitlogominus -to 11 5
12073 image delete gitlogominus
12074
12075 image create photo gitlogoplus -width 4 -height 4
12076 gitlogoplus put #008000 -to 1 0 3 4
12077 gitlogoplus put #008000 -to 0 1 4 3
12078 gitlogo copy gitlogoplus -to 1 9
12079 gitlogo copy gitlogoplus -to 6 9
12080 gitlogo copy gitlogoplus -to 11 9
12081 image delete gitlogoplus
12082
Stephen Boydd38d7d42009-03-19 01:54:18 -070012083 image create photo gitlogo32 -width 32 -height 32
12084 gitlogo32 copy gitlogo -zoom 2 2
12085
12086 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012087}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012088# wait for the window to become visible
12089tkwait visibility .
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012090wm title . "$appname: [reponame]"
Pat Thoyts478afad2009-04-15 17:14:03 +010012091update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012092readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012093
Yann Dirson2d480852008-02-21 21:23:31 +010012094if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012095 # create a view for the files/dirs specified on the command line
12096 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012097 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012098 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012099 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012100 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012101 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012102 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012103 set viewperm(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012104 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012105 addviewmenu 1
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +110012106 .bar.view entryconf [mca "Edit view..."] -state normal
12107 .bar.view entryconf [mca "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012108}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012109
12110if {[info exists permviews]} {
12111 foreach v $permviews {
12112 set n $nextviewnum
12113 incr nextviewnum
12114 set viewname($n) [lindex $v 0]
12115 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012116 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010012117 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012118 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012119 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012120 }
12121}
Johannes Sixte4df5192008-12-18 08:30:49 +010012122
12123if {[tk windowingsystem] eq "win32"} {
12124 focus -force .
12125}
12126
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012127getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012128
12129# Local variables:
12130# mode: tcl
12131# indent-tabs-mode: t
12132# tab-width: 8
12133# End: