blob: 251e9242b362d53758bf50ed6acb61927db026d9 [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 Mackerrase1a7c812006-07-18 01:52:14 +10005# Copyright (C) 2005-2006 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
Junio C Hamano73b6a6c2005-07-28 00:28:44 -070010proc gitdir {} {
11 global env
12 if {[info exists env(GIT_DIR)]} {
13 return $env(GIT_DIR)
14 } else {
Peter Baumann5024baa2007-01-09 15:30:19 +010015 return [exec git rev-parse --git-dir]
Junio C Hamano73b6a6c2005-07-28 00:28:44 -070016 }
17}
18
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100019# A simple scheduler for compute-intensive stuff.
20# The aim is to make sure that event handlers for GUI actions can
21# run at least every 50-100 ms. Unfortunately fileevent handlers are
22# run before X event handlers, so reading from a fast source can
23# make the GUI completely unresponsive.
24proc run args {
25 global isonrunq runq
26
27 set script $args
28 if {[info exists isonrunq($script)]} return
29 if {$runq eq {}} {
30 after idle dorunq
31 }
32 lappend runq [list {} $script]
33 set isonrunq($script) 1
34}
35
36proc filerun {fd script} {
37 fileevent $fd readable [list filereadable $fd $script]
38}
39
40proc filereadable {fd script} {
41 global runq
42
43 fileevent $fd readable {}
44 if {$runq eq {}} {
45 after idle dorunq
46 }
47 lappend runq [list $fd $script]
48}
49
50proc dorunq {} {
51 global isonrunq runq
52
53 set tstart [clock clicks -milliseconds]
54 set t0 $tstart
55 while {$runq ne {}} {
56 set fd [lindex $runq 0 0]
57 set script [lindex $runq 0 1]
58 set repeat [eval $script]
59 set t1 [clock clicks -milliseconds]
60 set t [expr {$t1 - $t0}]
61 set runq [lrange $runq 1 end]
62 if {$repeat ne {} && $repeat} {
63 if {$fd eq {} || $repeat == 2} {
64 # script returns 1 if it wants to be readded
65 # file readers return 2 if they could do more straight away
66 lappend runq [list $fd $script]
67 } else {
68 fileevent $fd readable [list filereadable $fd $script]
69 }
70 } elseif {$fd eq {}} {
71 unset isonrunq($script)
72 }
73 set t0 $t1
74 if {$t1 - $tstart >= 80} break
75 }
76 if {$runq ne {}} {
77 after idle dorunq
78 }
79}
80
81# Start off a git rev-list process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100082proc start_rev_list {view} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100083 global startmsecs
Paul Mackerras9f1afe02006-02-19 22:44:47 +110084 global commfd leftover tclencoding datemode
Paul Mackerras6e8c8702007-07-31 21:03:06 +100085 global viewargs viewfiles commitidx vnextroot
Paul Mackerras219ea3a2006-09-07 10:21:39 +100086 global lookingforhead showlocalchanges
Paul Mackerras38ad0912005-12-01 22:42:46 +110087
88 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100089 set commitidx($view) 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100090 set vnextroot($view) 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110091 set order "--topo-order"
92 if {$datemode} {
93 set order "--date-order"
94 }
Paul Mackerras418c4c72006-02-07 09:10:18 +110095 if {[catch {
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100096 set fd [open [concat | git log -z --pretty=raw $order --parents \
97 --boundary $viewargs($view) "--" $viewfiles($view)] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +110098 } err]} {
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100099 error_popup "Error executing git rev-list: $err"
Paul Mackerras38ad0912005-12-01 22:42:46 +1100100 exit 1
101 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000102 set commfd($view) $fd
103 set leftover($view) {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000104 set lookingforhead $showlocalchanges
Mark Levedahl86da5b62007-07-17 18:42:04 -0400105 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100106 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000107 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100108 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000109 filerun $fd [list getcommitlines $fd $view]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000110 nowbusy $view
Paul Mackerras38ad0912005-12-01 22:42:46 +1100111}
112
Paul Mackerras22626ef2006-04-17 09:56:02 +1000113proc stop_rev_list {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000114 global commfd curview
Paul Mackerras22626ef2006-04-17 09:56:02 +1000115
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000116 if {![info exists commfd($curview)]} return
117 set fd $commfd($curview)
Paul Mackerras22626ef2006-04-17 09:56:02 +1000118 catch {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000119 set pid [pid $fd]
Paul Mackerras22626ef2006-04-17 09:56:02 +1000120 exec kill $pid
121 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000122 catch {close $fd}
123 unset commfd($curview)
Paul Mackerras22626ef2006-04-17 09:56:02 +1000124}
125
Paul Mackerrasa8aaf192006-04-23 22:45:55 +1000126proc getcommits {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000127 global phase canv mainfont curview
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100128
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100129 set phase getcommits
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000130 initlayout
131 start_rev_list $curview
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000132 show_status "Reading commits..."
Paul Mackerras1d10f362005-05-15 12:55:47 +0000133}
134
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000135# This makes a string representation of a positive integer which
136# sorts as a string in numerical order
137proc strrep {n} {
138 if {$n < 16} {
139 return [format "%x" $n]
140 } elseif {$n < 256} {
141 return [format "x%.2x" $n]
142 } elseif {$n < 65536} {
143 return [format "y%.4x" $n]
144 }
145 return [format "z%.8x" $n]
146}
147
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000148proc getcommitlines {fd view} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000149 global commitlisted
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000150 global leftover commfd
Paul Mackerras8ed16482006-03-02 22:56:44 +1100151 global displayorder commitidx commitrow commitdata
Paul Mackerras6a90bff2007-06-18 09:48:23 +1000152 global parentlist children curview hlview
153 global vparentlist vdisporder vcmitlisted
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000154 global ordertok vnextroot idpending
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000155
Paul Mackerrasd1e46752006-08-16 20:02:32 +1000156 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +1000157 # git log doesn't terminate the last commit with a null...
158 if {$stuff == {} && $leftover($view) ne {} && [eof $fd]} {
159 set stuff "\0"
160 }
Paul Mackerrasb490a992005-06-22 10:25:38 +1000161 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000162 if {![eof $fd]} {
163 return 1
164 }
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000165 # Check if we have seen any ids listed as parents that haven't
166 # appeared in the list
167 foreach vid [array names idpending "$view,*"] {
168 # should only get here if git log is buggy
169 set id [lindex [split $vid ","] 1]
170 set commitrow($vid) $commitidx($view)
171 incr commitidx($view)
172 if {$view == $curview} {
173 lappend parentlist {}
174 lappend displayorder $id
175 lappend commitlisted 0
176 } else {
177 lappend vparentlist($view) {}
178 lappend vdisporder($view) $id
179 lappend vcmitlisted($view) 0
180 }
181 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000182 global viewname
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000183 unset commfd($view)
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000184 notbusy $view
Paul Mackerrasf0654862005-07-18 14:29:03 -0400185 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000186 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000187 if {[catch {close $fd} err]} {
188 set fv {}
189 if {$view != $curview} {
190 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000191 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000192 if {[string range $err 0 4] == "usage"} {
193 set err "Gitk: error reading commits$fv:\
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300194 bad arguments to git rev-list."
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000195 if {$viewname($view) eq "Command line"} {
196 append err \
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300197 " (Note: arguments to gitk are passed to git rev-list\
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000198 to allow selection of commits to be displayed.)"
199 }
200 } else {
201 set err "Error reading commits$fv: $err"
202 }
203 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +0000204 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000205 if {$view == $curview} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000206 run chewcommits $view
Paul Mackerras9a40c502005-05-12 23:46:16 +0000207 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000208 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +0000209 }
Paul Mackerrasb490a992005-06-22 10:25:38 +1000210 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100211 set gotsome 0
Paul Mackerrasb490a992005-06-22 10:25:38 +1000212 while 1 {
213 set i [string first "\0" $stuff $start]
214 if {$i < 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000215 append leftover($view) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100216 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000217 }
Paul Mackerrasb490a992005-06-22 10:25:38 +1000218 if {$start == 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000219 set cmit $leftover($view)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100220 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000221 set leftover($view) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100222 } else {
223 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +1000224 }
225 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000226 set j [string first "\n" $cmit]
227 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100228 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +1000229 if {$j >= 0 && [string match "commit *" $cmit]} {
230 set ids [string range $cmit 7 [expr {$j - 1}]]
231 if {[string match {[-<>]*} $ids]} {
232 switch -- [string index $ids 0] {
233 "-" {set listed 0}
234 "<" {set listed 2}
235 ">" {set listed 3}
236 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100237 set ids [string range $ids 1 end]
238 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000239 set ok 1
240 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100241 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000242 set ok 0
243 break
244 }
245 }
246 }
247 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +1000248 set shortcmit $cmit
249 if {[string length $shortcmit] > 80} {
250 set shortcmit "[string range $shortcmit 0 80]..."
251 }
Paul Mackerrasc961b222007-07-09 22:45:47 +1000252 error_popup "Can't parse git log output: {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +1000253 exit 1
254 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000255 set id [lindex $ids 0]
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000256 if {![info exists ordertok($view,$id)]} {
257 set otok "o[strrep $vnextroot($view)]"
258 incr vnextroot($view)
259 set ordertok($view,$id) $otok
260 } else {
261 set otok $ordertok($view,$id)
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000262 unset idpending($view,$id)
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000263 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100264 if {$listed} {
265 set olds [lrange $ids 1 end]
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000266 if {[llength $olds] == 1} {
267 set p [lindex $olds 0]
268 lappend children($view,$p) $id
269 if {![info exists ordertok($view,$p)]} {
270 set ordertok($view,$p) $ordertok($view,$id)
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000271 set idpending($view,$p) 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000272 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000273 } else {
274 set i 0
275 foreach p $olds {
276 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
277 lappend children($view,$p) $id
278 }
279 if {![info exists ordertok($view,$p)]} {
280 set ordertok($view,$p) "$otok[strrep $i]]"
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000281 set idpending($view,$p) 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000282 }
283 incr i
284 }
Paul Mackerras79b2c752006-04-02 20:47:40 +1000285 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100286 } else {
287 set olds {}
288 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000289 if {![info exists children($view,$id)]} {
290 set children($view,$id) {}
Paul Mackerras79b2c752006-04-02 20:47:40 +1000291 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100292 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000293 set commitrow($view,$id) $commitidx($view)
294 incr commitidx($view)
295 if {$view == $curview} {
296 lappend parentlist $olds
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000297 lappend displayorder $id
298 lappend commitlisted $listed
299 } else {
300 lappend vparentlist($view) $olds
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000301 lappend vdisporder($view) $id
302 lappend vcmitlisted($view) $listed
303 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100304 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100305 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100306 if {$gotsome} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000307 run chewcommits $view
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100308 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000309 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +0000310}
311
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000312proc chewcommits {view} {
313 global curview hlview commfd
314 global selectedline pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000315
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000316 set more 0
317 if {$view == $curview} {
318 set allread [expr {![info exists commfd($view)]}]
319 set tlimit [expr {[clock clicks -milliseconds] + 50}]
320 set more [layoutmore $tlimit $allread]
321 if {$allread && !$more} {
Paul Mackerras8f489362007-07-13 19:49:37 +1000322 global displayorder commitidx phase
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000323 global numcommits startmsecs
324
325 if {[info exists pending_select]} {
Paul Mackerras8f489362007-07-13 19:49:37 +1000326 set row [first_real_row]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000327 selectline $row 1
328 }
329 if {$commitidx($curview) > 0} {
330 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
331 #puts "overall $ms ms for $numcommits commits"
332 } else {
333 show_status "No commits selected"
334 }
335 notbusy layout
336 set phase {}
337 }
Paul Mackerrasb6645502005-08-11 09:56:23 +1000338 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000339 if {[info exists hlview] && $view == $hlview} {
340 vhighlightmore
Paul Mackerrasb6645502005-08-11 09:56:23 +1000341 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000342 return $more
Paul Mackerras1db95b02005-05-09 04:08:39 +0000343}
344
345proc readcommit {id} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300346 if {[catch {set contents [exec git cat-file commit $id]}]} return
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100347 parsecommit $id $contents 0
Paul Mackerrasb490a992005-06-22 10:25:38 +1000348}
349
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000350proc updatecommits {} {
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000351 global viewdata curview phase displayorder ordertok idpending
Paul Mackerrasa69b2d12007-08-13 15:02:02 +1000352 global children commitrow selectedline thickerline showneartags
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000353
Paul Mackerras22626ef2006-04-17 09:56:02 +1000354 if {$phase ne {}} {
355 stop_rev_list
356 set phase {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100357 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000358 set n $curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000359 foreach id $displayorder {
360 catch {unset children($n,$id)}
361 catch {unset commitrow($n,$id)}
Paul Mackerrasb0cdca92007-08-23 19:35:51 +1000362 catch {unset ordertok($n,$id)}
363 }
364 foreach vid [array names idpending "$n,*"] {
365 unset idpending($vid)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000366 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000367 set curview -1
Paul Mackerras908c3582006-05-20 09:38:11 +1000368 catch {unset selectedline}
369 catch {unset thickerline}
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000370 catch {unset viewdata($n)}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100371 readrefs
Paul Mackerrase11f1232007-06-16 20:29:25 +1000372 changedrefs
Paul Mackerrasa69b2d12007-08-13 15:02:02 +1000373 if {$showneartags} {
374 getallcommits
375 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000376 showview $n
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100377}
378
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100379proc parsecommit {id contents listed} {
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100380 global commitinfo cdate
381
382 set inhdr 1
383 set comment {}
384 set headline {}
385 set auname {}
386 set audate {}
387 set comname {}
388 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +1100389 set hdrend [string first "\n\n" $contents]
390 if {$hdrend < 0} {
391 # should never happen...
392 set hdrend [string length $contents]
393 }
394 set header [string range $contents 0 [expr {$hdrend - 1}]]
395 set comment [string range $contents [expr {$hdrend + 2}] end]
396 foreach line [split $header "\n"] {
397 set tag [lindex $line 0]
398 if {$tag == "author"} {
399 set audate [lindex $line end-1]
400 set auname [lrange $line 1 end-2]
401 } elseif {$tag == "committer"} {
402 set comdate [lindex $line end-1]
403 set comname [lrange $line 1 end-2]
Paul Mackerras1db95b02005-05-09 04:08:39 +0000404 }
405 }
Paul Mackerras232475d2005-11-15 10:34:03 +1100406 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +1000407 # take the first non-blank line of the comment as the headline
408 set headline [string trimleft $comment]
409 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +1100410 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +1000411 set headline [string range $headline 0 $i]
412 }
413 set headline [string trimright $headline]
414 set i [string first "\r" $headline]
415 if {$i >= 0} {
416 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +1100417 }
418 if {!$listed} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300419 # git rev-list indents the comment by 4 spaces;
420 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +1100421 set newcomment {}
422 foreach line [split $comment "\n"] {
423 append newcomment " "
424 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +1100425 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +1100426 }
427 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +0000428 }
429 if {$comdate != {}} {
Paul Mackerrascfb45632005-05-31 12:14:42 +0000430 set cdate($id) $comdate
Paul Mackerras1db95b02005-05-09 04:08:39 +0000431 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +0000432 set commitinfo($id) [list $headline $auname $audate \
433 $comname $comdate $comment]
Paul Mackerras1db95b02005-05-09 04:08:39 +0000434}
435
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100436proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +1000437 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +1100438
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100439 if {[info exists commitdata($id)]} {
440 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +1100441 } else {
442 readcommit $id
443 if {![info exists commitinfo($id)]} {
444 set commitinfo($id) {"No commit information available"}
Paul Mackerras8ed16482006-03-02 22:56:44 +1100445 }
446 }
447 return 1
448}
449
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000450proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000451 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000452 global otherrefids idotherrefs mainhead mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000453
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100454 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
455 catch {unset $v}
456 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000457 set refd [open [list | git show-ref -d] r]
458 while {[gets $refd line] >= 0} {
459 if {[string index $line 40] ne " "} continue
460 set id [string range $line 0 39]
461 set ref [string range $line 41 end]
462 if {![string match "refs/*" $ref]} continue
463 set name [string range $ref 5 end]
464 if {[string match "remotes/*" $name]} {
465 if {![string match "*/HEAD" $name]} {
466 set headids($name) $id
467 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000468 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000469 } elseif {[string match "heads/*" $name]} {
470 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800471 set headids($name) $id
472 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000473 } elseif {[string match "tags/*" $name]} {
474 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
475 # which is what we want since the former is the commit ID
476 set name [string range $name 5 end]
477 if {[string match "*^{}" $name]} {
478 set name [string range $name 0 end-3]
479 } else {
480 set tagobjid($name) $id
481 }
482 set tagids($name) $id
483 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800484 } else {
485 set otherrefids($name) $id
486 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000487 }
488 }
Alex Riesen062d6712007-07-29 22:28:40 +0200489 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +1000490 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000491 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +1000492 catch {
493 set thehead [exec git symbolic-ref HEAD]
494 if {[string match "refs/heads/*" $thehead]} {
495 set mainhead [string range $thehead 11 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000496 if {[info exists headids($mainhead)]} {
497 set mainheadid $headids($mainhead)
498 }
Paul Mackerras8a485712006-07-06 10:21:23 +1000499 }
500 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000501}
502
Paul Mackerras8f489362007-07-13 19:49:37 +1000503# skip over fake commits
504proc first_real_row {} {
505 global nullid nullid2 displayorder numcommits
506
507 for {set row 0} {$row < $numcommits} {incr row} {
508 set id [lindex $displayorder $row]
509 if {$id ne $nullid && $id ne $nullid2} {
510 break
511 }
512 }
513 return $row
514}
515
Paul Mackerrase11f1232007-06-16 20:29:25 +1000516# update things for a head moved to a child of its previous location
517proc movehead {id name} {
518 global headids idheads
519
520 removehead $headids($name) $name
521 set headids($name) $id
522 lappend idheads($id) $name
523}
524
525# update things when a head has been removed
526proc removehead {id name} {
527 global headids idheads
528
529 if {$idheads($id) eq $name} {
530 unset idheads($id)
531 } else {
532 set i [lsearch -exact $idheads($id) $name]
533 if {$i >= 0} {
534 set idheads($id) [lreplace $idheads($id) $i $i]
535 }
536 }
537 unset headids($name)
538}
539
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000540proc show_error {w top msg} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000541 message $w.m -text $msg -justify center -aspect 400
542 pack $w.m -side top -fill x -padx 20 -pady 20
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000543 button $w.ok -text OK -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000544 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000545 bind $top <Visibility> "grab $top; focus $top"
546 bind $top <Key-Return> "destroy $top"
547 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000548}
549
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000550proc error_popup msg {
551 set w .error
552 toplevel $w
553 wm transient $w .
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000554 show_error $w $w $msg
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000555}
556
Paul Mackerras10299152006-08-02 09:52:01 +1000557proc confirm_popup msg {
558 global confirm_ok
559 set confirm_ok 0
560 set w .confirm
561 toplevel $w
562 wm transient $w .
563 message $w.m -text $msg -justify center -aspect 400
564 pack $w.m -side top -fill x -padx 20 -pady 20
565 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
566 pack $w.ok -side left -fill x
567 button $w.cancel -text Cancel -command "destroy $w"
568 pack $w.cancel -side right -fill x
569 bind $w <Visibility> "grab $w; focus $w"
570 tkwait window $w
571 return $confirm_ok
572}
573
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000574proc makewindow {} {
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +1000575 global canv canv2 canv3 linespc charspc ctext cflist
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400576 global textfont mainfont uifont tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400577 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000578 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +0200579 global diffcontextstring diffcontext
Paul Mackerras94a2eed2005-08-07 15:27:57 +1000580 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000581 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000582 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000583 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -0400584 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Paul Mackerras10299152006-08-02 09:52:01 +1000585 global headctxmenu
Paul Mackerras9a40c502005-05-12 23:46:16 +0000586
587 menu .bar
588 .bar add cascade -label "File" -menu .bar.file
Keith Packard4840be62006-04-04 00:19:45 -0700589 .bar configure -font $uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +0000590 menu .bar.file
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000591 .bar.file add command -label "Update" -command updatecommits
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000592 .bar.file add command -label "Reread references" -command rereadrefs
Paul Mackerras887c9962007-08-20 19:36:20 +1000593 .bar.file add command -label "List references" -command showrefs
Paul Mackerras1d10f362005-05-15 12:55:47 +0000594 .bar.file add command -label "Quit" -command doquit
Keith Packard4840be62006-04-04 00:19:45 -0700595 .bar.file configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +1100596 menu .bar.edit
597 .bar add cascade -label "Edit" -menu .bar.edit
598 .bar.edit add command -label "Preferences" -command doprefs
Keith Packard4840be62006-04-04 00:19:45 -0700599 .bar.edit configure -font $uifont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000600
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +1000601 menu .bar.view -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000602 .bar add cascade -label "View" -menu .bar.view
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000603 .bar.view add command -label "New view..." -command {newview 0}
604 .bar.view add command -label "Edit view..." -command editview \
605 -state disabled
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000606 .bar.view add command -label "Delete view" -command delview -state disabled
607 .bar.view add separator
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000608 .bar.view add radiobutton -label "All files" -command {showview 0} \
609 -variable selectedview -value 0
Mark Levedahl40b87ff2007-02-01 08:44:46 -0500610
Paul Mackerras9a40c502005-05-12 23:46:16 +0000611 menu .bar.help
612 .bar add cascade -label "Help" -menu .bar.help
613 .bar.help add command -label "About gitk" -command about
Paul Mackerras4e95e1f2006-04-05 09:39:51 +1000614 .bar.help add command -label "Key bindings" -command keys
Keith Packard4840be62006-04-04 00:19:45 -0700615 .bar.help configure -font $uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +0000616 . configure -menu .bar
617
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500618 # the gui has upper and lower half, parts of a paned window.
Paul Mackerras0327d272005-05-10 00:23:42 +0000619 panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500620
621 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500622 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500623 set geometry(topheight) [expr {15 * $linespc}]
624 set geometry(topwidth) [expr {80 * $charspc}]
625 set geometry(botheight) [expr {15 * $linespc}]
626 set geometry(botwidth) [expr {50 * $charspc}]
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500627 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
628 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000629 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500630
631 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
632 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
633 frame .tf.histframe
634 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
635
636 # create three canvases
637 set cscroll .tf.histframe.csb
638 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500639 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -0400640 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000641 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100642 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500643 .tf.histframe.pwclist add $canv
644 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500645 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -0400646 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000647 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500648 .tf.histframe.pwclist add $canv2
649 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500650 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -0400651 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000652 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500653 .tf.histframe.pwclist add $canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500654 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
655 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Paul Mackerras98f350e2005-05-15 05:56:51 +0000656
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500657 # a scroll bar to rule them
658 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
659 pack $cscroll -side right -fill y
660 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
661 lappend bglist $canv $canv2 $canv3
662 pack .tf.histframe.pwclist -fill both -expand 1 -side left
663
664 # we have two button bars at bottom of top frame. Bar 1
665 frame .tf.bar
666 frame .tf.lbar -height 15
667
668 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000669 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500670 set sha1but .tf.bar.sha1label
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000671 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
Keith Packard4840be62006-04-04 00:19:45 -0700672 -command gotocommit -width 8 -font $uifont
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000673 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500674 pack .tf.bar.sha1label -side left
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000675 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
676 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +0000677 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +1000678
679 image create bitmap bm-left -data {
680 #define left_width 16
681 #define left_height 16
682 static unsigned char left_bits[] = {
683 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
684 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
685 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
686 }
687 image create bitmap bm-right -data {
688 #define right_width 16
689 #define right_height 16
690 static unsigned char right_bits[] = {
691 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
692 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
693 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
694 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500695 button .tf.bar.leftbut -image bm-left -command goback \
Paul Mackerrasd6982062005-08-06 22:06:06 +1000696 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500697 pack .tf.bar.leftbut -side left -fill y
698 button .tf.bar.rightbut -image bm-right -command goforw \
Paul Mackerrasd6982062005-08-06 22:06:06 +1000699 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500700 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +1000701
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500702 button .tf.bar.findbut -text "Find" -command dofind -font $uifont
703 pack .tf.bar.findbut -side left
Paul Mackerras98f350e2005-05-15 05:56:51 +0000704 set findstring {}
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500705 set fstring .tf.bar.findstring
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000706 lappend entries $fstring
Paul Mackerras908c3582006-05-20 09:38:11 +1000707 entry $fstring -width 30 -font $textfont -textvariable findstring
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000708 trace add variable findstring write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500709 pack $fstring -side left -expand 1 -fill x -in .tf.bar
Paul Mackerras98f350e2005-05-15 05:56:51 +0000710 set findtype Exact
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500711 set findtypemenu [tk_optionMenu .tf.bar.findtype \
712 findtype Exact IgnCase Regexp]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000713 trace add variable findtype write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500714 .tf.bar.findtype configure -font $uifont
715 .tf.bar.findtype.menu configure -font $uifont
Paul Mackerras98f350e2005-05-15 05:56:51 +0000716 set findloc "All fields"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500717 tk_optionMenu .tf.bar.findloc findloc "All fields" Headline \
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000718 Comments Author Committer
719 trace add variable findloc write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500720 .tf.bar.findloc configure -font $uifont
721 .tf.bar.findloc.menu configure -font $uifont
722 pack .tf.bar.findloc -side right
723 pack .tf.bar.findtype -side right
Paul Mackerrasb5721c72005-05-10 12:08:22 +0000724
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500725 # build up the bottom bar of upper window
726 label .tf.lbar.flabel -text "Highlight: Commits " \
727 -font $uifont
728 pack .tf.lbar.flabel -side left -fill y
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000729 set gdttype "touching paths:"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500730 set gm [tk_optionMenu .tf.lbar.gdttype gdttype "touching paths:" \
731 "adding/removing string:"]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000732 trace add variable gdttype write hfiles_change
733 $gm conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500734 .tf.lbar.gdttype conf -font $uifont
735 pack .tf.lbar.gdttype -side left -fill y
736 entry .tf.lbar.fent -width 25 -font $textfont \
Paul Mackerras908c3582006-05-20 09:38:11 +1000737 -textvariable highlight_files
738 trace add variable highlight_files write hfiles_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500739 lappend entries .tf.lbar.fent
740 pack .tf.lbar.fent -side left -fill x -expand 1
741 label .tf.lbar.vlabel -text " OR in view" -font $uifont
742 pack .tf.lbar.vlabel -side left -fill y
Paul Mackerras908c3582006-05-20 09:38:11 +1000743 global viewhlmenu selectedhlview
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500744 set viewhlmenu [tk_optionMenu .tf.lbar.vhl selectedhlview None]
Paul Mackerras3cd204e2006-11-23 21:06:16 +1100745 $viewhlmenu entryconf None -command delvhighlight
Paul Mackerras63b79192006-05-20 21:31:52 +1000746 $viewhlmenu conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500747 .tf.lbar.vhl conf -font $uifont
748 pack .tf.lbar.vhl -side left -fill y
749 label .tf.lbar.rlabel -text " OR " -font $uifont
750 pack .tf.lbar.rlabel -side left -fill y
Paul Mackerras164ff272006-05-29 19:50:02 +1000751 global highlight_related
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500752 set m [tk_optionMenu .tf.lbar.relm highlight_related None \
753 "Descendent" "Not descendent" "Ancestor" "Not ancestor"]
Paul Mackerras164ff272006-05-29 19:50:02 +1000754 $m conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500755 .tf.lbar.relm conf -font $uifont
Paul Mackerras164ff272006-05-29 19:50:02 +1000756 trace add variable highlight_related write vrel_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500757 pack .tf.lbar.relm -side left -fill y
Paul Mackerras908c3582006-05-20 09:38:11 +1000758
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500759 # Finish putting the upper half of the viewer together
760 pack .tf.lbar -in .tf -side bottom -fill x
761 pack .tf.bar -in .tf -side bottom -fill x
762 pack .tf.histframe -fill both -side top -expand 1
763 .ctop add .tf
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500764 .ctop paneconfigure .tf -height $geometry(topheight)
765 .ctop paneconfigure .tf -width $geometry(topwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500766
767 # now build up the bottom
768 panedwindow .pwbottom -orient horizontal
769
770 # lower left, a text box over search bar, scroll bar to the right
771 # if we know window height, then that will set the lower text height, otherwise
772 # we set lower text height which will drive window height
773 if {[info exists geometry(main)]} {
774 frame .bleft -width $geometry(botwidth)
775 } else {
776 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
777 }
778 frame .bleft.top
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000779 frame .bleft.mid
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500780
781 button .bleft.top.search -text "Search" -command dosearch \
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000782 -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500783 pack .bleft.top.search -side left -padx 5
784 set sstring .bleft.top.sstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000785 entry $sstring -width 20 -font $textfont -textvariable searchstring
786 lappend entries $sstring
787 trace add variable searchstring write incrsearch
788 pack $sstring -side left -expand 1 -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000789 radiobutton .bleft.mid.diff -text "Diff" \
790 -command changediffdisp -variable diffelide -value {0 0}
791 radiobutton .bleft.mid.old -text "Old version" \
792 -command changediffdisp -variable diffelide -value {0 1}
793 radiobutton .bleft.mid.new -text "New version" \
794 -command changediffdisp -variable diffelide -value {1 0}
Steffen Prohaska890fae72007-08-12 12:05:46 +0200795 label .bleft.mid.labeldiffcontext -text " Lines of context: " \
796 -font $uifont
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000797 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Steffen Prohaska890fae72007-08-12 12:05:46 +0200798 spinbox .bleft.mid.diffcontext -width 5 -font $textfont \
799 -from 1 -increment 1 -to 10000000 \
800 -validate all -validatecommand "diffcontextvalidate %P" \
801 -textvariable diffcontextstring
802 .bleft.mid.diffcontext set $diffcontext
803 trace add variable diffcontextstring write diffcontextchange
804 lappend entries .bleft.mid.diffcontext
805 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500806 set ctext .bleft.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000807 text $ctext -background $bgcolor -foreground $fgcolor \
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400808 -tabs "[expr {$tabstop * $charspc}]" \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000809 -state disabled -font $textfont \
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000810 -yscrollcommand scrolltext -wrap none
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500811 scrollbar .bleft.sb -command "$ctext yview"
812 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000813 pack .bleft.mid -side top -fill x
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500814 pack .bleft.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000815 pack $ctext -side left -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000816 lappend bglist $ctext
817 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000818
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400819 $ctext tag conf comment -wrap $wrapcomment
Paul Mackerrasf0654862005-07-18 14:29:03 -0400820 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000821 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
822 $ctext tag conf d0 -fore [lindex $diffcolors 0]
823 $ctext tag conf d1 -fore [lindex $diffcolors 1]
Paul Mackerras712fcc02005-11-30 09:28:16 +1100824 $ctext tag conf m0 -fore red
825 $ctext tag conf m1 -fore blue
826 $ctext tag conf m2 -fore green
827 $ctext tag conf m3 -fore purple
828 $ctext tag conf m4 -fore brown
Paul Mackerrasb77b0272006-02-07 09:13:52 +1100829 $ctext tag conf m5 -fore "#009090"
830 $ctext tag conf m6 -fore magenta
831 $ctext tag conf m7 -fore "#808000"
832 $ctext tag conf m8 -fore "#009000"
833 $ctext tag conf m9 -fore "#ff0080"
834 $ctext tag conf m10 -fore cyan
835 $ctext tag conf m11 -fore "#b07070"
836 $ctext tag conf m12 -fore "#70b0f0"
837 $ctext tag conf m13 -fore "#70f0b0"
838 $ctext tag conf m14 -fore "#f0b070"
839 $ctext tag conf m15 -fore "#ff70b0"
Paul Mackerras712fcc02005-11-30 09:28:16 +1100840 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +1100841 set mergemax 16
Paul Mackerras712fcc02005-11-30 09:28:16 +1100842 $ctext tag conf mresult -font [concat $textfont bold]
843 $ctext tag conf msep -font [concat $textfont bold]
844 $ctext tag conf found -back yellow
Paul Mackerrase5c2d852005-05-11 23:44:54 +0000845
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500846 .pwbottom add .bleft
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500847 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500848
849 # lower right
850 frame .bright
851 frame .bright.mode
852 radiobutton .bright.mode.patch -text "Patch" \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000853 -command reselectline -variable cmitmode -value "patch"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +0400854 .bright.mode.patch configure -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500855 radiobutton .bright.mode.tree -text "Tree" \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000856 -command reselectline -variable cmitmode -value "tree"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +0400857 .bright.mode.tree configure -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500858 grid .bright.mode.patch .bright.mode.tree -sticky ew
859 pack .bright.mode -side top -fill x
860 set cflist .bright.cfiles
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000861 set indent [font measure $mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500862 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -0400863 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000864 -background $bgcolor -foreground $fgcolor \
865 -font $mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000866 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500867 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000868 -cursor [. cget -cursor] \
869 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000870 lappend bglist $cflist
871 lappend fglist $cflist
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500872 scrollbar .bright.sb -command "$cflist yview"
873 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000874 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +1000875 $cflist tag configure highlight \
876 -background [$cflist cget -selectbackground]
Paul Mackerras63b79192006-05-20 21:31:52 +1000877 $cflist tag configure bold -font [concat $mainfont bold]
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000878
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500879 .pwbottom add .bright
880 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +0000881
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500882 # restore window position if known
883 if {[info exists geometry(main)]} {
884 wm geometry . "$geometry(main)"
885 }
886
Shawn O. Pearced23d98d2007-07-19 00:37:58 -0400887 if {[tk windowingsystem] eq {aqua}} {
888 set M1B M1
889 } else {
890 set M1B Control
891 }
892
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500893 bind .pwbottom <Configure> {resizecdetpanes %W %w}
894 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +1000895 bindall <1> {selcanvline %W %x %y}
896 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -0400897 if {[tk windowingsystem] == "win32"} {
898 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
899 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
900 } else {
901 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
902 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
903 }
Paul Mackerrasbe0cd092006-03-31 09:55:11 +1100904 bindall <2> "canvscan mark %W %x %y"
905 bindall <B2-Motion> "canvscan dragto %W %x %y"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +1000906 bindkey <Home> selfirstline
907 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +0000908 bind . <Key-Up> "selnextline -1"
909 bind . <Key-Down> "selnextline 1"
Paul Mackerras4e7d6772006-05-30 21:33:07 +1000910 bind . <Shift-Key-Up> "next_highlight -1"
911 bind . <Shift-Key-Down> "next_highlight 1"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +1000912 bindkey <Key-Right> "goforw"
913 bindkey <Key-Left> "goback"
914 bind . <Key-Prior> "selnextpage -1"
915 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -0400916 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
917 bind . <$M1B-End> "allcanvs yview moveto 1.0"
918 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
919 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
920 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
921 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +0000922 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
923 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
924 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000925 bindkey p "selnextline -1"
926 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +1000927 bindkey z "goback"
928 bindkey x "goforw"
929 bindkey i "selnextline -1"
930 bindkey k "selnextline 1"
931 bindkey j "goback"
932 bindkey l "goforw"
Paul Mackerrascfb45632005-05-31 12:14:42 +0000933 bindkey b "$ctext yview scroll -1 pages"
934 bindkey d "$ctext yview scroll 18 units"
935 bindkey u "$ctext yview scroll -18 units"
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400936 bindkey / {findnext 1}
937 bindkey <Key-Return> {findnext 0}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000938 bindkey ? findprev
Paul Mackerras39ad8572005-05-19 12:35:53 +0000939 bindkey f nextfile
Eric Wonge7a09192007-02-23 12:36:34 -0800940 bindkey <F5> updatecommits
Shawn O. Pearced23d98d2007-07-19 00:37:58 -0400941 bind . <$M1B-q> doquit
942 bind . <$M1B-f> dofind
943 bind . <$M1B-g> {findnext 0}
944 bind . <$M1B-r> dosearchback
945 bind . <$M1B-s> dosearch
946 bind . <$M1B-equal> {incrfont 1}
947 bind . <$M1B-KP_Add> {incrfont 1}
948 bind . <$M1B-minus> {incrfont -1}
949 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -0500950 wm protocol . WM_DELETE_WINDOW doquit
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000951 bind . <Button-1> "click %W"
Paul Mackerras17386062005-05-18 22:51:00 +0000952 bind $fstring <Key-Return> dofind
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000953 bind $sha1entry <Key-Return> gotocommit
Paul Mackerrasee3dc722005-06-25 16:37:13 +1000954 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000955 bind $cflist <1> {sel_flist %W %x %y; break}
956 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000957 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerras32447292007-07-27 22:30:15 +1000958 bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
Paul Mackerrasea13cba2005-06-16 10:54:04 +0000959
960 set maincursor [. cget -cursor]
961 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +1000962 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +0000963
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +1000964 set rowctxmenu .rowctxmenu
965 menu $rowctxmenu -tearoff 0
966 $rowctxmenu add command -label "Diff this -> selected" \
967 -command {diffvssel 0}
968 $rowctxmenu add command -label "Diff selected -> this" \
969 -command {diffvssel 1}
Paul Mackerras74daedb2005-06-27 19:27:32 +1000970 $rowctxmenu add command -label "Make patch" -command mkpatch
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +1000971 $rowctxmenu add command -label "Create tag" -command mktag
Paul Mackerras4a2139f2005-06-29 09:47:48 +1000972 $rowctxmenu add command -label "Write commit to file" -command writecommit
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +1000973 $rowctxmenu add command -label "Create new branch" -command mkbranch
Paul Mackerrasca6d8f52006-08-06 21:08:05 +1000974 $rowctxmenu add command -label "Cherry-pick this commit" \
975 -command cherrypick
Paul Mackerras6fb735a2006-10-19 10:09:06 +1000976 $rowctxmenu add command -label "Reset HEAD branch to here" \
977 -command resethead
Paul Mackerras10299152006-08-02 09:52:01 +1000978
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000979 set fakerowmenu .fakerowmenu
980 menu $fakerowmenu -tearoff 0
981 $fakerowmenu add command -label "Diff this -> selected" \
982 -command {diffvssel 0}
983 $fakerowmenu add command -label "Diff selected -> this" \
984 -command {diffvssel 1}
985 $fakerowmenu add command -label "Make patch" -command mkpatch
986# $fakerowmenu add command -label "Commit" -command {mkcommit 0}
987# $fakerowmenu add command -label "Commit all" -command {mkcommit 1}
988# $fakerowmenu add command -label "Revert local changes" -command revertlocal
989
Paul Mackerras10299152006-08-02 09:52:01 +1000990 set headctxmenu .headctxmenu
991 menu $headctxmenu -tearoff 0
992 $headctxmenu add command -label "Check out this branch" \
993 -command cobranch
994 $headctxmenu add command -label "Remove this branch" \
995 -command rmbranch
Paul Mackerras32447292007-07-27 22:30:15 +1000996
997 global flist_menu
998 set flist_menu .flistctxmenu
999 menu $flist_menu -tearoff 0
1000 $flist_menu add command -label "Highlight this too" \
1001 -command {flist_hl 0}
1002 $flist_menu add command -label "Highlight this only" \
1003 -command {flist_hl 1}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001004}
1005
Mark Levedahl314c3092007-08-07 21:40:35 -04001006# Windows sends all mouse wheel events to the current focused window, not
1007# the one where the mouse hovers, so bind those events here and redirect
1008# to the correct window
1009proc windows_mousewheel_redirector {W X Y D} {
1010 global canv canv2 canv3
1011 set w [winfo containing -displayof $W $X $Y]
1012 if {$w ne ""} {
1013 set u [expr {$D < 0 ? 5 : -5}]
1014 if {$w == $canv || $w == $canv2 || $w == $canv3} {
1015 allcanvs yview scroll $u units
1016 } else {
1017 catch {
1018 $w yview scroll $u units
1019 }
1020 }
1021 }
1022}
1023
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11001024# mouse-2 makes all windows scan vertically, but only the one
1025# the cursor is in scans horizontally
1026proc canvscan {op w x y} {
1027 global canv canv2 canv3
1028 foreach c [list $canv $canv2 $canv3] {
1029 if {$c == $w} {
1030 $c scan $op $x $y
1031 } else {
1032 $c scan $op 0 $y
1033 }
1034 }
1035}
1036
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001037proc scrollcanv {cscroll f0 f1} {
1038 $cscroll set $f0 $f1
1039 drawfrac $f0 $f1
Paul Mackerras908c3582006-05-20 09:38:11 +10001040 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001041}
1042
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001043# when we make a key binding for the toplevel, make sure
1044# it doesn't get triggered when that key is pressed in the
1045# find string entry widget.
1046proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001047 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001048 bind . $ev $script
1049 set escript [bind Entry $ev]
1050 if {$escript == {}} {
1051 set escript [bind Entry <Key>]
1052 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001053 foreach e $entries {
1054 bind $e $ev "$escript; break"
1055 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001056}
1057
1058# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001059# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001060proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04001061 global ctext entries
1062 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001063 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001064 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001065 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001066}
1067
1068proc savestuff {w} {
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04001069 global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11001070 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001071 global maxwidth showneartags showlocalchanges
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001072 global viewname viewfiles viewargs viewperm nextviewnum
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02001073 global cmitmode wrapcomment datetimeformat
Steffen Prohaska890fae72007-08-12 12:05:46 +02001074 global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
Paul Mackerras4ef17532005-07-27 22:16:51 -05001075
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001076 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001077 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001078 catch {
1079 set f [open "~/.gitk-new" w]
Paul Mackerrasf0654862005-07-18 14:29:03 -04001080 puts $f [list set mainfont $mainfont]
1081 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07001082 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04001083 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04001084 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10001085 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10001086 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001087 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04001088 puts $f [list set wrapcomment $wrapcomment]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10001089 puts $f [list set showneartags $showneartags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001090 puts $f [list set showlocalchanges $showlocalchanges]
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02001091 puts $f [list set datetimeformat $datetimeformat]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001092 puts $f [list set bgcolor $bgcolor]
1093 puts $f [list set fgcolor $fgcolor]
1094 puts $f [list set colors $colors]
1095 puts $f [list set diffcolors $diffcolors]
Steffen Prohaska890fae72007-08-12 12:05:46 +02001096 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04001097 puts $f [list set selectbgcolor $selectbgcolor]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001098
Mark Levedahlb6047c52007-02-08 22:22:24 -05001099 puts $f "set geometry(main) [wm geometry .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001100 puts $f "set geometry(topwidth) [winfo width .tf]"
1101 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001102 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
1103 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001104 puts $f "set geometry(botwidth) [winfo width .bleft]"
1105 puts $f "set geometry(botheight) [winfo height .bleft]"
1106
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001107 puts -nonewline $f "set permviews {"
1108 for {set v 0} {$v < $nextviewnum} {incr v} {
1109 if {$viewperm($v)} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001110 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001111 }
1112 }
1113 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001114 close $f
1115 file rename -force "~/.gitk-new" "~/.gitk"
1116 }
1117 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00001118}
1119
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001120proc resizeclistpanes {win w} {
1121 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11001122 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001123 set s0 [$win sash coord 0]
1124 set s1 [$win sash coord 1]
1125 if {$w < 60} {
1126 set sash0 [expr {int($w/2 - 2)}]
1127 set sash1 [expr {int($w*5/6 - 2)}]
1128 } else {
1129 set factor [expr {1.0 * $w / $oldwidth($win)}]
1130 set sash0 [expr {int($factor * [lindex $s0 0])}]
1131 set sash1 [expr {int($factor * [lindex $s1 0])}]
1132 if {$sash0 < 30} {
1133 set sash0 30
1134 }
1135 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001136 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001137 }
1138 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001139 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001140 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001141 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001142 }
1143 }
1144 }
1145 $win sash place 0 $sash0 [lindex $s0 1]
1146 $win sash place 1 $sash1 [lindex $s1 1]
1147 }
1148 set oldwidth($win) $w
1149}
1150
1151proc resizecdetpanes {win w} {
1152 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11001153 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001154 set s0 [$win sash coord 0]
1155 if {$w < 60} {
1156 set sash0 [expr {int($w*3/4 - 2)}]
1157 } else {
1158 set factor [expr {1.0 * $w / $oldwidth($win)}]
1159 set sash0 [expr {int($factor * [lindex $s0 0])}]
1160 if {$sash0 < 45} {
1161 set sash0 45
1162 }
1163 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001164 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001165 }
1166 }
1167 $win sash place 0 $sash0 [lindex $s0 1]
1168 }
1169 set oldwidth($win) $w
1170}
1171
Paul Mackerrasb5721c72005-05-10 12:08:22 +00001172proc allcanvs args {
1173 global canv canv2 canv3
1174 eval $canv $args
1175 eval $canv2 $args
1176 eval $canv3 $args
1177}
1178
1179proc bindall {event action} {
1180 global canv canv2 canv3
1181 bind $canv $event $action
1182 bind $canv2 $event $action
1183 bind $canv3 $event $action
1184}
1185
Paul Mackerras9a40c502005-05-12 23:46:16 +00001186proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001187 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00001188 set w .about
1189 if {[winfo exists $w]} {
1190 raise $w
1191 return
1192 }
1193 toplevel $w
1194 wm title $w "About gitk"
1195 message $w.m -text {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001196Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00001197
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001198Copyright © 2005-2006 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00001199
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10001200Use and redistribute under the terms of the GNU General Public License} \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001201 -justify center -aspect 400 -border 2 -bg white -relief groove
1202 pack $w.m -side top -fill x -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001203 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001204 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00001205 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001206 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001207 bind $w <Visibility> "focus $w.ok"
1208 bind $w <Key-Escape> "destroy $w"
1209 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00001210}
1211
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001212proc keys {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001213 global uifont
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001214 set w .keys
1215 if {[winfo exists $w]} {
1216 raise $w
1217 return
1218 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001219 if {[tk windowingsystem] eq {aqua}} {
1220 set M1T Cmd
1221 } else {
1222 set M1T Ctrl
1223 }
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001224 toplevel $w
1225 wm title $w "Gitk key bindings"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001226 message $w.m -text "
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001227Gitk key bindings:
1228
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001229<$M1T-Q> Quit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001230<Home> Move to first commit
1231<End> Move to last commit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001232<Up>, p, i Move up one commit
1233<Down>, n, k Move down one commit
1234<Left>, z, j Go back in history list
1235<Right>, x, l Go forward in history list
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001236<PageUp> Move up one page in commit list
1237<PageDown> Move down one page in commit list
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001238<$M1T-Home> Scroll to top of commit list
1239<$M1T-End> Scroll to bottom of commit list
1240<$M1T-Up> Scroll commit list up one line
1241<$M1T-Down> Scroll commit list down one line
1242<$M1T-PageUp> Scroll commit list up one page
1243<$M1T-PageDown> Scroll commit list down one page
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001244<Shift-Up> Move to previous highlighted line
1245<Shift-Down> Move to next highlighted line
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001246<Delete>, b Scroll diff view up one page
1247<Backspace> Scroll diff view up one page
1248<Space> Scroll diff view down one page
1249u Scroll diff view up 18 lines
1250d Scroll diff view down 18 lines
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001251<$M1T-F> Find
1252<$M1T-G> Move to next find hit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001253<Return> Move to next find hit
1254/ Move to next find hit, or redo find
1255? Move to previous find hit
1256f Scroll diff view to next file
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001257<$M1T-S> Search for next hit in diff view
1258<$M1T-R> Search for previous hit in diff view
1259<$M1T-KP+> Increase font size
1260<$M1T-plus> Increase font size
1261<$M1T-KP-> Decrease font size
1262<$M1T-minus> Decrease font size
Eric Wonge7a09192007-02-23 12:36:34 -08001263<F5> Update
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001264" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001265 -justify left -bg white -border 2 -relief groove
1266 pack $w.m -side top -fill both -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001267 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001268 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001269 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001270 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001271 bind $w <Visibility> "focus $w.ok"
1272 bind $w <Key-Escape> "destroy $w"
1273 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001274}
1275
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001276# Procedures for manipulating the file list window at the
1277# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001278
1279proc treeview {w l openlevs} {
1280 global treecontents treediropen treeheight treeparent treeindex
1281
1282 set ix 0
1283 set treeindex() 0
1284 set lev 0
1285 set prefix {}
1286 set prefixend -1
1287 set prefendstack {}
1288 set htstack {}
1289 set ht 0
1290 set treecontents() {}
1291 $w conf -state normal
1292 foreach f $l {
1293 while {[string range $f 0 $prefixend] ne $prefix} {
1294 if {$lev <= $openlevs} {
1295 $w mark set e:$treeindex($prefix) "end -1c"
1296 $w mark gravity e:$treeindex($prefix) left
1297 }
1298 set treeheight($prefix) $ht
1299 incr ht [lindex $htstack end]
1300 set htstack [lreplace $htstack end end]
1301 set prefixend [lindex $prefendstack end]
1302 set prefendstack [lreplace $prefendstack end end]
1303 set prefix [string range $prefix 0 $prefixend]
1304 incr lev -1
1305 }
1306 set tail [string range $f [expr {$prefixend+1}] end]
1307 while {[set slash [string first "/" $tail]] >= 0} {
1308 lappend htstack $ht
1309 set ht 0
1310 lappend prefendstack $prefixend
1311 incr prefixend [expr {$slash + 1}]
1312 set d [string range $tail 0 $slash]
1313 lappend treecontents($prefix) $d
1314 set oldprefix $prefix
1315 append prefix $d
1316 set treecontents($prefix) {}
1317 set treeindex($prefix) [incr ix]
1318 set treeparent($prefix) $oldprefix
1319 set tail [string range $tail [expr {$slash+1}] end]
1320 if {$lev <= $openlevs} {
1321 set ht 1
1322 set treediropen($prefix) [expr {$lev < $openlevs}]
1323 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
1324 $w mark set d:$ix "end -1c"
1325 $w mark gravity d:$ix left
1326 set str "\n"
1327 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1328 $w insert end $str
1329 $w image create end -align center -image $bm -padx 1 \
1330 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10001331 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001332 $w mark set s:$ix "end -1c"
1333 $w mark gravity s:$ix left
1334 }
1335 incr lev
1336 }
1337 if {$tail ne {}} {
1338 if {$lev <= $openlevs} {
1339 incr ht
1340 set str "\n"
1341 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1342 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001343 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001344 }
1345 lappend treecontents($prefix) $tail
1346 }
1347 }
1348 while {$htstack ne {}} {
1349 set treeheight($prefix) $ht
1350 incr ht [lindex $htstack end]
1351 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05001352 set prefixend [lindex $prefendstack end]
1353 set prefendstack [lreplace $prefendstack end end]
1354 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001355 }
1356 $w conf -state disabled
1357}
1358
1359proc linetoelt {l} {
1360 global treeheight treecontents
1361
1362 set y 2
1363 set prefix {}
1364 while {1} {
1365 foreach e $treecontents($prefix) {
1366 if {$y == $l} {
1367 return "$prefix$e"
1368 }
1369 set n 1
1370 if {[string index $e end] eq "/"} {
1371 set n $treeheight($prefix$e)
1372 if {$y + $n > $l} {
1373 append prefix $e
1374 incr y
1375 break
1376 }
1377 }
1378 incr y $n
1379 }
1380 }
1381}
1382
Paul Mackerras45a9d502006-05-20 22:56:27 +10001383proc highlight_tree {y prefix} {
1384 global treeheight treecontents cflist
1385
1386 foreach e $treecontents($prefix) {
1387 set path $prefix$e
1388 if {[highlight_tag $path] ne {}} {
1389 $cflist tag add bold $y.0 "$y.0 lineend"
1390 }
1391 incr y
1392 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
1393 set y [highlight_tree $y $path]
1394 }
1395 }
1396 return $y
1397}
1398
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001399proc treeclosedir {w dir} {
1400 global treediropen treeheight treeparent treeindex
1401
1402 set ix $treeindex($dir)
1403 $w conf -state normal
1404 $w delete s:$ix e:$ix
1405 set treediropen($dir) 0
1406 $w image configure a:$ix -image tri-rt
1407 $w conf -state disabled
1408 set n [expr {1 - $treeheight($dir)}]
1409 while {$dir ne {}} {
1410 incr treeheight($dir) $n
1411 set dir $treeparent($dir)
1412 }
1413}
1414
1415proc treeopendir {w dir} {
1416 global treediropen treeheight treeparent treecontents treeindex
1417
1418 set ix $treeindex($dir)
1419 $w conf -state normal
1420 $w image configure a:$ix -image tri-dn
1421 $w mark set e:$ix s:$ix
1422 $w mark gravity e:$ix right
1423 set lev 0
1424 set str "\n"
1425 set n [llength $treecontents($dir)]
1426 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
1427 incr lev
1428 append str "\t"
1429 incr treeheight($x) $n
1430 }
1431 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001432 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001433 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001434 set iy $treeindex($de)
1435 $w mark set d:$iy e:$ix
1436 $w mark gravity d:$iy left
1437 $w insert e:$ix $str
1438 set treediropen($de) 0
1439 $w image create e:$ix -align center -image tri-rt -padx 1 \
1440 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10001441 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001442 $w mark set s:$iy e:$ix
1443 $w mark gravity s:$iy left
1444 set treeheight($de) 1
1445 } else {
1446 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001447 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001448 }
1449 }
1450 $w mark gravity e:$ix left
1451 $w conf -state disabled
1452 set treediropen($dir) 1
1453 set top [lindex [split [$w index @0,0] .] 0]
1454 set ht [$w cget -height]
1455 set l [lindex [split [$w index s:$ix] .] 0]
1456 if {$l < $top} {
1457 $w yview $l.0
1458 } elseif {$l + $n + 1 > $top + $ht} {
1459 set top [expr {$l + $n + 2 - $ht}]
1460 if {$l < $top} {
1461 set top $l
1462 }
1463 $w yview $top.0
1464 }
1465}
1466
1467proc treeclick {w x y} {
1468 global treediropen cmitmode ctext cflist cflist_top
1469
1470 if {$cmitmode ne "tree"} return
1471 if {![info exists cflist_top]} return
1472 set l [lindex [split [$w index "@$x,$y"] "."] 0]
1473 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1474 $cflist tag add highlight $l.0 "$l.0 lineend"
1475 set cflist_top $l
1476 if {$l == 1} {
1477 $ctext yview 1.0
1478 return
1479 }
1480 set e [linetoelt $l]
1481 if {[string index $e end] ne "/"} {
1482 showfile $e
1483 } elseif {$treediropen($e)} {
1484 treeclosedir $w $e
1485 } else {
1486 treeopendir $w $e
1487 }
1488}
1489
1490proc setfilelist {id} {
1491 global treefilelist cflist
1492
1493 treeview $cflist $treefilelist($id) 0
1494}
1495
1496image create bitmap tri-rt -background black -foreground blue -data {
1497 #define tri-rt_width 13
1498 #define tri-rt_height 13
1499 static unsigned char tri-rt_bits[] = {
1500 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
1501 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
1502 0x00, 0x00};
1503} -maskdata {
1504 #define tri-rt-mask_width 13
1505 #define tri-rt-mask_height 13
1506 static unsigned char tri-rt-mask_bits[] = {
1507 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
1508 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
1509 0x08, 0x00};
1510}
1511image create bitmap tri-dn -background black -foreground blue -data {
1512 #define tri-dn_width 13
1513 #define tri-dn_height 13
1514 static unsigned char tri-dn_bits[] = {
1515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
1516 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1517 0x00, 0x00};
1518} -maskdata {
1519 #define tri-dn-mask_width 13
1520 #define tri-dn-mask_height 13
1521 static unsigned char tri-dn-mask_bits[] = {
1522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
1523 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
1524 0x00, 0x00};
1525}
1526
Paul Mackerras887c9962007-08-20 19:36:20 +10001527image create bitmap reficon-T -background black -foreground yellow -data {
1528 #define tagicon_width 13
1529 #define tagicon_height 9
1530 static unsigned char tagicon_bits[] = {
1531 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
1532 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
1533} -maskdata {
1534 #define tagicon-mask_width 13
1535 #define tagicon-mask_height 9
1536 static unsigned char tagicon-mask_bits[] = {
1537 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
1538 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
1539}
1540set rectdata {
1541 #define headicon_width 13
1542 #define headicon_height 9
1543 static unsigned char headicon_bits[] = {
1544 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
1545 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
1546}
1547set rectmask {
1548 #define headicon-mask_width 13
1549 #define headicon-mask_height 9
1550 static unsigned char headicon-mask_bits[] = {
1551 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
1552 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
1553}
1554image create bitmap reficon-H -background black -foreground green \
1555 -data $rectdata -maskdata $rectmask
1556image create bitmap reficon-o -background black -foreground "#ddddff" \
1557 -data $rectdata -maskdata $rectmask
1558
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001559proc init_flist {first} {
Paul Mackerras89b11d32006-05-02 19:55:31 +10001560 global cflist cflist_top selectedline difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001561
1562 $cflist conf -state normal
1563 $cflist delete 0.0 end
1564 if {$first ne {}} {
1565 $cflist insert end $first
1566 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001567 $cflist tag add highlight 1.0 "1.0 lineend"
1568 } else {
1569 catch {unset cflist_top}
1570 }
1571 $cflist conf -state disabled
1572 set difffilestart {}
1573}
1574
Paul Mackerras63b79192006-05-20 21:31:52 +10001575proc highlight_tag {f} {
1576 global highlight_paths
1577
1578 foreach p $highlight_paths {
1579 if {[string match $p $f]} {
1580 return "bold"
1581 }
1582 }
1583 return {}
1584}
1585
1586proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001587 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001588
Paul Mackerras45a9d502006-05-20 22:56:27 +10001589 $cflist conf -state normal
1590 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10001591 set end [lindex [split [$cflist index end] .] 0]
1592 for {set l 2} {$l < $end} {incr l} {
1593 set line [$cflist get $l.0 "$l.0 lineend"]
1594 if {[highlight_tag $line] ne {}} {
1595 $cflist tag add bold $l.0 "$l.0 lineend"
1596 }
1597 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001598 } else {
1599 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10001600 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001601 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001602}
1603
1604proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001605 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001606
Paul Mackerras45a9d502006-05-20 22:56:27 +10001607 $cflist conf -state normal
1608 $cflist tag remove bold 1.0 end
1609 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001610}
1611
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001612proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001613 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001614
Paul Mackerras45a9d502006-05-20 22:56:27 +10001615 $cflist conf -state normal
1616 foreach f $fl {
1617 $cflist insert end "\n"
1618 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001619 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001620 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001621}
1622
1623proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001624 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001625
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001626 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001627 if {![info exists cflist_top]} return
1628 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10001629 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1630 $cflist tag add highlight $l.0 "$l.0 lineend"
1631 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001632 if {$l == 1} {
1633 $ctext yview 1.0
1634 } else {
1635 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001636 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001637}
1638
Paul Mackerras32447292007-07-27 22:30:15 +10001639proc pop_flist_menu {w X Y x y} {
1640 global ctext cflist cmitmode flist_menu flist_menu_file
1641 global treediffs diffids
1642
1643 set l [lindex [split [$w index "@$x,$y"] "."] 0]
1644 if {$l <= 1} return
1645 if {$cmitmode eq "tree"} {
1646 set e [linetoelt $l]
1647 if {[string index $e end] eq "/"} return
1648 } else {
1649 set e [lindex $treediffs($diffids) [expr {$l-2}]]
1650 }
1651 set flist_menu_file $e
1652 tk_popup $flist_menu $X $Y
1653}
1654
1655proc flist_hl {only} {
1656 global flist_menu_file highlight_files
1657
1658 set x [shellquote $flist_menu_file]
1659 if {$only || $highlight_files eq {}} {
1660 set highlight_files $x
1661 } else {
1662 append highlight_files " " $x
1663 }
1664}
1665
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001666# Functions for adding and removing shell-type quoting
1667
1668proc shellquote {str} {
1669 if {![string match "*\['\"\\ \t]*" $str]} {
1670 return $str
1671 }
1672 if {![string match "*\['\"\\]*" $str]} {
1673 return "\"$str\""
1674 }
1675 if {![string match "*'*" $str]} {
1676 return "'$str'"
1677 }
1678 return "\"[string map {\" \\\" \\ \\\\} $str]\""
1679}
1680
1681proc shellarglist {l} {
1682 set str {}
1683 foreach a $l {
1684 if {$str ne {}} {
1685 append str " "
1686 }
1687 append str [shellquote $a]
1688 }
1689 return $str
1690}
1691
1692proc shelldequote {str} {
1693 set ret {}
1694 set used -1
1695 while {1} {
1696 incr used
1697 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
1698 append ret [string range $str $used end]
1699 set used [string length $str]
1700 break
1701 }
1702 set first [lindex $first 0]
1703 set ch [string index $str $first]
1704 if {$first > $used} {
1705 append ret [string range $str $used [expr {$first - 1}]]
1706 set used $first
1707 }
1708 if {$ch eq " " || $ch eq "\t"} break
1709 incr used
1710 if {$ch eq "'"} {
1711 set first [string first "'" $str $used]
1712 if {$first < 0} {
1713 error "unmatched single-quote"
1714 }
1715 append ret [string range $str $used [expr {$first - 1}]]
1716 set used $first
1717 continue
1718 }
1719 if {$ch eq "\\"} {
1720 if {$used >= [string length $str]} {
1721 error "trailing backslash"
1722 }
1723 append ret [string index $str $used]
1724 continue
1725 }
1726 # here ch == "\""
1727 while {1} {
1728 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
1729 error "unmatched double-quote"
1730 }
1731 set first [lindex $first 0]
1732 set ch [string index $str $first]
1733 if {$first > $used} {
1734 append ret [string range $str $used [expr {$first - 1}]]
1735 set used $first
1736 }
1737 if {$ch eq "\""} break
1738 incr used
1739 append ret [string index $str $used]
1740 incr used
1741 }
1742 }
1743 return [list $used $ret]
1744}
1745
1746proc shellsplit {str} {
1747 set l {}
1748 while {1} {
1749 set str [string trimleft $str]
1750 if {$str eq {}} break
1751 set dq [shelldequote $str]
1752 set n [lindex $dq 0]
1753 set word [lindex $dq 1]
1754 set str [string range $str $n end]
1755 lappend l $word
1756 }
1757 return $l
1758}
1759
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001760# Code to implement multiple views
1761
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001762proc newview {ishighlight} {
1763 global nextviewnum newviewname newviewperm uifont newishighlight
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001764 global newviewargs revtreeargs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001765
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001766 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001767 set top .gitkview
1768 if {[winfo exists $top]} {
1769 raise $top
1770 return
1771 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001772 set newviewname($nextviewnum) "View $nextviewnum"
1773 set newviewperm($nextviewnum) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001774 set newviewargs($nextviewnum) [shellarglist $revtreeargs]
Mark Levedahl40b87ff2007-02-01 08:44:46 -05001775 vieweditor $top $nextviewnum "Gitk view definition"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001776}
1777
1778proc editview {} {
1779 global curview
1780 global viewname viewperm newviewname newviewperm
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001781 global viewargs newviewargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001782
1783 set top .gitkvedit-$curview
1784 if {[winfo exists $top]} {
1785 raise $top
1786 return
1787 }
1788 set newviewname($curview) $viewname($curview)
1789 set newviewperm($curview) $viewperm($curview)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001790 set newviewargs($curview) [shellarglist $viewargs($curview)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001791 vieweditor $top $curview "Gitk: edit view $viewname($curview)"
1792}
1793
1794proc vieweditor {top n title} {
1795 global newviewname newviewperm viewfiles
1796 global uifont
1797
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001798 toplevel $top
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001799 wm title $top $title
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001800 label $top.nl -text "Name" -font $uifont
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001801 entry $top.name -width 20 -textvariable newviewname($n) -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001802 grid $top.nl $top.name -sticky w -pady 5
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001803 checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) \
1804 -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001805 grid $top.perm - -pady 5 -sticky w
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001806 message $top.al -aspect 1000 -font $uifont \
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001807 -text "Commits to include (arguments to git rev-list):"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001808 grid $top.al - -sticky w -pady 5
1809 entry $top.args -width 50 -textvariable newviewargs($n) \
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001810 -background white -font $uifont
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001811 grid $top.args - -sticky ew -padx 5
1812 message $top.l -aspect 1000 -font $uifont \
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001813 -text "Enter files and directories to include, one per line:"
1814 grid $top.l - -sticky w
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001815 text $top.t -width 40 -height 10 -background white -font $uifont
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001816 if {[info exists viewfiles($n)]} {
1817 foreach f $viewfiles($n) {
1818 $top.t insert end $f
1819 $top.t insert end "\n"
1820 }
1821 $top.t delete {end - 1c} end
1822 $top.t mark set insert 0.0
1823 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001824 grid $top.t - -sticky ew -padx 5
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001825 frame $top.buts
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001826 button $top.buts.ok -text "OK" -command [list newviewok $top $n] \
1827 -font $uifont
1828 button $top.buts.can -text "Cancel" -command [list destroy $top] \
1829 -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001830 grid $top.buts.ok $top.buts.can
1831 grid columnconfigure $top.buts 0 -weight 1 -uniform a
1832 grid columnconfigure $top.buts 1 -weight 1 -uniform a
1833 grid $top.buts - -pady 10 -sticky ew
1834 focus $top.t
1835}
1836
Paul Mackerras908c3582006-05-20 09:38:11 +10001837proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001838 set nmenu [$m index end]
1839 for {set i $first} {$i <= $nmenu} {incr i} {
1840 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001841 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001842 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001843 }
1844 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001845}
1846
1847proc allviewmenus {n op args} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001848 global viewhlmenu
1849
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001850 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras908c3582006-05-20 09:38:11 +10001851 doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001852}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001853
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001854proc newviewok {top n} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001855 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001856 global viewname viewfiles viewperm selectedview curview
Paul Mackerras908c3582006-05-20 09:38:11 +10001857 global viewargs newviewargs viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001858
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001859 if {[catch {
1860 set newargs [shellsplit $newviewargs($n)]
1861 } err]} {
1862 error_popup "Error in commit selection arguments: $err"
1863 wm raise $top
1864 focus $top
1865 return
1866 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001867 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001868 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001869 set ft [string trim $f]
1870 if {$ft ne {}} {
1871 lappend files $ft
1872 }
1873 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001874 if {![info exists viewfiles($n)]} {
1875 # creating a new view
1876 incr nextviewnum
1877 set viewname($n) $newviewname($n)
1878 set viewperm($n) $newviewperm($n)
1879 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001880 set viewargs($n) $newargs
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001881 addviewmenu $n
1882 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001883 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001884 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001885 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001886 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001887 } else {
1888 # editing an existing view
1889 set viewperm($n) $newviewperm($n)
1890 if {$newviewname($n) ne $viewname($n)} {
1891 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001892 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10001893 entryconf [list -label $viewname($n)]
1894 doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
1895 entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001896 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001897 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001898 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001899 set viewargs($n) $newargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001900 if {$curview == $n} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001901 run updatecommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001902 }
1903 }
1904 }
1905 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001906}
1907
1908proc delview {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001909 global curview viewdata viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001910
1911 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10001912 if {[info exists hlview] && $hlview == $curview} {
1913 set selectedhlview None
1914 unset hlview
1915 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001916 allviewmenus $curview delete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001917 set viewdata($curview) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001918 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001919 showview 0
1920}
1921
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001922proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001923 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001924
1925 .bar.view add radiobutton -label $viewname($n) \
1926 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras908c3582006-05-20 09:38:11 +10001927 $viewhlmenu add radiobutton -label $viewname($n) \
1928 -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001929}
1930
Paul Mackerras22626ef2006-04-17 09:56:02 +10001931proc flatten {var} {
1932 global $var
1933
1934 set ret {}
1935 foreach i [array names $var] {
1936 lappend ret $i [set $var\($i\)]
1937 }
1938 return $ret
1939}
1940
1941proc unflatten {var l} {
1942 global $var
1943
1944 catch {unset $var}
1945 foreach {i v} $l {
1946 set $var\($i\) $v
1947 }
1948}
1949
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001950proc showview {n} {
1951 global curview viewdata viewfiles
Paul Mackerras03800812007-08-29 21:45:21 +10001952 global displayorder parentlist rowidlist rowisopt
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001953 global colormap rowtextx commitrow nextcolor canvxmax
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10001954 global numcommits commitlisted
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001955 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10001956 global treediffs
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001957 global pending_select phase
Paul Mackerras03800812007-08-29 21:45:21 +10001958 global commitidx
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001959 global commfd
Paul Mackerrase507fd42007-06-16 21:51:08 +10001960 global selectedview selectfirst
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001961 global vparentlist vdisporder vcmitlisted
Paul Mackerras97645682007-08-23 22:24:38 +10001962 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001963
1964 if {$n == $curview} return
1965 set selid {}
1966 if {[info exists selectedline]} {
1967 set selid $currentid
1968 set y [yc $selectedline]
1969 set ymax [lindex [$canv cget -scrollregion] 3]
1970 set span [$canv yview]
1971 set ytop [expr {[lindex $span 0] * $ymax}]
1972 set ybot [expr {[lindex $span 1] * $ymax}]
1973 if {$ytop < $y && $y < $ybot} {
1974 set yscreen [expr {$y - $ytop}]
1975 } else {
1976 set yscreen [expr {($ybot - $ytop) / 2}]
1977 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10001978 } elseif {[info exists pending_select]} {
1979 set selid $pending_select
1980 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001981 }
1982 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10001983 normalline
Paul Mackerras22626ef2006-04-17 09:56:02 +10001984 if {$curview >= 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001985 set vparentlist($curview) $parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001986 set vdisporder($curview) $displayorder
1987 set vcmitlisted($curview) $commitlisted
Paul Mackerras22626ef2006-04-17 09:56:02 +10001988 if {$phase ne {}} {
1989 set viewdata($curview) \
Paul Mackerras03800812007-08-29 21:45:21 +10001990 [list $phase $rowidlist $rowisopt $numcommits]
Paul Mackerras2516dae2006-04-21 10:35:31 +10001991 } elseif {![info exists viewdata($curview)]
1992 || [lindex $viewdata($curview) 0] ne {}} {
Paul Mackerras22626ef2006-04-17 09:56:02 +10001993 set viewdata($curview) \
Paul Mackerras03800812007-08-29 21:45:21 +10001994 [list {} $rowidlist $rowisopt]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001995 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001996 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001997 catch {unset treediffs}
1998 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10001999 if {[info exists hlview] && $hlview == $n} {
2000 unset hlview
2001 set selectedhlview None
2002 }
Paul Mackerras97645682007-08-23 22:24:38 +10002003 catch {unset commitinterest}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002004
2005 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002006 set selectedview $n
Paul Mackerras3cd204e2006-11-23 21:06:16 +11002007 .bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}]
2008 .bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002009
Paul Mackerrasdf904492007-08-29 22:03:07 +10002010 run refill_reflist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002011 if {![info exists viewdata($n)]} {
Paul Mackerrase507fd42007-06-16 21:51:08 +10002012 if {$selid ne {}} {
2013 set pending_select $selid
2014 }
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10002015 getcommits
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002016 return
2017 }
2018
Paul Mackerras22626ef2006-04-17 09:56:02 +10002019 set v $viewdata($n)
2020 set phase [lindex $v 0]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002021 set displayorder $vdisporder($n)
2022 set parentlist $vparentlist($n)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002023 set commitlisted $vcmitlisted($n)
2024 set rowidlist [lindex $v 1]
Paul Mackerras03800812007-08-29 21:45:21 +10002025 set rowisopt [lindex $v 2]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002026 if {$phase eq {}} {
2027 set numcommits [llength $displayorder]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002028 } else {
Paul Mackerras03800812007-08-29 21:45:21 +10002029 set numcommits [lindex $v 3]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002030 }
2031
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002032 catch {unset colormap}
2033 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002034 set nextcolor 0
2035 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002036 set curview $n
2037 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002038 setcanvscroll
2039 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10002040 set row {}
2041 set selectfirst 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002042 if {$selid ne {} && [info exists commitrow($n,$selid)]} {
2043 set row $commitrow($n,$selid)
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002044 # try to get the selected row in the same position on the screen
2045 set ymax [lindex [$canv cget -scrollregion] 3]
2046 set ytop [expr {[yc $row] - $yscreen}]
2047 if {$ytop < 0} {
2048 set ytop 0
2049 }
2050 set yf [expr {$ytop * 1.0 / $ymax}]
2051 }
2052 allcanvs yview moveto $yf
2053 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10002054 if {$row ne {}} {
2055 selectline $row 0
2056 } elseif {$selid ne {}} {
2057 set pending_select $selid
2058 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10002059 set row [first_real_row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002060 if {$row < $numcommits} {
2061 selectline $row 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10002062 } else {
2063 set selectfirst 1
2064 }
2065 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002066 if {$phase ne {}} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10002067 if {$phase eq "getcommits"} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10002068 show_status "Reading commits..."
Paul Mackerrasd16c0812006-04-25 21:21:10 +10002069 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002070 run chewcommits $n
Paul Mackerras098dd8a2006-05-03 09:32:53 +10002071 } elseif {$numcommits == 0} {
2072 show_status "No commits selected"
Paul Mackerras2516dae2006-04-21 10:35:31 +10002073 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002074}
2075
Paul Mackerras908c3582006-05-20 09:38:11 +10002076# Stuff relating to the highlighting facility
2077
2078proc ishighlighted {row} {
Paul Mackerras164ff272006-05-29 19:50:02 +10002079 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10002080
2081 if {[info exists nhighlights($row)] && $nhighlights($row) > 0} {
2082 return $nhighlights($row)
2083 }
2084 if {[info exists vhighlights($row)] && $vhighlights($row) > 0} {
2085 return $vhighlights($row)
2086 }
2087 if {[info exists fhighlights($row)] && $fhighlights($row) > 0} {
2088 return $fhighlights($row)
2089 }
Paul Mackerras164ff272006-05-29 19:50:02 +10002090 if {[info exists rhighlights($row)] && $rhighlights($row) > 0} {
2091 return $rhighlights($row)
2092 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002093 return 0
2094}
2095
2096proc bolden {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002097 global canv linehtag selectedline boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10002098
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002099 lappend boldrows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10002100 $canv itemconf $linehtag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10002101 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10002102 $canv delete secsel
2103 set t [eval $canv create rect [$canv bbox $linehtag($row)] \
2104 -outline {{}} -tags secsel \
2105 -fill [$canv cget -selectbackground]]
2106 $canv lower $t
2107 }
2108}
2109
2110proc bolden_name {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002111 global canv2 linentag selectedline boldnamerows
Paul Mackerras908c3582006-05-20 09:38:11 +10002112
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002113 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10002114 $canv2 itemconf $linentag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10002115 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10002116 $canv2 delete secsel
2117 set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
2118 -outline {{}} -tags secsel \
2119 -fill [$canv2 cget -selectbackground]]
2120 $canv2 lower $t
2121 }
2122}
2123
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002124proc unbolden {} {
2125 global mainfont boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10002126
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002127 set stillbold {}
2128 foreach row $boldrows {
Paul Mackerras908c3582006-05-20 09:38:11 +10002129 if {![ishighlighted $row]} {
2130 bolden $row $mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002131 } else {
2132 lappend stillbold $row
Paul Mackerras908c3582006-05-20 09:38:11 +10002133 }
2134 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002135 set boldrows $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10002136}
2137
2138proc addvhighlight {n} {
2139 global hlview curview viewdata vhl_done vhighlights commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002140
2141 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10002142 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002143 }
2144 set hlview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002145 if {$n != $curview && ![info exists viewdata($n)]} {
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10002146 set viewdata($n) [list getcommits {{}} 0 0 0]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002147 set vparentlist($n) {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002148 set vdisporder($n) {}
2149 set vcmitlisted($n) {}
2150 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10002151 }
2152 set vhl_done $commitidx($hlview)
2153 if {$vhl_done > 0} {
2154 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002155 }
2156}
2157
Paul Mackerras908c3582006-05-20 09:38:11 +10002158proc delvhighlight {} {
2159 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002160
2161 if {![info exists hlview]} return
2162 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002163 catch {unset vhighlights}
2164 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002165}
2166
Paul Mackerras908c3582006-05-20 09:38:11 +10002167proc vhighlightmore {} {
2168 global hlview vhl_done commitidx vhighlights
2169 global displayorder vdisporder curview mainfont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002170
2171 set font [concat $mainfont bold]
2172 set max $commitidx($hlview)
2173 if {$hlview == $curview} {
2174 set disp $displayorder
2175 } else {
2176 set disp $vdisporder($hlview)
2177 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002178 set vr [visiblerows]
2179 set r0 [lindex $vr 0]
2180 set r1 [lindex $vr 1]
2181 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002182 set id [lindex $disp $i]
2183 if {[info exists commitrow($curview,$id)]} {
2184 set row $commitrow($curview,$id)
Paul Mackerras908c3582006-05-20 09:38:11 +10002185 if {$r0 <= $row && $row <= $r1} {
2186 if {![highlighted $row]} {
2187 bolden $row $font
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002188 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002189 set vhighlights($row) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002190 }
2191 }
2192 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002193 set vhl_done $max
2194}
2195
2196proc askvhighlight {row id} {
2197 global hlview vhighlights commitrow iddrawn mainfont
2198
2199 if {[info exists commitrow($hlview,$id)]} {
2200 if {[info exists iddrawn($id)] && ![ishighlighted $row]} {
2201 bolden $row [concat $mainfont bold]
2202 }
2203 set vhighlights($row) 1
2204 } else {
2205 set vhighlights($row) 0
2206 }
2207}
2208
2209proc hfiles_change {name ix op} {
2210 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras63b79192006-05-20 21:31:52 +10002211 global mainfont highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10002212
2213 if {[info exists filehighlight]} {
2214 # delete previous highlights
2215 catch {close $filehighlight}
2216 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002217 catch {unset fhighlights}
2218 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10002219 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10002220 }
Paul Mackerras63b79192006-05-20 21:31:52 +10002221 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002222 after cancel do_file_hl $fh_serial
2223 incr fh_serial
2224 if {$highlight_files ne {}} {
2225 after 300 do_file_hl $fh_serial
2226 }
2227}
2228
Paul Mackerras63b79192006-05-20 21:31:52 +10002229proc makepatterns {l} {
2230 set ret {}
2231 foreach e $l {
2232 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
2233 if {[string index $ee end] eq "/"} {
2234 lappend ret "$ee*"
2235 } else {
2236 lappend ret $ee
2237 lappend ret "$ee/*"
2238 }
2239 }
2240 return $ret
2241}
2242
Paul Mackerras908c3582006-05-20 09:38:11 +10002243proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002244 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002245
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002246 if {$gdttype eq "touching paths:"} {
2247 if {[catch {set paths [shellsplit $highlight_files]}]} return
2248 set highlight_paths [makepatterns $paths]
2249 highlight_filelist
2250 set gdtargs [concat -- $paths]
2251 } else {
2252 set gdtargs [list "-S$highlight_files"]
2253 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002254 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10002255 set filehighlight [open $cmd r+]
2256 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002257 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002258 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002259 drawvisible
2260 flushhighlights
2261}
2262
2263proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002264 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002265
2266 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002267 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002268 puts $filehighlight ""
2269 flush $filehighlight
2270 }
2271}
2272
2273proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002274 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002275
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002276 lappend fhl_list $id
2277 set fhighlights($row) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10002278 puts $filehighlight $id
2279}
2280
2281proc readfhighlight {} {
2282 global filehighlight fhighlights commitrow curview mainfont iddrawn
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002283 global fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002284
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002285 if {![info exists filehighlight]} {
2286 return 0
2287 }
2288 set nr 0
2289 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002290 set line [string trim $line]
2291 set i [lsearch -exact $fhl_list $line]
2292 if {$i < 0} continue
2293 for {set j 0} {$j < $i} {incr j} {
2294 set id [lindex $fhl_list $j]
2295 if {[info exists commitrow($curview,$id)]} {
2296 set fhighlights($commitrow($curview,$id)) 0
2297 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002298 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002299 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
2300 if {$line eq {}} continue
2301 if {![info exists commitrow($curview,$line)]} continue
2302 set row $commitrow($curview,$line)
2303 if {[info exists iddrawn($line)] && ![ishighlighted $row]} {
2304 bolden $row [concat $mainfont bold]
2305 }
2306 set fhighlights($row) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002307 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002308 if {[eof $filehighlight]} {
2309 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002310 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002311 catch {close $filehighlight}
2312 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002313 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10002314 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002315 next_hlcont
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002316 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002317}
2318
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002319proc find_change {name ix op} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002320 global nhighlights mainfont boldnamerows
Paul Mackerras005a2f42007-07-26 22:36:39 +10002321 global findstring findpattern findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10002322
2323 # delete previous highlights, if any
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002324 foreach row $boldnamerows {
2325 bolden_name $row $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10002326 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002327 set boldnamerows {}
2328 catch {unset nhighlights}
2329 unbolden
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002330 unmarkmatches
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002331 if {$findtype ne "Regexp"} {
2332 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
2333 $findstring]
2334 set findpattern "*$e*"
Paul Mackerras908c3582006-05-20 09:38:11 +10002335 }
2336 drawvisible
2337}
2338
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002339proc doesmatch {f} {
2340 global findtype findstring findpattern
2341
2342 if {$findtype eq "Regexp"} {
2343 return [regexp $findstring $f]
2344 } elseif {$findtype eq "IgnCase"} {
2345 return [string match -nocase $findpattern $f]
2346 } else {
2347 return [string match $findpattern $f]
2348 }
2349}
2350
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002351proc askfindhighlight {row id} {
2352 global nhighlights commitinfo iddrawn mainfont
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002353 global findloc
2354 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10002355
2356 if {![info exists commitinfo($id)]} {
2357 getcommit $id
2358 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002359 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10002360 set isbold 0
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002361 set fldtypes {Headline Author Date Committer CDate Comments}
2362 foreach f $info ty $fldtypes {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002363 if {($findloc eq "All fields" || $findloc eq $ty) &&
2364 [doesmatch $f]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002365 if {$ty eq "Author"} {
2366 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002367 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002368 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002369 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002370 }
2371 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002372 if {$isbold && [info exists iddrawn($id)]} {
2373 set f [concat $mainfont bold]
2374 if {![ishighlighted $row]} {
2375 bolden $row $f
2376 if {$isbold > 1} {
2377 bolden_name $row $f
2378 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002379 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002380 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10002381 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10002382 }
2383 }
2384 set nhighlights($row) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002385}
2386
Paul Mackerras005a2f42007-07-26 22:36:39 +10002387proc markrowmatches {row id} {
2388 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002389
Paul Mackerras005a2f42007-07-26 22:36:39 +10002390 set headline [lindex $commitinfo($id) 0]
2391 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002392 $canv delete match$row
2393 $canv2 delete match$row
Paul Mackerras005a2f42007-07-26 22:36:39 +10002394 if {$findloc eq "All fields" || $findloc eq "Headline"} {
2395 set m [findmatches $headline]
2396 if {$m ne {}} {
2397 markmatches $canv $row $headline $linehtag($row) $m \
2398 [$canv itemcget $linehtag($row) -font] $row
2399 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002400 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10002401 if {$findloc eq "All fields" || $findloc eq "Author"} {
2402 set m [findmatches $author]
2403 if {$m ne {}} {
2404 markmatches $canv2 $row $author $linentag($row) $m \
2405 [$canv2 itemcget $linentag($row) -font] $row
2406 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002407 }
2408}
2409
Paul Mackerras164ff272006-05-29 19:50:02 +10002410proc vrel_change {name ix op} {
2411 global highlight_related
2412
2413 rhighlight_none
2414 if {$highlight_related ne "None"} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002415 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002416 }
2417}
2418
2419# prepare for testing whether commits are descendents or ancestors of a
2420proc rhighlight_sel {a} {
2421 global descendent desc_todo ancestor anc_todo
2422 global highlight_related rhighlights
2423
2424 catch {unset descendent}
2425 set desc_todo [list $a]
2426 catch {unset ancestor}
2427 set anc_todo [list $a]
2428 if {$highlight_related ne "None"} {
2429 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002430 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002431 }
2432}
2433
2434proc rhighlight_none {} {
2435 global rhighlights
2436
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002437 catch {unset rhighlights}
2438 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10002439}
2440
2441proc is_descendent {a} {
2442 global curview children commitrow descendent desc_todo
2443
2444 set v $curview
2445 set la $commitrow($v,$a)
2446 set todo $desc_todo
2447 set leftover {}
2448 set done 0
2449 for {set i 0} {$i < [llength $todo]} {incr i} {
2450 set do [lindex $todo $i]
2451 if {$commitrow($v,$do) < $la} {
2452 lappend leftover $do
2453 continue
2454 }
2455 foreach nk $children($v,$do) {
2456 if {![info exists descendent($nk)]} {
2457 set descendent($nk) 1
2458 lappend todo $nk
2459 if {$nk eq $a} {
2460 set done 1
2461 }
2462 }
2463 }
2464 if {$done} {
2465 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2466 return
2467 }
2468 }
2469 set descendent($a) 0
2470 set desc_todo $leftover
2471}
2472
2473proc is_ancestor {a} {
2474 global curview parentlist commitrow ancestor anc_todo
2475
2476 set v $curview
2477 set la $commitrow($v,$a)
2478 set todo $anc_todo
2479 set leftover {}
2480 set done 0
2481 for {set i 0} {$i < [llength $todo]} {incr i} {
2482 set do [lindex $todo $i]
2483 if {![info exists commitrow($v,$do)] || $commitrow($v,$do) > $la} {
2484 lappend leftover $do
2485 continue
2486 }
2487 foreach np [lindex $parentlist $commitrow($v,$do)] {
2488 if {![info exists ancestor($np)]} {
2489 set ancestor($np) 1
2490 lappend todo $np
2491 if {$np eq $a} {
2492 set done 1
2493 }
2494 }
2495 }
2496 if {$done} {
2497 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2498 return
2499 }
2500 }
2501 set ancestor($a) 0
2502 set anc_todo $leftover
2503}
2504
2505proc askrelhighlight {row id} {
2506 global descendent highlight_related iddrawn mainfont rhighlights
2507 global selectedline ancestor
2508
2509 if {![info exists selectedline]} return
2510 set isbold 0
2511 if {$highlight_related eq "Descendent" ||
2512 $highlight_related eq "Not descendent"} {
2513 if {![info exists descendent($id)]} {
2514 is_descendent $id
2515 }
2516 if {$descendent($id) == ($highlight_related eq "Descendent")} {
2517 set isbold 1
2518 }
2519 } elseif {$highlight_related eq "Ancestor" ||
2520 $highlight_related eq "Not ancestor"} {
2521 if {![info exists ancestor($id)]} {
2522 is_ancestor $id
2523 }
2524 if {$ancestor($id) == ($highlight_related eq "Ancestor")} {
2525 set isbold 1
2526 }
2527 }
2528 if {[info exists iddrawn($id)]} {
2529 if {$isbold && ![ishighlighted $row]} {
2530 bolden $row [concat $mainfont bold]
2531 }
2532 }
2533 set rhighlights($row) $isbold
2534}
2535
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002536proc next_hlcont {} {
2537 global fhl_row fhl_dirn displayorder numcommits
2538 global vhighlights fhighlights nhighlights rhighlights
2539 global hlview filehighlight findstring highlight_related
2540
2541 if {![info exists fhl_dirn] || $fhl_dirn == 0} return
2542 set row $fhl_row
2543 while {1} {
2544 if {$row < 0 || $row >= $numcommits} {
2545 bell
2546 set fhl_dirn 0
2547 return
2548 }
2549 set id [lindex $displayorder $row]
2550 if {[info exists hlview]} {
2551 if {![info exists vhighlights($row)]} {
2552 askvhighlight $row $id
2553 }
2554 if {$vhighlights($row) > 0} break
2555 }
2556 if {$findstring ne {}} {
2557 if {![info exists nhighlights($row)]} {
2558 askfindhighlight $row $id
2559 }
2560 if {$nhighlights($row) > 0} break
2561 }
2562 if {$highlight_related ne "None"} {
2563 if {![info exists rhighlights($row)]} {
2564 askrelhighlight $row $id
2565 }
2566 if {$rhighlights($row) > 0} break
2567 }
2568 if {[info exists filehighlight]} {
2569 if {![info exists fhighlights($row)]} {
2570 # ask for a few more while we're at it...
2571 set r $row
2572 for {set n 0} {$n < 100} {incr n} {
2573 if {![info exists fhighlights($r)]} {
2574 askfilehighlight $r [lindex $displayorder $r]
2575 }
2576 incr r $fhl_dirn
2577 if {$r < 0 || $r >= $numcommits} break
2578 }
2579 flushhighlights
2580 }
2581 if {$fhighlights($row) < 0} {
2582 set fhl_row $row
2583 return
2584 }
2585 if {$fhighlights($row) > 0} break
2586 }
2587 incr row $fhl_dirn
2588 }
2589 set fhl_dirn 0
2590 selectline $row 1
2591}
2592
2593proc next_highlight {dirn} {
2594 global selectedline fhl_row fhl_dirn
2595 global hlview filehighlight findstring highlight_related
2596
2597 if {![info exists selectedline]} return
2598 if {!([info exists hlview] || $findstring ne {} ||
2599 $highlight_related ne "None" || [info exists filehighlight])} return
2600 set fhl_row [expr {$selectedline + $dirn}]
2601 set fhl_dirn $dirn
2602 next_hlcont
2603}
2604
2605proc cancel_next_highlight {} {
2606 global fhl_dirn
2607
2608 set fhl_dirn 0
2609}
2610
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002611# Graph layout functions
2612
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002613proc shortids {ids} {
2614 set res {}
2615 foreach id $ids {
2616 if {[llength $id] > 1} {
2617 lappend res [shortids $id]
2618 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
2619 lappend res [string range $id 0 7]
2620 } else {
2621 lappend res $id
2622 }
2623 }
2624 return $res
2625}
2626
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002627proc ntimes {n o} {
2628 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10002629 set o [list $o]
2630 for {set mask 1} {$mask <= $n} {incr mask $mask} {
2631 if {($n & $mask) != 0} {
2632 set ret [concat $ret $o]
2633 }
2634 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002635 }
2636 return $ret
2637}
2638
Paul Mackerras6e8c8702007-07-31 21:03:06 +10002639# Work out where id should go in idlist so that order-token
2640# values increase from left to right
2641proc idcol {idlist id {i 0}} {
2642 global ordertok curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002643
Paul Mackerras6e8c8702007-07-31 21:03:06 +10002644 set t $ordertok($curview,$id)
2645 if {$i >= [llength $idlist] ||
2646 $t < $ordertok($curview,[lindex $idlist $i])} {
2647 if {$i > [llength $idlist]} {
2648 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002649 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10002650 while {[incr i -1] >= 0 &&
2651 $t < $ordertok($curview,[lindex $idlist $i])} {}
2652 incr i
2653 } else {
2654 if {$t > $ordertok($curview,[lindex $idlist $i])} {
2655 while {[incr i] < [llength $idlist] &&
2656 $t >= $ordertok($curview,[lindex $idlist $i])} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002657 }
2658 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10002659 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002660}
2661
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002662proc initlayout {} {
Paul Mackerras03800812007-08-29 21:45:21 +10002663 global rowidlist rowisopt displayorder commitlisted
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002664 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002665 global nextcolor
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002666 global parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002667 global colormap rowtextx
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002668 global selectfirst
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002669
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002670 set numcommits 0
2671 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002672 set commitlisted {}
2673 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002674 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10002675 set rowidlist {}
2676 set rowisopt {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002677 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002678 catch {unset colormap}
2679 catch {unset rowtextx}
Paul Mackerrase507fd42007-06-16 21:51:08 +10002680 set selectfirst 1
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002681}
2682
2683proc setcanvscroll {} {
2684 global canv canv2 canv3 numcommits linespc canvxmax canvy0
2685
2686 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
2687 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
2688 $canv2 conf -scrollregion [list 0 0 0 $ymax]
2689 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002690}
2691
2692proc visiblerows {} {
2693 global canv numcommits linespc
2694
2695 set ymax [lindex [$canv cget -scrollregion] 3]
2696 if {$ymax eq {} || $ymax == 0} return
2697 set f [$canv yview]
2698 set y0 [expr {int([lindex $f 0] * $ymax)}]
2699 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
2700 if {$r0 < 0} {
2701 set r0 0
2702 }
2703 set y1 [expr {int([lindex $f 1] * $ymax)}]
2704 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
2705 if {$r1 >= $numcommits} {
2706 set r1 [expr {$numcommits - 1}]
2707 }
2708 return [list $r0 $r1]
2709}
2710
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002711proc layoutmore {tmax allread} {
Paul Mackerras03800812007-08-29 21:45:21 +10002712 global commitidx numcommits
2713 global uparrowlen downarrowlen mingaplen curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002714
Paul Mackerras03800812007-08-29 21:45:21 +10002715 set show $commitidx($curview)
2716 if {!$allread} {
2717 set delay [expr {$uparrowlen + $mingaplen + $downarrowlen + 3}]
2718 set show [expr {$show - $delay}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002719 }
Paul Mackerras03800812007-08-29 21:45:21 +10002720 if {$show > $numcommits} {
2721 showstuff $show $allread
2722 }
2723 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002724}
2725
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002726proc showstuff {canshow last} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002727 global numcommits commitrow pending_select selectedline curview
Paul Mackerras8f489362007-07-13 19:49:37 +10002728 global lookingforhead mainheadid displayorder selectfirst
Paul Mackerras887c9962007-08-20 19:36:20 +10002729 global lastscrollset commitinterest
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002730
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002731 if {$numcommits == 0} {
2732 global phase
2733 set phase "incrdraw"
2734 allcanvs delete all
2735 }
Paul Mackerras887c9962007-08-20 19:36:20 +10002736 for {set l $numcommits} {$l < $canshow} {incr l} {
2737 set id [lindex $displayorder $l]
2738 if {[info exists commitinterest($id)]} {
2739 foreach script $commitinterest($id) {
2740 eval [string map [list "%I" $id] $script]
2741 }
2742 unset commitinterest($id)
2743 }
2744 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002745 set r0 $numcommits
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002746 set prev $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002747 set numcommits $canshow
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002748 set t [clock clicks -milliseconds]
2749 if {$prev < 100 || $last || $t - $lastscrollset > 500} {
2750 set lastscrollset $t
2751 setcanvscroll
2752 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002753 set rows [visiblerows]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002754 set r1 [lindex $rows 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002755 if {$r1 >= $canshow} {
2756 set r1 [expr {$canshow - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002757 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002758 if {$r0 <= $r1} {
2759 drawcommits $r0 $r1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002760 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002761 if {[info exists pending_select] &&
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002762 [info exists commitrow($curview,$pending_select)] &&
2763 $commitrow($curview,$pending_select) < $numcommits} {
2764 selectline $commitrow($curview,$pending_select) 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002765 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10002766 if {$selectfirst} {
2767 if {[info exists selectedline] || [info exists pending_select]} {
2768 set selectfirst 0
2769 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10002770 set l [first_real_row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002771 selectline $l 1
Paul Mackerrase507fd42007-06-16 21:51:08 +10002772 set selectfirst 0
2773 }
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10002774 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002775 if {$lookingforhead && [info exists commitrow($curview,$mainheadid)]
2776 && ($last || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2777 set lookingforhead 0
2778 dodiffindex
2779 }
2780}
2781
2782proc doshowlocalchanges {} {
2783 global lookingforhead curview mainheadid phase commitrow
2784
2785 if {[info exists commitrow($curview,$mainheadid)] &&
2786 ($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2787 dodiffindex
2788 } elseif {$phase ne {}} {
2789 set lookingforhead 1
2790 }
2791}
2792
2793proc dohidelocalchanges {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002794 global lookingforhead localfrow localirow lserial
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002795
2796 set lookingforhead 0
Paul Mackerras8f489362007-07-13 19:49:37 +10002797 if {$localfrow >= 0} {
2798 removerow $localfrow
2799 set localfrow -1
2800 if {$localirow > 0} {
2801 incr localirow -1
2802 }
2803 }
2804 if {$localirow >= 0} {
2805 removerow $localirow
2806 set localirow -1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002807 }
2808 incr lserial
2809}
2810
Paul Mackerras8f489362007-07-13 19:49:37 +10002811# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002812proc dodiffindex {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002813 global localirow localfrow lserial
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002814
2815 incr lserial
Paul Mackerras8f489362007-07-13 19:49:37 +10002816 set localfrow -1
2817 set localirow -1
2818 set fd [open "|git diff-index --cached HEAD" r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002819 fconfigure $fd -blocking 0
2820 filerun $fd [list readdiffindex $fd $lserial]
2821}
2822
2823proc readdiffindex {fd serial} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002824 global localirow commitrow mainheadid nullid2 curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002825 global commitinfo commitdata lserial
2826
Paul Mackerras8f489362007-07-13 19:49:37 +10002827 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002828 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002829 if {![eof $fd]} {
2830 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002831 }
Paul Mackerras8f489362007-07-13 19:49:37 +10002832 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002833 }
2834 # we only need to see one line and we don't really care what it says...
2835 close $fd
2836
Paul Mackerras8f489362007-07-13 19:49:37 +10002837 # now see if there are any local changes not checked in to the index
2838 if {$serial == $lserial} {
2839 set fd [open "|git diff-files" r]
2840 fconfigure $fd -blocking 0
2841 filerun $fd [list readdifffiles $fd $serial]
2842 }
2843
2844 if {$isdiff && $serial == $lserial && $localirow == -1} {
2845 # add the line for the changes in the index to the graph
2846 set localirow $commitrow($curview,$mainheadid)
2847 set hl "Local changes checked in to index but not committed"
2848 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
2849 set commitdata($nullid2) "\n $hl\n"
2850 insertrow $localirow $nullid2
2851 }
2852 return 0
2853}
2854
2855proc readdifffiles {fd serial} {
2856 global localirow localfrow commitrow mainheadid nullid curview
2857 global commitinfo commitdata lserial
2858
2859 set isdiff 1
2860 if {[gets $fd line] < 0} {
2861 if {![eof $fd]} {
2862 return 1
2863 }
2864 set isdiff 0
2865 }
2866 # we only need to see one line and we don't really care what it says...
2867 close $fd
2868
2869 if {$isdiff && $serial == $lserial && $localfrow == -1} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002870 # add the line for the local diff to the graph
Paul Mackerras8f489362007-07-13 19:49:37 +10002871 if {$localirow >= 0} {
2872 set localfrow $localirow
2873 incr localirow
2874 } else {
2875 set localfrow $commitrow($curview,$mainheadid)
2876 }
2877 set hl "Local uncommitted changes, not checked in to index"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002878 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
2879 set commitdata($nullid) "\n $hl\n"
Paul Mackerras8f489362007-07-13 19:49:37 +10002880 insertrow $localfrow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002881 }
2882 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002883}
2884
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10002885proc nextuse {id row} {
2886 global commitrow curview children
2887
2888 if {[info exists children($curview,$id)]} {
2889 foreach kid $children($curview,$id) {
Paul Mackerras03800812007-08-29 21:45:21 +10002890 if {![info exists commitrow($curview,$kid)]} {
2891 return -1
2892 }
2893 if {$commitrow($curview,$kid) > $row} {
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10002894 return $commitrow($curview,$kid)
2895 }
2896 }
2897 }
2898 if {[info exists commitrow($curview,$id)]} {
2899 return $commitrow($curview,$id)
2900 }
2901 return -1
2902}
2903
Paul Mackerras03800812007-08-29 21:45:21 +10002904proc make_idlist {row} {
2905 global displayorder parentlist uparrowlen downarrowlen mingaplen
2906 global commitidx curview ordertok children commitrow
2907
2908 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
2909 if {$r < 0} {
2910 set r 0
2911 }
2912 set ra [expr {$row - $downarrowlen}]
2913 if {$ra < 0} {
2914 set ra 0
2915 }
2916 set rb [expr {$row + $uparrowlen}]
2917 if {$rb > $commitidx($curview)} {
2918 set rb $commitidx($curview)
2919 }
2920 set ids {}
2921 for {} {$r < $ra} {incr r} {
2922 set nextid [lindex $displayorder [expr {$r + 1}]]
2923 foreach p [lindex $parentlist $r] {
2924 if {$p eq $nextid} continue
2925 set rn [nextuse $p $r]
2926 if {$rn >= $row &&
2927 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
2928 lappend ids [list $ordertok($curview,$p) $p]
2929 }
2930 }
2931 }
2932 for {} {$r < $row} {incr r} {
2933 set nextid [lindex $displayorder [expr {$r + 1}]]
2934 foreach p [lindex $parentlist $r] {
2935 if {$p eq $nextid} continue
2936 set rn [nextuse $p $r]
2937 if {$rn < 0 || $rn >= $row} {
2938 lappend ids [list $ordertok($curview,$p) $p]
2939 }
2940 }
2941 }
2942 set id [lindex $displayorder $row]
2943 lappend ids [list $ordertok($curview,$id) $id]
2944 while {$r < $rb} {
2945 foreach p [lindex $parentlist $r] {
2946 set firstkid [lindex $children($curview,$p) 0]
2947 if {$commitrow($curview,$firstkid) < $row} {
2948 lappend ids [list $ordertok($curview,$p) $p]
2949 }
2950 }
2951 incr r
2952 set id [lindex $displayorder $r]
2953 if {$id ne {}} {
2954 set firstkid [lindex $children($curview,$id) 0]
2955 if {$firstkid ne {} && $commitrow($curview,$firstkid) < $row} {
2956 lappend ids [list $ordertok($curview,$id) $id]
2957 }
2958 }
2959 }
2960 set idlist {}
2961 foreach idx [lsort -unique $ids] {
2962 lappend idlist [lindex $idx 1]
2963 }
2964 return $idlist
2965}
2966
2967proc layoutrows {row endrow} {
2968 global rowidlist rowisopt displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002969 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002970 global children parentlist
Paul Mackerras03800812007-08-29 21:45:21 +10002971 global commitidx curview commitrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002972
Paul Mackerras03800812007-08-29 21:45:21 +10002973 set idlist {}
2974 if {$row > 0} {
2975 foreach id [lindex $rowidlist [expr {$row - 1}]] {
2976 if {$id ne {}} {
2977 lappend idlist $id
2978 }
2979 }
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10002980 }
Paul Mackerras03800812007-08-29 21:45:21 +10002981 for {} {$row < $endrow} {incr row} {
2982 set rm1 [expr {$row - 1}]
2983 if {$rm1 < 0 || [lindex $rowidlist $rm1] eq {}} {
2984 set idlist [make_idlist $row]
2985 } else {
2986 set id [lindex $displayorder $rm1]
2987 set col [lsearch -exact $idlist $id]
2988 set idlist [lreplace $idlist $col $col]
2989 foreach p [lindex $parentlist $rm1] {
2990 if {[lsearch -exact $idlist $p] < 0} {
2991 set col [idcol $idlist $p $col]
2992 set idlist [linsert $idlist $col $p]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002993 }
2994 }
Paul Mackerras03800812007-08-29 21:45:21 +10002995 set id [lindex $displayorder $row]
2996 if {$row > $downarrowlen} {
2997 set termrow [expr {$row - $downarrowlen - 1}]
2998 foreach p [lindex $parentlist $termrow] {
2999 set i [lsearch -exact $idlist $p]
3000 if {$i < 0} continue
3001 set nr [nextuse $p $termrow]
3002 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
3003 set idlist [lreplace $idlist $i $i]
3004 }
3005 }
3006 }
3007 set col [lsearch -exact $idlist $id]
3008 if {$col < 0} {
3009 set col [idcol $idlist $id]
3010 set idlist [linsert $idlist $col $id]
3011 }
3012 set r [expr {$row + $uparrowlen - 1}]
3013 if {$r < $commitidx($curview)} {
3014 set x $col
3015 foreach p [lindex $parentlist $r] {
3016 if {[lsearch -exact $idlist $p] >= 0} continue
3017 set fk [lindex $children($curview,$p) 0]
3018 if {$commitrow($curview,$fk) < $row} {
3019 set x [idcol $idlist $p $x]
3020 set idlist [linsert $idlist $x $p]
3021 }
3022 }
3023 if {[incr r] < $commitidx($curview)} {
3024 set p [lindex $displayorder $r]
3025 if {[lsearch -exact $idlist $p] < 0} {
3026 set fk [lindex $children($curview,$p) 0]
3027 if {$fk ne {} && $commitrow($curview,$fk) < $row} {
3028 set x [idcol $idlist $p $x]
3029 set idlist [linsert $idlist $x $p]
3030 }
3031 }
3032 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10003033 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10003034 }
Paul Mackerras03800812007-08-29 21:45:21 +10003035 set l [llength $rowidlist]
3036 if {$row == $l} {
3037 lappend rowidlist $idlist
3038 lappend rowisopt 0
3039 } elseif {$row < $l} {
3040 if {$idlist ne [lindex $rowidlist $row]} {
3041 lset rowidlist $row $idlist
3042 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003043 }
Paul Mackerras03800812007-08-29 21:45:21 +10003044 } else {
3045 set rowidlist [concat $rowidlist [ntimes [expr {$row - $l}] {}]]
3046 lappend rowidlist $idlist
3047 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003048 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003049 }
3050 return $row
3051}
3052
Paul Mackerras03800812007-08-29 21:45:21 +10003053proc changedrow {row} {
3054 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003055
Paul Mackerras03800812007-08-29 21:45:21 +10003056 set l [llength $rowisopt]
3057 if {$row < $l} {
3058 lset rowisopt $row 0
3059 if {$row + 1 < $l} {
3060 lset rowisopt [expr {$row + 1}] 0
3061 if {$row + 2 < $l} {
3062 lset rowisopt [expr {$row + 2}] 0
3063 }
3064 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10003065 }
Paul Mackerras03800812007-08-29 21:45:21 +10003066 set id [lindex $displayorder $row]
3067 if {[info exists iddrawn($id)]} {
3068 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003069 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003070}
3071
3072proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003073 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003074
3075 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10003076 set idlist [lindex $rowidlist $row]
3077 set bef [lrange $idlist 0 [expr {$col - 1}]]
3078 set aft [lrange $idlist $col end]
3079 set i [lsearch -exact $aft {}]
3080 if {$i > 0} {
3081 set aft [lreplace $aft $i $i]
3082 }
3083 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10003084 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003085}
3086
3087proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10003088 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003089
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003090 if {$row < 1} {
3091 set row 1
3092 }
Paul Mackerras03800812007-08-29 21:45:21 +10003093 for {} {$row < $endrow} {incr row; set col 0} {
3094 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003095 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003096 set y0 [expr {$row - 1}]
3097 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10003098 set idlist [lindex $rowidlist $row]
3099 set previdlist [lindex $rowidlist $y0]
3100 if {$idlist eq {} || $previdlist eq {}} continue
3101 if {$ym >= 0} {
3102 set pprevidlist [lindex $rowidlist $ym]
3103 if {$pprevidlist eq {}} continue
3104 } else {
3105 set pprevidlist {}
3106 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003107 set x0 -1
3108 set xm -1
3109 for {} {$col < [llength $idlist]} {incr col} {
3110 set id [lindex $idlist $col]
3111 if {[lindex $previdlist $col] eq $id} continue
3112 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003113 set haspad 1
3114 continue
3115 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003116 set x0 [lsearch -exact $previdlist $id]
3117 if {$x0 < 0} continue
3118 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003119 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003120 set z0 {}
3121 if {$ym >= 0} {
3122 set xm [lsearch -exact $pprevidlist $id]
3123 if {$xm >= 0} {
3124 set z0 [expr {$xm - $x0}]
3125 }
3126 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003127 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10003128 # if row y0 is the first child of $id then it's not an arrow
3129 if {[lindex $children($curview,$id) 0] ne
3130 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003131 set isarrow 1
3132 }
3133 }
Paul Mackerrase341c062007-08-12 12:42:57 +10003134 if {!$isarrow && $id ne [lindex $displayorder $row] &&
3135 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
3136 set isarrow 1
3137 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10003138 # Looking at lines from this row to the previous row,
3139 # make them go straight up if they end in an arrow on
3140 # the previous row; otherwise make them go straight up
3141 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003142 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10003143 # Line currently goes left too much;
3144 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003145 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003146 insert_pad $y0 $x0 $npad
3147 if {$y0 > 0} {
3148 optimize_rows $y0 $x0 $row
3149 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003150 set previdlist [lindex $rowidlist $y0]
3151 set x0 [lsearch -exact $previdlist $id]
3152 set z [expr {$x0 - $col}]
3153 if {$z0 ne {}} {
3154 set pprevidlist [lindex $rowidlist $ym]
3155 set xm [lsearch -exact $pprevidlist $id]
3156 set z0 [expr {$xm - $x0}]
3157 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003158 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10003159 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003160 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003161 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10003162 insert_pad $row $col $npad
3163 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003164 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003165 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003166 set haspad 1
3167 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003168 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003169 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003170 set id [lindex $displayorder $ym]
3171 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11003172 if {$xc >= 0} {
3173 set z0 [expr {$xc - $x0}]
3174 }
3175 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10003176 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003177 if {$z0 ne {} && $z < 0 && $z0 > 0} {
3178 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003179 incr x0
3180 optimize_rows $y0 $x0 $row
3181 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003182 }
3183 }
3184 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10003185 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003186 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003187 set id [lindex $idlist $col]
3188 if {$id eq {}} break
3189 set x0 [lsearch -exact $previdlist $id]
3190 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003191 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10003192 set kid [lindex $displayorder $y0]
3193 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003194 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10003195 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11003196 }
3197 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003198 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003199 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10003200 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003201 # isn't the last column
3202 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003203 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10003204 lset rowidlist $row $idlist
3205 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003206 }
3207 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003208 }
3209}
3210
3211proc xc {row col} {
3212 global canvx0 linespc
3213 return [expr {$canvx0 + $col * $linespc}]
3214}
3215
3216proc yc {row} {
3217 global canvy0 linespc
3218 return [expr {$canvy0 + $row * $linespc}]
3219}
3220
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003221proc linewidth {id} {
3222 global thickerline lthickness
3223
3224 set wid $lthickness
3225 if {[info exists thickerline] && $id eq $thickerline} {
3226 set wid [expr {2 * $lthickness}]
3227 }
3228 return $wid
3229}
3230
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003231proc rowranges {id} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10003232 global commitrow curview children uparrowlen downarrowlen
3233 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003234
Paul Mackerras92ed6662007-08-22 22:35:28 +10003235 set kids $children($curview,$id)
3236 if {$kids eq {}} {
3237 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003238 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10003239 set ret {}
3240 lappend kids $id
3241 foreach child $kids {
3242 if {![info exists commitrow($curview,$child)]} break
3243 set row $commitrow($curview,$child)
3244 if {![info exists prev]} {
3245 lappend ret [expr {$row + 1}]
3246 } else {
3247 if {$row <= $prevrow} {
3248 puts "oops children out of order [shortids $id] $row < [shortids $prev] $prevrow"
3249 }
3250 # see if the line extends the whole way from prevrow to row
3251 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
3252 [lsearch -exact [lindex $rowidlist \
3253 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
3254 # it doesn't, see where it ends
3255 set r [expr {$prevrow + $downarrowlen}]
3256 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
3257 while {[incr r -1] > $prevrow &&
3258 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
3259 } else {
3260 while {[incr r] <= $row &&
3261 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
3262 incr r -1
3263 }
3264 lappend ret $r
3265 # see where it starts up again
3266 set r [expr {$row - $uparrowlen}]
3267 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
3268 while {[incr r] < $row &&
3269 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
3270 } else {
3271 while {[incr r -1] >= $prevrow &&
3272 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
3273 incr r
3274 }
3275 lappend ret $r
3276 }
3277 }
3278 if {$child eq $id} {
3279 lappend ret $row
3280 }
3281 set prev $id
3282 set prevrow $row
Paul Mackerras66e46f32006-10-14 19:21:02 +10003283 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10003284 return $ret
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003285}
3286
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003287proc drawlineseg {id row endrow arrowlow} {
3288 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10003289 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003290
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003291 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
3292 set le [expr {$row + 1}]
3293 set arrowhigh 1
3294 while {1} {
3295 set c [lsearch -exact [lindex $rowidlist $le] $id]
3296 if {$c < 0} {
3297 incr le -1
3298 break
3299 }
3300 lappend cols $c
3301 set x [lindex $displayorder $le]
3302 if {$x eq $id} {
3303 set arrowhigh 0
3304 break
3305 }
3306 if {[info exists iddrawn($x)] || $le == $endrow} {
3307 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
3308 if {$c >= 0} {
3309 lappend cols $c
3310 set arrowhigh 0
3311 }
3312 break
3313 }
3314 incr le
3315 }
3316 if {$le <= $row} {
3317 return $row
3318 }
3319
3320 set lines {}
3321 set i 0
3322 set joinhigh 0
3323 if {[info exists linesegs($id)]} {
3324 set lines $linesegs($id)
3325 foreach li $lines {
3326 set r0 [lindex $li 0]
3327 if {$r0 > $row} {
3328 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
3329 set joinhigh 1
3330 }
3331 break
3332 }
3333 incr i
3334 }
3335 }
3336 set joinlow 0
3337 if {$i > 0} {
3338 set li [lindex $lines [expr {$i-1}]]
3339 set r1 [lindex $li 1]
3340 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
3341 set joinlow 1
3342 }
3343 }
3344
3345 set x [lindex $cols [expr {$le - $row}]]
3346 set xp [lindex $cols [expr {$le - 1 - $row}]]
3347 set dir [expr {$xp - $x}]
3348 if {$joinhigh} {
3349 set ith [lindex $lines $i 2]
3350 set coords [$canv coords $ith]
3351 set ah [$canv itemcget $ith -arrow]
3352 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
3353 set x2 [lindex $cols [expr {$le + 1 - $row}]]
3354 if {$x2 ne {} && $x - $x2 == $dir} {
3355 set coords [lrange $coords 0 end-2]
3356 }
3357 } else {
3358 set coords [list [xc $le $x] [yc $le]]
3359 }
3360 if {$joinlow} {
3361 set itl [lindex $lines [expr {$i-1}] 2]
3362 set al [$canv itemcget $itl -arrow]
3363 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10003364 } elseif {$arrowlow} {
3365 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
3366 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
3367 set arrowlow 0
3368 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003369 }
3370 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
3371 for {set y $le} {[incr y -1] > $row} {} {
3372 set x $xp
3373 set xp [lindex $cols [expr {$y - 1 - $row}]]
3374 set ndir [expr {$xp - $x}]
3375 if {$dir != $ndir || $xp < 0} {
3376 lappend coords [xc $y $x] [yc $y]
3377 }
3378 set dir $ndir
3379 }
3380 if {!$joinlow} {
3381 if {$xp < 0} {
3382 # join parent line to first child
3383 set ch [lindex $displayorder $row]
3384 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
3385 if {$xc < 0} {
3386 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10003387 } elseif {$xc != $x} {
3388 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
3389 set d [expr {int(0.5 * $linespc)}]
3390 set x1 [xc $row $x]
3391 if {$xc < $x} {
3392 set x2 [expr {$x1 - $d}]
3393 } else {
3394 set x2 [expr {$x1 + $d}]
3395 }
3396 set y2 [yc $row]
3397 set y1 [expr {$y2 + $d}]
3398 lappend coords $x1 $y1 $x2 $y2
3399 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003400 lappend coords [xc $row [expr {$x-1}]] [yc $row]
3401 } elseif {$xc > $x + 1} {
3402 lappend coords [xc $row [expr {$x+1}]] [yc $row]
3403 }
3404 set x $xc
3405 }
3406 lappend coords [xc $row $x] [yc $row]
3407 } else {
3408 set xn [xc $row $xp]
3409 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10003410 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003411 }
3412 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003413 assigncolor $id
3414 set t [$canv create line $coords -width [linewidth $id] \
3415 -fill $colormap($id) -tags lines.$id -arrow $arrow]
3416 $canv lower $t
3417 bindline $t $id
3418 set lines [linsert $lines $i [list $row $le $t]]
3419 } else {
3420 $canv coords $ith $coords
3421 if {$arrow ne $ah} {
3422 $canv itemconf $ith -arrow $arrow
3423 }
3424 lset lines $i 0 $row
3425 }
3426 } else {
3427 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
3428 set ndir [expr {$xo - $xp}]
3429 set clow [$canv coords $itl]
3430 if {$dir == $ndir} {
3431 set clow [lrange $clow 2 end]
3432 }
3433 set coords [concat $coords $clow]
3434 if {!$joinhigh} {
3435 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003436 } else {
3437 # coalesce two pieces
3438 $canv delete $ith
3439 set b [lindex $lines [expr {$i-1}] 0]
3440 set e [lindex $lines $i 1]
3441 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
3442 }
3443 $canv coords $itl $coords
3444 if {$arrow ne $al} {
3445 $canv itemconf $itl -arrow $arrow
3446 }
3447 }
3448
3449 set linesegs($id) $lines
3450 return $le
3451}
3452
3453proc drawparentlinks {id row} {
3454 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10003455 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003456
3457 set rowids [lindex $rowidlist $row]
3458 set col [lsearch -exact $rowids $id]
3459 if {$col < 0} return
3460 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003461 set row2 [expr {$row + 1}]
3462 set x [xc $row $col]
3463 set y [yc $row]
3464 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10003465 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10003466 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003467 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003468 # rmx = right-most X coord used
3469 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003470 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11003471 set i [lsearch -exact $ids $p]
3472 if {$i < 0} {
3473 puts "oops, parent $p of $id not in list"
3474 continue
3475 }
3476 set x2 [xc $row2 $i]
3477 if {$x2 > $rmx} {
3478 set rmx $x2
3479 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10003480 set j [lsearch -exact $rowids $p]
3481 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003482 # drawlineseg will do this one for us
3483 continue
3484 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003485 assigncolor $p
3486 # should handle duplicated parents here...
3487 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10003488 if {$i != $col} {
3489 # if attaching to a vertical segment, draw a smaller
3490 # slant for visual distinctness
3491 if {$i == $j} {
3492 if {$i < $col} {
3493 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
3494 } else {
3495 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
3496 }
3497 } elseif {$i < $col && $i < $j} {
3498 # segment slants towards us already
3499 lappend coords [xc $row $j] $y
3500 } else {
3501 if {$i < $col - 1} {
3502 lappend coords [expr {$x2 + $linespc}] $y
3503 } elseif {$i > $col + 1} {
3504 lappend coords [expr {$x2 - $linespc}] $y
3505 }
3506 lappend coords $x2 $y2
3507 }
3508 } else {
3509 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003510 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003511 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003512 -fill $colormap($p) -tags lines.$p]
3513 $canv lower $t
3514 bindline $t $p
3515 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003516 if {$rmx > [lindex $idpos($id) 1]} {
3517 lset idpos($id) 1 $rmx
3518 redrawtags $id
3519 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003520}
3521
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003522proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003523 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003524
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003525 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003526}
3527
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003528proc drawcmittext {id row col} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10003529 global linespc canv canv2 canv3 canvy0 fgcolor curview
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003530 global commitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003531 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10003532 global linehtag linentag linedtag selectedline
Paul Mackerras8f489362007-07-13 19:49:37 +10003533 global mainfont canvxmax boldrows boldnamerows fgcolor nullid nullid2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003534
Paul Mackerrasc961b222007-07-09 22:45:47 +10003535 # listed is 0 for boundary, 1 for normal, 2 for left, 3 for right
3536 set listed [lindex $commitlisted $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003537 if {$id eq $nullid} {
3538 set ofill red
Paul Mackerras8f489362007-07-13 19:49:37 +10003539 } elseif {$id eq $nullid2} {
Paul Mackerrasef3192b2007-07-22 22:05:30 +10003540 set ofill green
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003541 } else {
Paul Mackerrasc961b222007-07-09 22:45:47 +10003542 set ofill [expr {$listed != 0? "blue": "white"}]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003543 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003544 set x [xc $row $col]
3545 set y [yc $row]
3546 set orad [expr {$linespc / 3}]
Paul Mackerrasc961b222007-07-09 22:45:47 +10003547 if {$listed <= 1} {
3548 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
3549 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
3550 -fill $ofill -outline $fgcolor -width 1 -tags circle]
3551 } elseif {$listed == 2} {
3552 # triangle pointing left for left-side commits
3553 set t [$canv create polygon \
3554 [expr {$x - $orad}] $y \
3555 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
3556 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
3557 -fill $ofill -outline $fgcolor -width 1 -tags circle]
3558 } else {
3559 # triangle pointing right for right-side commits
3560 set t [$canv create polygon \
3561 [expr {$x + $orad - 1}] $y \
3562 [expr {$x - $orad}] [expr {$y - $orad}] \
3563 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
3564 -fill $ofill -outline $fgcolor -width 1 -tags circle]
3565 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003566 $canv raise $t
3567 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003568 set rmx [llength [lindex $rowidlist $row]]
3569 set olds [lindex $parentlist $row]
3570 if {$olds ne {}} {
3571 set nextids [lindex $rowidlist [expr {$row + 1}]]
3572 foreach p $olds {
3573 set i [lsearch -exact $nextids $p]
3574 if {$i > $rmx} {
3575 set rmx $i
3576 }
3577 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003578 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003579 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003580 set rowtextx($row) $xt
3581 set idpos($id) [list $x $xt $y]
3582 if {[info exists idtags($id)] || [info exists idheads($id)]
3583 || [info exists idotherrefs($id)]} {
3584 set xt [drawtags $id $x $xt $y]
3585 }
3586 set headline [lindex $commitinfo($id) 0]
3587 set name [lindex $commitinfo($id) 1]
3588 set date [lindex $commitinfo($id) 2]
3589 set date [formatdate $date]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003590 set font $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10003591 set nfont $mainfont
3592 set isbold [ishighlighted $row]
3593 if {$isbold > 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003594 lappend boldrows $row
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003595 lappend font bold
Paul Mackerras908c3582006-05-20 09:38:11 +10003596 if {$isbold > 1} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003597 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003598 lappend nfont bold
3599 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003600 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003601 set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
3602 -text $headline -font $font -tags text]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003603 $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003604 set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
3605 -text $name -font $nfont -tags text]
3606 set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
3607 -text $date -font $mainfont -tags text]
Paul Mackerras03800812007-08-29 21:45:21 +10003608 if {[info exists selectedline] && $selectedline == $row} {
3609 make_secsel $row
3610 }
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11003611 set xr [expr {$xt + [font measure $mainfont $headline]}]
3612 if {$xr > $canvxmax} {
3613 set canvxmax $xr
3614 setcanvscroll
3615 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003616}
3617
3618proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10003619 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10003620 global iddrawn markingmatches
Paul Mackerrase7da3472006-04-17 10:27:59 +10003621 global commitinfo parentlist numcommits
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003622 global filehighlight fhighlights findstring nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10003623 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10003624 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003625
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003626 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003627
3628 set id [lindex $displayorder $row]
Paul Mackerras908c3582006-05-20 09:38:11 +10003629 if {[info exists hlview] && ![info exists vhighlights($row)]} {
3630 askvhighlight $row $id
3631 }
3632 if {[info exists filehighlight] && ![info exists fhighlights($row)]} {
3633 askfilehighlight $row $id
3634 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003635 if {$findstring ne {} && ![info exists nhighlights($row)]} {
3636 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10003637 }
Paul Mackerras164ff272006-05-29 19:50:02 +10003638 if {$highlight_related ne "None" && ![info exists rhighlights($row)]} {
3639 askrelhighlight $row $id
3640 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10003641 if {![info exists iddrawn($id)]} {
3642 set col [lsearch -exact [lindex $rowidlist $row] $id]
3643 if {$col < 0} {
3644 puts "oops, row $row id $id not in list"
3645 return
3646 }
3647 if {![info exists commitinfo($id)]} {
3648 getcommit $id
3649 }
3650 assigncolor $id
3651 drawcmittext $id $row $col
3652 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10003653 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003654 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10003655 if {$markingmatches} {
3656 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003657 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003658}
3659
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003660proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10003661 global numcommits iddrawn displayorder curview need_redisplay
3662 global parentlist rowidlist uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003663
3664 if {$row < 0} {
3665 set row 0
3666 }
3667 if {$endrow eq {}} {
3668 set endrow $row
3669 }
3670 if {$endrow >= $numcommits} {
3671 set endrow [expr {$numcommits - 1}]
3672 }
3673
Paul Mackerras03800812007-08-29 21:45:21 +10003674 set rl1 [expr {$row - $downarrowlen - 3}]
3675 if {$rl1 < 0} {
3676 set rl1 0
3677 }
3678 set ro1 [expr {$row - 3}]
3679 if {$ro1 < 0} {
3680 set ro1 0
3681 }
3682 set r2 [expr {$endrow + $uparrowlen + 3}]
3683 if {$r2 > $numcommits} {
3684 set r2 $numcommits
3685 }
3686 for {set r $rl1} {$r < $r2} {incr r} {
3687 if {[lindex $rowidlist $r] ne {}} {
3688 if {$rl1 < $r} {
3689 layoutrows $rl1 $r
3690 }
3691 set rl1 [expr {$r + 1}]
3692 }
3693 }
3694 if {$rl1 < $r} {
3695 layoutrows $rl1 $r
3696 }
3697 optimize_rows $ro1 0 $r2
3698 if {$need_redisplay || $nrows_drawn > 2000} {
3699 clear_display
3700 drawvisible
3701 }
3702
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003703 # make the lines join to already-drawn rows either side
3704 set r [expr {$row - 1}]
3705 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
3706 set r $row
3707 }
3708 set er [expr {$endrow + 1}]
3709 if {$er >= $numcommits ||
3710 ![info exists iddrawn([lindex $displayorder $er])]} {
3711 set er $endrow
3712 }
3713 for {} {$r <= $er} {incr r} {
3714 set id [lindex $displayorder $r]
3715 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003716 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003717 if {$r == $er} break
3718 set nextid [lindex $displayorder [expr {$r + 1}]]
3719 if {$wasdrawn && [info exists iddrawn($nextid)]} {
3720 catch {unset prevlines}
3721 continue
3722 }
3723 drawparentlinks $id $r
3724
3725 if {[info exists lineends($r)]} {
3726 foreach lid $lineends($r) {
3727 unset prevlines($lid)
3728 }
3729 }
3730 set rowids [lindex $rowidlist $r]
3731 foreach lid $rowids {
3732 if {$lid eq {}} continue
3733 if {$lid eq $id} {
3734 # see if this is the first child of any of its parents
3735 foreach p [lindex $parentlist $r] {
3736 if {[lsearch -exact $rowids $p] < 0} {
3737 # make this line extend up to the child
3738 set le [drawlineseg $p $r $er 0]
3739 lappend lineends($le) $p
3740 set prevlines($p) 1
3741 }
3742 }
3743 } elseif {![info exists prevlines($lid)]} {
3744 set le [drawlineseg $lid $r $er 1]
3745 lappend lineends($le) $lid
3746 set prevlines($lid) 1
3747 }
3748 }
3749 }
3750}
3751
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003752proc drawfrac {f0 f1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003753 global canv linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003754
3755 set ymax [lindex [$canv cget -scrollregion] 3]
3756 if {$ymax eq {} || $ymax == 0} return
3757 set y0 [expr {int($f0 * $ymax)}]
3758 set row [expr {int(($y0 - 3) / $linespc) - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003759 set y1 [expr {int($f1 * $ymax)}]
3760 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003761 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003762}
3763
3764proc drawvisible {} {
3765 global canv
3766 eval drawfrac [$canv yview]
3767}
3768
3769proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10003770 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10003771 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003772
3773 allcanvs delete all
3774 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003775 catch {unset linesegs}
Paul Mackerras908c3582006-05-20 09:38:11 +10003776 catch {unset vhighlights}
3777 catch {unset fhighlights}
3778 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10003779 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10003780 set need_redisplay 0
3781 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003782}
3783
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003784proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003785 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003786
3787 set cross {}
3788 set ccross {}
3789 foreach {s e} [rowranges $id] {
3790 if {$e >= $numcommits} {
3791 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003792 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10003793 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003794 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003795 set x [lsearch -exact [lindex $rowidlist $row] $id]
3796 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003797 set olds [lindex $parentlist $row]
3798 set kid [lindex $displayorder $row]
3799 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
3800 if {$kidx < 0} continue
3801 set nextrow [lindex $rowidlist [expr {$row + 1}]]
3802 foreach p $olds {
3803 set px [lsearch -exact $nextrow $p]
3804 if {$px < 0} continue
3805 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
3806 if {[lsearch -exact $ccross $p] >= 0} continue
3807 if {$x == $px + ($kidx < $px? -1: 1)} {
3808 lappend ccross $p
3809 } elseif {[lsearch -exact $cross $p] < 0} {
3810 lappend cross $p
3811 }
3812 }
3813 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003814 }
3815 }
3816 return [concat $ccross {{}} $cross]
3817}
3818
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003819proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11003820 global colormap colors nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003821 global commitrow parentlist children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003822
Paul Mackerras418c4c72006-02-07 09:10:18 +11003823 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003824 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003825 if {[info exists children($curview,$id)]} {
3826 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10003827 } else {
3828 set kids {}
3829 }
3830 if {[llength $kids] == 1} {
3831 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003832 if {[info exists colormap($child)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003833 && [llength [lindex $parentlist $commitrow($curview,$child)]] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003834 set colormap($id) $colormap($child)
3835 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003836 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003837 }
3838 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003839 set origbad {}
3840 foreach x [findcrossings $id] {
3841 if {$x eq {}} {
3842 # delimiter between corner crossings and other crossings
3843 if {[llength $badcolors] >= $ncolors - 1} break
3844 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003845 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003846 if {[info exists colormap($x)]
3847 && [lsearch -exact $badcolors $colormap($x)] < 0} {
3848 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003849 }
3850 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003851 if {[llength $badcolors] >= $ncolors} {
3852 set badcolors $origbad
3853 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003854 set origbad $badcolors
3855 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003856 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003857 if {[info exists colormap($child)]
3858 && [lsearch -exact $badcolors $colormap($child)] < 0} {
3859 lappend badcolors $colormap($child)
3860 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003861 foreach p [lindex $parentlist $commitrow($curview,$child)] {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003862 if {[info exists colormap($p)]
3863 && [lsearch -exact $badcolors $colormap($p)] < 0} {
3864 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003865 }
3866 }
3867 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003868 if {[llength $badcolors] >= $ncolors} {
3869 set badcolors $origbad
3870 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003871 }
3872 for {set i 0} {$i <= $ncolors} {incr i} {
3873 set c [lindex $colors $nextcolor]
3874 if {[incr nextcolor] >= $ncolors} {
3875 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003876 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003877 if {[lsearch -exact $badcolors $c]} break
3878 }
3879 set colormap($id) $c
3880}
3881
Paul Mackerrasa823a912005-06-21 10:01:38 +10003882proc bindline {t id} {
3883 global canv
3884
Paul Mackerrasa823a912005-06-21 10:01:38 +10003885 $canv bind $t <Enter> "lineenter %x %y $id"
3886 $canv bind $t <Motion> "linemotion %x %y $id"
3887 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10003888 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10003889}
3890
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003891proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10003892 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003893 global linespc lthickness
Paul Mackerras8a485712006-07-06 10:21:23 +10003894 global canv mainfont commitrow rowtextx curview fgcolor bgcolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003895
3896 set marks {}
3897 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003898 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003899 if {[info exists idtags($id)]} {
3900 set marks $idtags($id)
3901 set ntags [llength $marks]
3902 }
3903 if {[info exists idheads($id)]} {
3904 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003905 set nheads [llength $idheads($id)]
3906 }
3907 if {[info exists idotherrefs($id)]} {
3908 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003909 }
3910 if {$marks eq {}} {
3911 return $xt
3912 }
3913
3914 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003915 set yt [expr {$y1 - 0.5 * $linespc}]
3916 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003917 set xvals {}
3918 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10003919 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003920 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10003921 incr i
3922 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
3923 set wid [font measure [concat $mainfont bold] $tag]
3924 } else {
3925 set wid [font measure $mainfont $tag]
3926 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003927 lappend xvals $xt
3928 lappend wvals $wid
3929 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
3930 }
3931 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
3932 -width $lthickness -fill black -tags tag.$id]
3933 $canv lower $t
3934 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003935 set xl [expr {$x + $delta}]
3936 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras8a485712006-07-06 10:21:23 +10003937 set font $mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003938 if {[incr ntags -1] >= 0} {
3939 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003940 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
3941 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10003942 -width 1 -outline black -fill yellow -tags tag.$id]
3943 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003944 set rowtextx($commitrow($curview,$id)) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003945 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003946 # draw a head or other ref
3947 if {[incr nheads -1] >= 0} {
3948 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10003949 if {$tag eq $mainhead} {
3950 lappend font bold
3951 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003952 } else {
3953 set col "#ddddff"
3954 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003955 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003956 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003957 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02003958 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
3959 set rwid [font measure $mainfont $remoteprefix]
3960 set xi [expr {$x + 1}]
3961 set yti [expr {$yt + 1}]
3962 set xri [expr {$x + $rwid}]
3963 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
3964 -width 0 -fill "#ffddaa" -tags tag.$id
3965 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003966 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003967 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10003968 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10003969 if {$ntags >= 0} {
3970 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10003971 } elseif {$nheads >= 0} {
3972 $canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10003973 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003974 }
3975 return $xt
3976}
3977
Paul Mackerras8d858d12005-08-05 09:52:16 +10003978proc xcoord {i level ln} {
3979 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003980
Paul Mackerras8d858d12005-08-05 09:52:16 +10003981 set x [expr {$canvx0 + $i * $xspc1($ln)}]
3982 if {$i > 0 && $i == $level} {
3983 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
3984 } elseif {$i > $level} {
3985 set x [expr {$x + $xspc2 - $xspc1($ln)}]
3986 }
3987 return $x
3988}
3989
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003990proc show_status {msg} {
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003991 global canv mainfont fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003992
3993 clear_display
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003994 $canv create text 3 3 -anchor nw -text $msg -font $mainfont \
3995 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003996}
3997
Paul Mackerras561d0382006-08-28 22:41:09 +10003998# Insert a new commit as the child of the commit on row $row.
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003999# The new commit will be displayed on row $row and the commits
4000# on that row and below will move down one row.
4001proc insertrow {row newcmit} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004002 global displayorder parentlist commitlisted children
Paul Mackerras03800812007-08-29 21:45:21 +10004003 global commitrow curview rowidlist rowisopt numcommits
4004 global numcommits
4005 global selectedline commitidx ordertok
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004006
4007 if {$row >= $numcommits} {
4008 puts "oops, inserting new row $row but only have $numcommits rows"
4009 return
4010 }
4011 set p [lindex $displayorder $row]
4012 set displayorder [linsert $displayorder $row $newcmit]
4013 set parentlist [linsert $parentlist $row $p]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004014 set kids $children($curview,$p)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004015 lappend kids $newcmit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004016 set children($curview,$p) $kids
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004017 set children($curview,$newcmit) {}
Paul Mackerras561d0382006-08-28 22:41:09 +10004018 set commitlisted [linsert $commitlisted $row 1]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004019 set l [llength $displayorder]
4020 for {set r $row} {$r < $l} {incr r} {
4021 set id [lindex $displayorder $r]
4022 set commitrow($curview,$id) $r
4023 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004024 incr commitidx($curview)
Paul Mackerras03800812007-08-29 21:45:21 +10004025 set ordertok($curview,$newcmit) $ordertok($curview,$p)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004026
4027 set idlist [lindex $rowidlist $row]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004028 if {[llength $kids] == 1} {
4029 set col [lsearch -exact $idlist $p]
4030 lset idlist $col $newcmit
4031 } else {
4032 set col [llength $idlist]
4033 lappend idlist $newcmit
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004034 }
4035 set rowidlist [linsert $rowidlist $row $idlist]
Paul Mackerras03800812007-08-29 21:45:21 +10004036 set rowisopt [linsert $rowisopt $row 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004037
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004038 incr numcommits
4039
Paul Mackerras561d0382006-08-28 22:41:09 +10004040 if {[info exists selectedline] && $selectedline >= $row} {
4041 incr selectedline
4042 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10004043 redisplay
4044}
4045
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004046# Remove a commit that was inserted with insertrow on row $row.
4047proc removerow {row} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004048 global displayorder parentlist commitlisted children
Paul Mackerras03800812007-08-29 21:45:21 +10004049 global commitrow curview rowidlist rowisopt numcommits
4050 global numcommits
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004051 global linesegends selectedline commitidx
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004052
4053 if {$row >= $numcommits} {
4054 puts "oops, removing row $row but only have $numcommits rows"
4055 return
4056 }
4057 set rp1 [expr {$row + 1}]
4058 set id [lindex $displayorder $row]
4059 set p [lindex $parentlist $row]
4060 set displayorder [lreplace $displayorder $row $row]
4061 set parentlist [lreplace $parentlist $row $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004062 set commitlisted [lreplace $commitlisted $row $row]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004063 set kids $children($curview,$p)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004064 set i [lsearch -exact $kids $id]
4065 if {$i >= 0} {
4066 set kids [lreplace $kids $i $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004067 set children($curview,$p) $kids
4068 }
4069 set l [llength $displayorder]
4070 for {set r $row} {$r < $l} {incr r} {
4071 set id [lindex $displayorder $r]
4072 set commitrow($curview,$id) $r
4073 }
4074 incr commitidx($curview) -1
4075
4076 set rowidlist [lreplace $rowidlist $row $row]
Paul Mackerras03800812007-08-29 21:45:21 +10004077 set rowisopt [lreplace $rowisopt $row $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004078
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004079 incr numcommits -1
4080
4081 if {[info exists selectedline] && $selectedline > $row} {
4082 incr selectedline -1
4083 }
4084 redisplay
4085}
4086
Paul Mackerras94a2eed2005-08-07 15:27:57 +10004087# Don't change the text pane cursor if it is currently the hand cursor,
4088# showing that we are over a sha1 ID link.
4089proc settextcursor {c} {
4090 global ctext curtextcursor
4091
4092 if {[$ctext cget -cursor] == $curtextcursor} {
4093 $ctext config -cursor $c
4094 }
4095 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00004096}
4097
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004098proc nowbusy {what} {
4099 global isbusy
4100
4101 if {[array names isbusy] eq {}} {
4102 . config -cursor watch
4103 settextcursor watch
4104 }
4105 set isbusy($what) 1
4106}
4107
4108proc notbusy {what} {
4109 global isbusy maincursor textcursor
4110
4111 catch {unset isbusy($what)}
4112 if {[array names isbusy] eq {}} {
4113 . config -cursor $maincursor
4114 settextcursor $textcursor
4115 }
4116}
4117
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004118proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004119 global findtype findstring
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004120 if {$findtype == "Regexp"} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004121 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004122 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004123 set fs $findstring
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004124 if {$findtype == "IgnCase"} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004125 set f [string tolower $f]
4126 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004127 }
4128 set matches {}
4129 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004130 set l [string length $fs]
4131 while {[set j [string first $fs $f $i]] >= 0} {
4132 lappend matches [list $j [expr {$j+$l-1}]]
4133 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004134 }
4135 }
4136 return $matches
4137}
4138
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004139proc dofind {{rev 0}} {
4140 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004141
Paul Mackerras98f350e2005-05-15 05:56:51 +00004142 unmarkmatches
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004143 cancel_next_highlight
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004144 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004145 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras98f350e2005-05-15 05:56:51 +00004146 if {![info exists selectedline]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004147 set findstartline [lindex [visiblerows] $rev]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004148 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004149 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00004150 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004151 set findcurline $findstartline
4152 nowbusy finding
4153 if {!$rev} {
4154 run findmore
4155 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004156 if {$findcurline == 0} {
4157 set findcurline $numcommits
Paul Mackerras8ed16482006-03-02 22:56:44 +11004158 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004159 incr findcurline -1
4160 run findmorerev
4161 }
4162}
4163
4164proc findnext {restart} {
4165 global findcurline
4166 if {![info exists findcurline]} {
4167 if {$restart} {
4168 dofind
4169 } else {
4170 bell
4171 }
4172 } else {
4173 run findmore
4174 nowbusy finding
4175 }
4176}
4177
4178proc findprev {} {
4179 global findcurline
4180 if {![info exists findcurline]} {
4181 dofind 1
4182 } else {
4183 run findmorerev
4184 nowbusy finding
4185 }
4186}
4187
4188proc findmore {} {
4189 global commitdata commitinfo numcommits findstring findpattern findloc
Paul Mackerras005a2f42007-07-26 22:36:39 +10004190 global findstartline findcurline displayorder
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004191
4192 set fldtypes {Headline Author Date Committer CDate Comments}
4193 set l [expr {$findcurline + 1}]
4194 if {$l >= $numcommits} {
4195 set l 0
4196 }
4197 if {$l <= $findstartline} {
4198 set lim [expr {$findstartline + 1}]
4199 } else {
4200 set lim $numcommits
4201 }
4202 if {$lim - $l > 500} {
4203 set lim [expr {$l + 500}]
4204 }
4205 set last 0
4206 for {} {$l < $lim} {incr l} {
4207 set id [lindex $displayorder $l]
Paul Mackerras005a2f42007-07-26 22:36:39 +10004208 # shouldn't happen unless git log doesn't give all the commits...
4209 if {![info exists commitdata($id)]} continue
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004210 if {![doesmatch $commitdata($id)]} continue
Paul Mackerras8ed16482006-03-02 22:56:44 +11004211 if {![info exists commitinfo($id)]} {
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11004212 getcommit $id
Paul Mackerras8ed16482006-03-02 22:56:44 +11004213 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004214 set info $commitinfo($id)
Paul Mackerras98f350e2005-05-15 05:56:51 +00004215 foreach f $info ty $fldtypes {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004216 if {($findloc eq "All fields" || $findloc eq $ty) &&
4217 [doesmatch $f]} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004218 findselectline $l
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004219 notbusy finding
4220 return 0
Paul Mackerras98f350e2005-05-15 05:56:51 +00004221 }
4222 }
4223 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004224 if {$l == $findstartline + 1} {
Paul Mackerras98f350e2005-05-15 05:56:51 +00004225 bell
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004226 unset findcurline
4227 notbusy finding
4228 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004229 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004230 set findcurline [expr {$l - 1}]
4231 return 1
4232}
4233
4234proc findmorerev {} {
4235 global commitdata commitinfo numcommits findstring findpattern findloc
Paul Mackerras005a2f42007-07-26 22:36:39 +10004236 global findstartline findcurline displayorder
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004237
4238 set fldtypes {Headline Author Date Committer CDate Comments}
4239 set l $findcurline
4240 if {$l == 0} {
4241 set l $numcommits
4242 }
4243 incr l -1
4244 if {$l >= $findstartline} {
4245 set lim [expr {$findstartline - 1}]
4246 } else {
4247 set lim -1
4248 }
4249 if {$l - $lim > 500} {
4250 set lim [expr {$l - 500}]
4251 }
4252 set last 0
4253 for {} {$l > $lim} {incr l -1} {
4254 set id [lindex $displayorder $l]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10004255 if {![info exists commitdata($id)]} continue
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004256 if {![doesmatch $commitdata($id)]} continue
4257 if {![info exists commitinfo($id)]} {
4258 getcommit $id
4259 }
4260 set info $commitinfo($id)
4261 foreach f $info ty $fldtypes {
4262 if {($findloc eq "All fields" || $findloc eq $ty) &&
4263 [doesmatch $f]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004264 findselectline $l
4265 notbusy finding
4266 return 0
4267 }
4268 }
4269 }
4270 if {$l == -1} {
4271 bell
4272 unset findcurline
4273 notbusy finding
4274 return 0
4275 }
4276 set findcurline [expr {$l + 1}]
4277 return 1
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004278}
4279
4280proc findselectline {l} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004281 global findloc commentend ctext findcurline markingmatches
4282
4283 set markingmatches 1
4284 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10004285 selectline $l 1
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004286 if {$findloc == "All fields" || $findloc == "Comments"} {
4287 # highlight the matches in the comments
4288 set f [$ctext get 1.0 $commentend]
4289 set matches [findmatches $f]
4290 foreach match $matches {
4291 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004292 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004293 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
4294 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004295 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10004296 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00004297}
4298
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004299# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10004300proc markmatches {canv l str tag matches font row} {
4301 global selectedline
4302
Paul Mackerras98f350e2005-05-15 05:56:51 +00004303 set bbox [$canv bbox $tag]
4304 set x0 [lindex $bbox 0]
4305 set y0 [lindex $bbox 1]
4306 set y1 [lindex $bbox 3]
4307 foreach match $matches {
4308 set start [lindex $match 0]
4309 set end [lindex $match 1]
4310 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004311 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
4312 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
4313 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
4314 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004315 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004316 $canv lower $t
Paul Mackerras005a2f42007-07-26 22:36:39 +10004317 if {[info exists selectedline] && $row == $selectedline} {
4318 $canv raise $t secsel
4319 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004320 }
4321}
4322
4323proc unmarkmatches {} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004324 global findids markingmatches findcurline
4325
Paul Mackerras98f350e2005-05-15 05:56:51 +00004326 allcanvs delete matches
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004327 catch {unset findids}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004328 set markingmatches 0
4329 catch {unset findcurline}
Paul Mackerras98f350e2005-05-15 05:56:51 +00004330}
4331
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004332proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004333 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004334 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00004335 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00004336 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00004337 set yfrac [lindex [$canv yview] 0]
4338 set y [expr {$y + $yfrac * $ymax}]
4339 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
4340 if {$l < 0} {
4341 set l 0
4342 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004343 if {$w eq $canv} {
4344 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
4345 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004346 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004347 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004348}
4349
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004350proc commit_descriptor {p} {
4351 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10004352 if {![info exists commitinfo($p)]} {
4353 getcommit $p
4354 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004355 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10004356 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004357 set l [lindex $commitinfo($p) 0]
4358 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004359 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004360}
4361
Paul Mackerras106288c2005-08-19 23:11:39 +10004362# append some text to the ctext widget, and make any SHA1 ID
4363# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004364proc appendwithlinks {text tags} {
Paul Mackerras97645682007-08-23 22:24:38 +10004365 global ctext commitrow linknum curview pendinglinks
Paul Mackerras106288c2005-08-19 23:11:39 +10004366
4367 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004368 $ctext insert end $text $tags
Paul Mackerras106288c2005-08-19 23:11:39 +10004369 set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
4370 foreach l $links {
4371 set s [lindex $l 0]
4372 set e [lindex $l 1]
4373 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10004374 incr e
Paul Mackerras106288c2005-08-19 23:11:39 +10004375 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10004376 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10004377 incr linknum
4378 }
Paul Mackerras97645682007-08-23 22:24:38 +10004379}
4380
4381proc setlink {id lk} {
4382 global curview commitrow ctext pendinglinks commitinterest
4383
4384 if {[info exists commitrow($curview,$id)]} {
4385 $ctext tag conf $lk -foreground blue -underline 1
4386 $ctext tag bind $lk <1> [list selectline $commitrow($curview,$id) 1]
4387 $ctext tag bind $lk <Enter> {linkcursor %W 1}
4388 $ctext tag bind $lk <Leave> {linkcursor %W -1}
4389 } else {
4390 lappend pendinglinks($id) $lk
4391 lappend commitinterest($id) {makelink %I}
4392 }
4393}
4394
4395proc makelink {id} {
4396 global pendinglinks
4397
4398 if {![info exists pendinglinks($id)]} return
4399 foreach lk $pendinglinks($id) {
4400 setlink $id $lk
4401 }
4402 unset pendinglinks($id)
4403}
4404
4405proc linkcursor {w inc} {
4406 global linkentercount curtextcursor
4407
4408 if {[incr linkentercount $inc] > 0} {
4409 $w configure -cursor hand2
4410 } else {
4411 $w configure -cursor $curtextcursor
4412 if {$linkentercount < 0} {
4413 set linkentercount 0
4414 }
4415 }
Paul Mackerras106288c2005-08-19 23:11:39 +10004416}
4417
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004418proc viewnextline {dir} {
4419 global canv linespc
4420
4421 $canv delete hover
4422 set ymax [lindex [$canv cget -scrollregion] 3]
4423 set wnow [$canv yview]
4424 set wtop [expr {[lindex $wnow 0] * $ymax}]
4425 set newtop [expr {$wtop + $dir * $linespc}]
4426 if {$newtop < 0} {
4427 set newtop 0
4428 } elseif {$newtop > $ymax} {
4429 set newtop $ymax
4430 }
4431 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
4432}
4433
Paul Mackerrasef030b82006-06-04 11:50:38 +10004434# add a list of tag or branch names at position pos
4435# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10004436proc appendrefs {pos ids var} {
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004437 global ctext commitrow linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004438
Paul Mackerrasef030b82006-06-04 11:50:38 +10004439 if {[catch {$ctext index $pos}]} {
4440 return 0
4441 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004442 $ctext conf -state normal
4443 $ctext delete $pos "$pos lineend"
4444 set tags {}
4445 foreach id $ids {
4446 foreach tag [set $var\($id\)] {
4447 lappend tags [list $tag $id]
4448 }
4449 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004450 if {[llength $tags] > $maxrefs} {
4451 $ctext insert $pos "many ([llength $tags])"
4452 } else {
4453 set tags [lsort -index 0 -decreasing $tags]
4454 set sep {}
4455 foreach ti $tags {
4456 set id [lindex $ti 1]
4457 set lk link$linknum
4458 incr linknum
4459 $ctext tag delete $lk
4460 $ctext insert $pos $sep
4461 $ctext insert $pos [lindex $ti 0] $lk
Paul Mackerras97645682007-08-23 22:24:38 +10004462 setlink $id $lk
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004463 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004464 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004465 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004466 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10004467 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004468}
4469
4470# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10004471proc dispneartags {delay} {
4472 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004473
4474 if {![info exists selectedline] || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10004475 after cancel dispnexttag
4476 if {$delay} {
4477 after 200 dispnexttag
4478 set tagphase -1
4479 } else {
4480 after idle dispnexttag
4481 set tagphase 0
4482 }
4483}
4484
4485proc dispnexttag {} {
4486 global selectedline currentid showneartags tagphase ctext
4487
4488 if {![info exists selectedline] || !$showneartags} return
4489 switch -- $tagphase {
4490 0 {
4491 set dtags [desctags $currentid]
4492 if {$dtags ne {}} {
4493 appendrefs precedes $dtags idtags
4494 }
4495 }
4496 1 {
4497 set atags [anctags $currentid]
4498 if {$atags ne {}} {
4499 appendrefs follows $atags idtags
4500 }
4501 }
4502 2 {
4503 set dheads [descheads $currentid]
4504 if {$dheads ne {}} {
4505 if {[appendrefs branch $dheads idheads] > 1
4506 && [$ctext get "branch -3c"] eq "h"} {
4507 # turn "Branch" into "Branches"
4508 $ctext conf -state normal
4509 $ctext insert "branch -2c" "es"
4510 $ctext conf -state disabled
4511 }
4512 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004513 }
4514 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004515 if {[incr tagphase] <= 2} {
4516 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004517 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004518}
4519
Paul Mackerras03800812007-08-29 21:45:21 +10004520proc make_secsel {l} {
4521 global linehtag linentag linedtag canv canv2 canv3
4522
4523 if {![info exists linehtag($l)]} return
4524 $canv delete secsel
4525 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
4526 -tags secsel -fill [$canv cget -selectbackground]]
4527 $canv lower $t
4528 $canv2 delete secsel
4529 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
4530 -tags secsel -fill [$canv2 cget -selectbackground]]
4531 $canv2 lower $t
4532 $canv3 delete secsel
4533 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
4534 -tags secsel -fill [$canv3 cget -selectbackground]]
4535 $canv3 lower $t
4536}
4537
Paul Mackerrasd6982062005-08-06 22:06:06 +10004538proc selectline {l isnew} {
Paul Mackerras03800812007-08-29 21:45:21 +10004539 global canv ctext commitinfo selectedline
4540 global displayorder
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004541 global canvy0 linespc parentlist children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004542 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004543 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004544 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10004545 global cmitmode showneartags allcommits
Paul Mackerrasd6982062005-08-06 22:06:06 +10004546
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004547 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00004548 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10004549 normalline
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004550 cancel_next_highlight
Paul Mackerras887c9962007-08-20 19:36:20 +10004551 unsel_reflist
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004552 if {$l < 0 || $l >= $numcommits} return
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004553 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00004554 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00004555 set ytop [expr {$y - $linespc - 1}]
4556 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004557 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004558 set wtop [expr {[lindex $wnow 0] * $ymax}]
4559 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00004560 set wh [expr {$wbot - $wtop}]
4561 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00004562 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00004563 if {$ybot < $wtop} {
4564 set newtop [expr {$y - $wh / 2.0}]
4565 } else {
4566 set newtop $ytop
4567 if {$newtop > $wtop - $linespc} {
4568 set newtop [expr {$wtop - $linespc}]
4569 }
Paul Mackerras17386062005-05-18 22:51:00 +00004570 }
Paul Mackerras58422152005-05-19 10:56:42 +00004571 } elseif {$ybot > $wbot} {
4572 if {$ytop > $wbot} {
4573 set newtop [expr {$y - $wh / 2.0}]
4574 } else {
4575 set newtop [expr {$ybot - $wh}]
4576 if {$newtop < $wtop + $linespc} {
4577 set newtop [expr {$wtop + $linespc}]
4578 }
Paul Mackerras17386062005-05-18 22:51:00 +00004579 }
Paul Mackerras58422152005-05-19 10:56:42 +00004580 }
4581 if {$newtop != $wtop} {
4582 if {$newtop < 0} {
4583 set newtop 0
4584 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004585 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004586 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004587 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004588
Paul Mackerras03800812007-08-29 21:45:21 +10004589 make_secsel $l
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004590
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004591 if {$isnew} {
4592 addtohistory [list selectline $l 0]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004593 }
4594
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004595 set selectedline $l
4596
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004597 set id [lindex $displayorder $l]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004598 set currentid $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004599 $sha1entry delete 0 end
4600 $sha1entry insert 0 $id
4601 $sha1entry selection from 0
4602 $sha1entry selection to end
Paul Mackerras164ff272006-05-29 19:50:02 +10004603 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004604
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004605 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004606 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10004607 set linknum 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00004608 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11004609 set date [formatdate [lindex $info 2]]
4610 $ctext insert end "Author: [lindex $info 1] $date\n"
4611 set date [formatdate [lindex $info 4]]
4612 $ctext insert end "Committer: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004613 if {[info exists idtags($id)]} {
4614 $ctext insert end "Tags:"
4615 foreach tag $idtags($id) {
4616 $ctext insert end " $tag"
4617 }
4618 $ctext insert end "\n"
4619 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004620
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004621 set headers {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004622 set olds [lindex $parentlist $l]
4623 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004624 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10004625 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004626 if {$np >= $mergemax} {
4627 set tag mmax
4628 } else {
4629 set tag m$np
4630 }
4631 $ctext insert end "Parent: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004632 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004633 incr np
4634 }
4635 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004636 foreach p $olds {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004637 append headers "Parent: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004638 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004639 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004640
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004641 foreach c $children($curview,$id) {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004642 append headers "Child: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004643 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004644
4645 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004646 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004647 if {$showneartags} {
4648 if {![info exists allcommits]} {
4649 getallcommits
4650 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004651 $ctext insert end "Branch: "
4652 $ctext mark set branch "end -1c"
4653 $ctext mark gravity branch left
Paul Mackerrasef030b82006-06-04 11:50:38 +10004654 $ctext insert end "\nFollows: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004655 $ctext mark set follows "end -1c"
4656 $ctext mark gravity follows left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004657 $ctext insert end "\nPrecedes: "
4658 $ctext mark set precedes "end -1c"
4659 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004660 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10004661 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004662 }
4663 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10004664 set comment [lindex $info 5]
4665 if {[string first "\r" $comment] >= 0} {
4666 set comment [string map {"\r" "\n "} $comment]
4667 }
4668 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10004669
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004670 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004671 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004672 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004673
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004674 init_flist "Comments"
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004675 if {$cmitmode eq "tree"} {
4676 gettree $id
4677 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11004678 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11004679 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004680 mergediff $id $l
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004681 }
4682}
4683
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004684proc selfirstline {} {
4685 unmarkmatches
4686 selectline 0 1
4687}
4688
4689proc sellastline {} {
4690 global numcommits
4691 unmarkmatches
4692 set l [expr {$numcommits - 1}]
4693 selectline $l 1
4694}
4695
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004696proc selnextline {dir} {
4697 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04004698 focus .
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004699 if {![info exists selectedline]} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004700 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004701 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004702 selectline $l 1
4703}
4704
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004705proc selnextpage {dir} {
4706 global canv linespc selectedline numcommits
4707
4708 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
4709 if {$lpp < 1} {
4710 set lpp 1
4711 }
4712 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10004713 drawvisible
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004714 if {![info exists selectedline]} return
4715 set l [expr {$selectedline + $dir * $lpp}]
4716 if {$l < 0} {
4717 set l 0
4718 } elseif {$l >= $numcommits} {
4719 set l [expr $numcommits - 1]
4720 }
4721 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004722 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004723}
4724
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004725proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004726 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004727
4728 catch {unset selectedline}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004729 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004730 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10004731 rhighlight_none
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004732 cancel_next_highlight
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004733}
4734
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004735proc reselectline {} {
4736 global selectedline
4737
4738 if {[info exists selectedline]} {
4739 selectline $selectedline 0
4740 }
4741}
4742
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004743proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004744 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004745
Paul Mackerras2516dae2006-04-21 10:35:31 +10004746 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004747 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10004748 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004749 return
4750 }
4751
4752 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004753 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004754 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004755 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004756 }
4757 incr historyindex
4758 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004759 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004760 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004761 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004762 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004763 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004764}
4765
Paul Mackerras2516dae2006-04-21 10:35:31 +10004766proc godo {elt} {
4767 global curview
4768
4769 set view [lindex $elt 0]
4770 set cmd [lindex $elt 1]
4771 if {$curview != $view} {
4772 showview $view
4773 }
4774 eval $cmd
4775}
4776
Paul Mackerrasd6982062005-08-06 22:06:06 +10004777proc goback {} {
4778 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04004779 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10004780
4781 if {$historyindex > 1} {
4782 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10004783 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004784 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004785 }
4786 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004787 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004788 }
4789}
4790
4791proc goforw {} {
4792 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04004793 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10004794
4795 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004796 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004797 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10004798 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004799 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004800 }
4801 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004802 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004803 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004804}
4805
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004806proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004807 global treefilelist treeidlist diffids diffmergeid treepending
4808 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004809
4810 set diffids $id
4811 catch {unset diffmergeid}
4812 if {![info exists treefilelist($id)]} {
4813 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004814 if {$id eq $nullid} {
4815 set cmd [list | git ls-files]
4816 } elseif {$id eq $nullid2} {
4817 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004818 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10004819 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004820 }
4821 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004822 return
4823 }
4824 set treepending $id
4825 set treefilelist($id) {}
4826 set treeidlist($id) {}
4827 fconfigure $gtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004828 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004829 }
4830 } else {
4831 setfilelist $id
4832 }
4833}
4834
4835proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004836 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004837
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004838 set nl 0
4839 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004840 if {$diffids eq $nullid} {
4841 set fname $line
4842 } else {
4843 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10004844 set i [string first "\t" $line]
4845 if {$i < 0} continue
4846 set sha1 [lindex $line 2]
4847 set fname [string range $line [expr {$i+1}] end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004848 if {[string index $fname 0] eq "\""} {
4849 set fname [lindex $fname 0]
4850 }
4851 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004852 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004853 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004854 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004855 if {![eof $gtf]} {
4856 return [expr {$nl >= 1000? 2: 1}]
4857 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004858 close $gtf
4859 unset treepending
4860 if {$cmitmode ne "tree"} {
4861 if {![info exists diffmergeid]} {
4862 gettreediffs $diffids
4863 }
4864 } elseif {$id ne $diffids} {
4865 gettree $diffids
4866 } else {
4867 setfilelist $id
4868 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004869 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004870}
4871
4872proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004873 global treefilelist treeidlist diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004874 global ctext commentend
4875
4876 set i [lsearch -exact $treefilelist($diffids) $f]
4877 if {$i < 0} {
4878 puts "oops, $f not in list for id $diffids"
4879 return
4880 }
Paul Mackerras8f489362007-07-13 19:49:37 +10004881 if {$diffids eq $nullid} {
4882 if {[catch {set bf [open $f r]} err]} {
4883 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004884 return
4885 }
4886 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10004887 set blob [lindex $treeidlist($diffids) $i]
4888 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
4889 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004890 return
4891 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004892 }
4893 fconfigure $bf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004894 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004895 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004896 clear_ctext $commentend
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004897 $ctext insert end "\n"
4898 $ctext insert end "$f\n" filesep
4899 $ctext config -state disabled
4900 $ctext yview $commentend
4901}
4902
4903proc getblobline {bf id} {
4904 global diffids cmitmode ctext
4905
4906 if {$id ne $diffids || $cmitmode ne "tree"} {
4907 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004908 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004909 }
4910 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004911 set nl 0
4912 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004913 $ctext insert end "$line\n"
4914 }
4915 if {[eof $bf]} {
4916 # delete last newline
4917 $ctext delete "end - 2c" "end - 1c"
4918 close $bf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004919 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004920 }
4921 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004922 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004923}
4924
Paul Mackerras79b2c752006-04-02 20:47:40 +10004925proc mergediff {id l} {
4926 global diffmergeid diffopts mdifffd
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004927 global diffids
Paul Mackerras79b2c752006-04-02 20:47:40 +10004928 global parentlist
Paul Mackerrase2ed4322005-07-17 03:39:44 -04004929
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004930 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004931 set diffids $id
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004932 # this doesn't seem to actually affect anything...
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004933 set env(GIT_DIFF_OPTS) $diffopts
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03004934 set cmd [concat | git diff-tree --no-commit-id --cc $id]
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004935 if {[catch {set mdf [open $cmd r]} err]} {
4936 error_popup "Error getting merge diffs: $err"
4937 return
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004938 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004939 fconfigure $mdf -blocking 0
4940 set mdifffd($id) $mdf
Paul Mackerras79b2c752006-04-02 20:47:40 +10004941 set np [llength [lindex $parentlist $l]]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004942 filerun $mdf [list getmergediffline $mdf $id $np]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004943}
4944
Paul Mackerras79b2c752006-04-02 20:47:40 +10004945proc getmergediffline {mdf id np} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004946 global diffmergeid ctext cflist mergemax
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004947 global difffilestart mdifffd
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004948
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004949 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004950 set nr 0
4951 while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
4952 if {![info exists diffmergeid] || $id != $diffmergeid
4953 || $mdf != $mdifffd($id)} {
4954 close $mdf
4955 return 0
4956 }
4957 if {[regexp {^diff --cc (.*)} $line match fname]} {
4958 # start of a new file
4959 $ctext insert end "\n"
4960 set here [$ctext index "end - 1c"]
4961 lappend difffilestart $here
4962 add_flist [list $fname]
4963 set l [expr {(78 - [string length $fname]) / 2}]
4964 set pad [string range "----------------------------------------" 1 $l]
4965 $ctext insert end "$pad $fname $pad\n" filesep
4966 } elseif {[regexp {^@@} $line]} {
4967 $ctext insert end "$line\n" hunksep
4968 } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
4969 # do nothing
4970 } else {
4971 # parse the prefix - one ' ', '-' or '+' for each parent
4972 set spaces {}
4973 set minuses {}
4974 set pluses {}
4975 set isbad 0
4976 for {set j 0} {$j < $np} {incr j} {
4977 set c [string range $line $j $j]
4978 if {$c == " "} {
4979 lappend spaces $j
4980 } elseif {$c == "-"} {
4981 lappend minuses $j
4982 } elseif {$c == "+"} {
4983 lappend pluses $j
4984 } else {
4985 set isbad 1
4986 break
4987 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004988 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004989 set tags {}
4990 set num {}
4991 if {!$isbad && $minuses ne {} && $pluses eq {}} {
4992 # line doesn't appear in result, parents in $minuses have the line
4993 set num [lindex $minuses 0]
4994 } elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
4995 # line appears in result, parents in $pluses don't have the line
4996 lappend tags mresult
4997 set num [lindex $spaces 0]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004998 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004999 if {$num ne {}} {
5000 if {$num >= $mergemax} {
5001 set num "max"
5002 }
5003 lappend tags m$num
5004 }
5005 $ctext insert end "$line\n" $tags
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05005006 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05005007 }
5008 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005009 if {[eof $mdf]} {
5010 close $mdf
5011 return 0
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05005012 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005013 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05005014}
5015
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005016proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005017 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005018
5019 set diffids $ids
5020 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10005021 if {![info exists treediffs($ids)] ||
5022 [lsearch -exact $ids $nullid] >= 0 ||
5023 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005024 if {![info exists treepending]} {
5025 gettreediffs $ids
5026 }
5027 } else {
5028 addtocflist $ids
5029 }
5030}
5031
5032proc addtocflist {ids} {
5033 global treediffs cflist
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10005034 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005035 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005036}
5037
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005038proc diffcmd {ids flags} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005039 global nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005040
5041 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10005042 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005043 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005044 if {[llength $ids] > 1 && $j < 0} {
5045 # comparing working directory with some specific revision
5046 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005047 if {$i == 0} {
5048 lappend cmd -R [lindex $ids 1]
5049 } else {
5050 lappend cmd [lindex $ids 0]
5051 }
5052 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10005053 # comparing working directory with index
5054 set cmd [concat | git diff-files $flags]
5055 if {$j == 1} {
5056 lappend cmd -R
5057 }
5058 }
5059 } elseif {$j >= 0} {
5060 set cmd [concat | git diff-index --cached $flags]
5061 if {[llength $ids] > 1} {
5062 # comparing index with specific revision
5063 if {$i == 0} {
5064 lappend cmd -R [lindex $ids 1]
5065 } else {
5066 lappend cmd [lindex $ids 0]
5067 }
5068 } else {
5069 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005070 lappend cmd HEAD
5071 }
5072 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10005073 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005074 }
5075 return $cmd
5076}
5077
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005078proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10005079 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005080
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005081 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005082 set treediff {}
Paul Mackerras8f489362007-07-13 19:49:37 +10005083 if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005084 fconfigure $gdtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005085 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005086}
5087
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005088proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005089 global treediff treediffs treepending diffids diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10005090 global cmitmode
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005091
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005092 set nr 0
5093 while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005094 set i [string first "\t" $line]
5095 if {$i >= 0} {
5096 set file [string range $line [expr {$i+1}] end]
5097 if {[string index $file 0] eq "\""} {
5098 set file [lindex $file 0]
5099 }
5100 lappend treediff $file
5101 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005102 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005103 if {![eof $gdtf]} {
5104 return [expr {$nr >= 1000? 2: 1}]
5105 }
5106 close $gdtf
5107 set treediffs($ids) $treediff
5108 unset treepending
5109 if {$cmitmode eq "tree"} {
5110 gettree $diffids
5111 } elseif {$ids != $diffids} {
5112 if {![info exists diffmergeid]} {
5113 gettreediffs $diffids
5114 }
5115 } else {
5116 addtocflist $ids
5117 }
5118 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005119}
5120
Steffen Prohaska890fae72007-08-12 12:05:46 +02005121# empty string or positive integer
5122proc diffcontextvalidate {v} {
5123 return [regexp {^(|[1-9][0-9]*)$} $v]
5124}
5125
5126proc diffcontextchange {n1 n2 op} {
5127 global diffcontextstring diffcontext
5128
5129 if {[string is integer -strict $diffcontextstring]} {
5130 if {$diffcontextstring > 0} {
5131 set diffcontext $diffcontextstring
5132 reselectline
5133 }
5134 }
5135}
5136
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005137proc getblobdiffs {ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005138 global diffopts blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005139 global diffinhdr treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02005140 global diffcontext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005141
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005142 set env(GIT_DIFF_OPTS) $diffopts
Steffen Prohaska890fae72007-08-12 12:05:46 +02005143 if {[catch {set bdf [open [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"] r]} err]} {
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005144 puts "error getting diffs: $err"
5145 return
5146 }
Paul Mackerras4f2c2642005-07-17 11:11:44 -04005147 set diffinhdr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005148 fconfigure $bdf -blocking 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005149 set blobdifffd($ids) $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005150 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005151}
5152
Paul Mackerras89b11d32006-05-02 19:55:31 +10005153proc setinlist {var i val} {
5154 global $var
5155
5156 while {[llength [set $var]] < $i} {
5157 lappend $var {}
5158 }
5159 if {[llength [set $var]] == $i} {
5160 lappend $var $val
5161 } else {
5162 lset $var $i $val
5163 }
5164}
5165
Paul Mackerras9396cd32007-06-23 20:28:15 +10005166proc makediffhdr {fname ids} {
5167 global ctext curdiffstart treediffs
5168
5169 set i [lsearch -exact $treediffs($ids) $fname]
5170 if {$i >= 0} {
5171 setinlist difffilestart $i $curdiffstart
5172 }
5173 set l [expr {(78 - [string length $fname]) / 2}]
5174 set pad [string range "----------------------------------------" 1 $l]
5175 $ctext insert $curdiffstart "$pad $fname $pad" filesep
5176}
5177
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005178proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005179 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04005180 global diffnexthead diffnextnote difffilestart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005181 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005182
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005183 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005184 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005185 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
5186 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
5187 close $bdf
5188 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10005189 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10005190 if {![string compare -length 11 "diff --git " $line]} {
5191 # trim off "diff --git "
5192 set line [string range $line 11 end]
5193 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005194 # start of a new file
5195 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10005196 set curdiffstart [$ctext index "end - 1c"]
5197 $ctext insert end "\n" filesep
5198 # If the name hasn't changed the length will be odd,
5199 # the middle char will be a space, and the two bits either
5200 # side will be a/name and b/name, or "a/name" and "b/name".
5201 # If the name has changed we'll get "rename from" and
Johannes Sixtd1cb2982007-08-16 14:32:29 +02005202 # "rename to" or "copy from" and "copy to" lines following this,
5203 # and we'll use them to get the filenames.
Paul Mackerras9396cd32007-06-23 20:28:15 +10005204 # This complexity is necessary because spaces in the filename(s)
5205 # don't get escaped.
5206 set l [string length $line]
5207 set i [expr {$l / 2}]
5208 if {!(($l & 1) && [string index $line $i] eq " " &&
5209 [string range $line 2 [expr {$i - 1}]] eq \
5210 [string range $line [expr {$i + 3}] end])} {
5211 continue
Paul Mackerras89b11d32006-05-02 19:55:31 +10005212 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10005213 # unescape if quoted and chop off the a/ from the front
5214 if {[string index $line 0] eq "\""} {
5215 set fname [string range [lindex $line 0] 2 end]
5216 } else {
5217 set fname [string range $line 2 [expr {$i - 1}]]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005218 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10005219 makediffhdr $fname $ids
5220
5221 } elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005222 $line match f1l f1c f2l f2c rest]} {
5223 $ctext insert end "$line\n" hunksep
5224 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10005225
5226 } elseif {$diffinhdr} {
Johannes Sixtd1cb2982007-08-16 14:32:29 +02005227 if {![string compare -length 12 "rename from " $line] ||
5228 ![string compare -length 10 "copy from " $line]} {
5229 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10005230 if {[string index $fname 0] eq "\""} {
5231 set fname [lindex $fname 0]
5232 }
5233 set i [lsearch -exact $treediffs($ids) $fname]
5234 if {$i >= 0} {
5235 setinlist difffilestart $i $curdiffstart
5236 }
Johannes Sixtd1cb2982007-08-16 14:32:29 +02005237 } elseif {![string compare -length 10 $line "rename to "] ||
5238 ![string compare -length 8 $line "copy to "]} {
5239 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10005240 if {[string index $fname 0] eq "\""} {
5241 set fname [lindex $fname 0]
5242 }
5243 makediffhdr $fname $ids
5244 } elseif {[string compare -length 3 $line "---"] == 0} {
5245 # do nothing
5246 continue
5247 } elseif {[string compare -length 3 $line "+++"] == 0} {
5248 set diffinhdr 0
5249 continue
5250 }
5251 $ctext insert end "$line\n" filesep
5252
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005253 } else {
5254 set x [string range $line 0 0]
5255 if {$x == "-" || $x == "+"} {
5256 set tag [expr {$x == "+"}]
5257 $ctext insert end "$line\n" d$tag
5258 } elseif {$x == " "} {
5259 $ctext insert end "$line\n"
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005260 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005261 # "\ No newline at end of file",
5262 # or something else we don't recognize
5263 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005264 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005265 }
5266 }
5267 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005268 if {[eof $bdf]} {
5269 close $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005270 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005271 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005272 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005273}
5274
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10005275proc changediffdisp {} {
5276 global ctext diffelide
5277
5278 $ctext tag conf d0 -elide [lindex $diffelide 0]
5279 $ctext tag conf d1 -elide [lindex $diffelide 1]
5280}
5281
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09005282proc prevfile {} {
5283 global difffilestart ctext
5284 set prev [lindex $difffilestart 0]
5285 set here [$ctext index @0,0]
5286 foreach loc $difffilestart {
5287 if {[$ctext compare $loc >= $here]} {
5288 $ctext yview $prev
5289 return
5290 }
5291 set prev $loc
5292 }
5293 $ctext yview $prev
5294}
5295
Paul Mackerras39ad8572005-05-19 12:35:53 +00005296proc nextfile {} {
5297 global difffilestart ctext
5298 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005299 foreach loc $difffilestart {
5300 if {[$ctext compare $loc > $here]} {
5301 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09005302 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00005303 }
5304 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00005305}
5306
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005307proc clear_ctext {{first 1.0}} {
5308 global ctext smarktop smarkbot
Paul Mackerras97645682007-08-23 22:24:38 +10005309 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005310
Paul Mackerras1902c272006-05-25 21:25:13 +10005311 set l [lindex [split $first .] 0]
5312 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
5313 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005314 }
Paul Mackerras1902c272006-05-25 21:25:13 +10005315 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
5316 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005317 }
5318 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10005319 if {$first eq "1.0"} {
5320 catch {unset pendinglinks}
5321 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005322}
5323
5324proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005325 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005326
5327 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10005328 if {[catch {$ctext index anchor}]} {
5329 # no anchor set, use start of selection, or of visible area
5330 set sel [$ctext tag ranges sel]
5331 if {$sel ne {}} {
5332 $ctext mark set anchor [lindex $sel 0]
5333 } elseif {$searchdirn eq "-forwards"} {
5334 $ctext mark set anchor @0,0
5335 } else {
5336 $ctext mark set anchor @0,[winfo height $ctext]
5337 }
5338 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005339 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005340 set here [$ctext search $searchdirn -- $searchstring anchor]
5341 if {$here ne {}} {
5342 $ctext see $here
5343 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005344 searchmarkvisible 1
5345 }
5346}
5347
5348proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005349 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005350
5351 focus $sstring
5352 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10005353 set searchdirn -forwards
5354 if {$searchstring ne {}} {
5355 set sel [$ctext tag ranges sel]
5356 if {$sel ne {}} {
5357 set start "[lindex $sel 0] + 1c"
5358 } elseif {[catch {set start [$ctext index anchor]}]} {
5359 set start "@0,0"
5360 }
5361 set match [$ctext search -count mlen -- $searchstring $start]
5362 $ctext tag remove sel 1.0 end
5363 if {$match eq {}} {
5364 bell
5365 return
5366 }
5367 $ctext see $match
5368 set mend "$match + $mlen c"
5369 $ctext tag add sel $match $mend
5370 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005371 }
Paul Mackerras1902c272006-05-25 21:25:13 +10005372}
5373
5374proc dosearchback {} {
5375 global sstring ctext searchstring searchdirn
5376
5377 focus $sstring
5378 $sstring icursor end
5379 set searchdirn -backwards
5380 if {$searchstring ne {}} {
5381 set sel [$ctext tag ranges sel]
5382 if {$sel ne {}} {
5383 set start [lindex $sel 0]
5384 } elseif {[catch {set start [$ctext index anchor]}]} {
5385 set start @0,[winfo height $ctext]
5386 }
5387 set match [$ctext search -backwards -count ml -- $searchstring $start]
5388 $ctext tag remove sel 1.0 end
5389 if {$match eq {}} {
5390 bell
5391 return
5392 }
5393 $ctext see $match
5394 set mend "$match + $ml c"
5395 $ctext tag add sel $match $mend
5396 $ctext mark unset anchor
5397 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005398}
5399
5400proc searchmark {first last} {
5401 global ctext searchstring
5402
5403 set mend $first.0
5404 while {1} {
5405 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
5406 if {$match eq {}} break
5407 set mend "$match + $mlen c"
5408 $ctext tag add found $match $mend
5409 }
5410}
5411
5412proc searchmarkvisible {doall} {
5413 global ctext smarktop smarkbot
5414
5415 set topline [lindex [split [$ctext index @0,0] .] 0]
5416 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
5417 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
5418 # no overlap with previous
5419 searchmark $topline $botline
5420 set smarktop $topline
5421 set smarkbot $botline
5422 } else {
5423 if {$topline < $smarktop} {
5424 searchmark $topline [expr {$smarktop-1}]
5425 set smarktop $topline
5426 }
5427 if {$botline > $smarkbot} {
5428 searchmark [expr {$smarkbot+1}] $botline
5429 set smarkbot $botline
5430 }
5431 }
5432}
5433
5434proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005435 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005436
Junio C Hamanoe9937d22007-02-01 08:46:38 -05005437 .bleft.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005438 if {$searchstring ne {}} {
5439 searchmarkvisible 0
5440 }
5441}
5442
Paul Mackerras1d10f362005-05-15 12:55:47 +00005443proc setcoords {} {
5444 global linespc charspc canvx0 canvy0 mainfont
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005445 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10005446
Paul Mackerras1d10f362005-05-15 12:55:47 +00005447 set linespc [font metrics $mainfont -linespace]
5448 set charspc [font measure $mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005449 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
5450 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005451 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10005452 set xspc1(0) $linespc
5453 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00005454}
Paul Mackerras1db95b02005-05-09 04:08:39 +00005455
Paul Mackerras1d10f362005-05-15 12:55:47 +00005456proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005457 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005458 global selectedline
5459
5460 set ymax [lindex [$canv cget -scrollregion] 3]
5461 if {$ymax eq {} || $ymax == 0} return
5462 set span [$canv yview]
5463 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005464 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005465 allcanvs yview moveto [lindex $span 0]
5466 drawvisible
5467 if {[info exists selectedline]} {
5468 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005469 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00005470 }
5471}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005472
5473proc incrfont {inc} {
Paul Mackerras887c9962007-08-20 19:36:20 +10005474 global mainfont textfont ctext canv phase cflist showrefstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005475 global charspc tabstop
Paul Mackerrascfb45632005-05-31 12:14:42 +00005476 global stopped entries
Paul Mackerras1d10f362005-05-15 12:55:47 +00005477 unmarkmatches
5478 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
Paul Mackerras1d10f362005-05-15 12:55:47 +00005479 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
5480 setcoords
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005481 $ctext conf -font $textfont -tabs "[expr {$tabstop * $charspc}]"
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005482 $cflist conf -font $textfont
Paul Mackerras1d10f362005-05-15 12:55:47 +00005483 $ctext tag conf filesep -font [concat $textfont bold]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005484 foreach e $entries {
5485 $e conf -font $mainfont
5486 }
Paul Mackerras22626ef2006-04-17 09:56:02 +10005487 if {$phase eq "getcommits"} {
Paul Mackerras1d10f362005-05-15 12:55:47 +00005488 $canv itemconf textitems -font $mainfont
5489 }
Paul Mackerras887c9962007-08-20 19:36:20 +10005490 if {[info exists showrefstop] && [winfo exists $showrefstop]} {
5491 $showrefstop.list conf -font $mainfont
5492 }
Paul Mackerras1d10f362005-05-15 12:55:47 +00005493 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00005494}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005495
Paul Mackerrasee3dc722005-06-25 16:37:13 +10005496proc clearsha1 {} {
5497 global sha1entry sha1string
5498 if {[string length $sha1string] == 40} {
5499 $sha1entry delete 0 end
5500 }
5501}
5502
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005503proc sha1change {n1 n2 op} {
5504 global sha1string currentid sha1but
5505 if {$sha1string == {}
5506 || ([info exists currentid] && $sha1string == $currentid)} {
5507 set state disabled
5508 } else {
5509 set state normal
5510 }
5511 if {[$sha1but cget -state] == $state} return
5512 if {$state == "normal"} {
5513 $sha1but conf -state normal -relief raised -text "Goto: "
5514 } else {
5515 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
5516 }
5517}
5518
5519proc gotocommit {} {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005520 global sha1string currentid commitrow tagids headids
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005521 global displayorder numcommits curview
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005522
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005523 if {$sha1string == {}
5524 || ([info exists currentid] && $sha1string == $currentid)} return
5525 if {[info exists tagids($sha1string)]} {
5526 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11005527 } elseif {[info exists headids($sha1string)]} {
5528 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005529 } else {
5530 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005531 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
5532 set matches {}
Paul Mackerras8ed16482006-03-02 22:56:44 +11005533 foreach i $displayorder {
5534 if {[string match $id* $i]} {
5535 lappend matches $i
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005536 }
5537 }
5538 if {$matches ne {}} {
5539 if {[llength $matches] > 1} {
5540 error_popup "Short SHA1 id $id is ambiguous"
5541 return
5542 }
5543 set id [lindex $matches 0]
5544 }
5545 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005546 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005547 if {[info exists commitrow($curview,$id)]} {
5548 selectline $commitrow($curview,$id) 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005549 return
5550 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005551 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005552 set type "SHA1 id"
5553 } else {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005554 set type "Tag/Head"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005555 }
5556 error_popup "$type $sha1string is not known"
5557}
5558
Paul Mackerras84ba7342005-06-17 00:12:26 +00005559proc lineenter {x y id} {
5560 global hoverx hovery hoverid hovertimer
5561 global commitinfo canv
5562
Paul Mackerras8ed16482006-03-02 22:56:44 +11005563 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00005564 set hoverx $x
5565 set hovery $y
5566 set hoverid $id
5567 if {[info exists hovertimer]} {
5568 after cancel $hovertimer
5569 }
5570 set hovertimer [after 500 linehover]
5571 $canv delete hover
5572}
5573
5574proc linemotion {x y id} {
5575 global hoverx hovery hoverid hovertimer
5576
5577 if {[info exists hoverid] && $id == $hoverid} {
5578 set hoverx $x
5579 set hovery $y
5580 if {[info exists hovertimer]} {
5581 after cancel $hovertimer
5582 }
5583 set hovertimer [after 500 linehover]
5584 }
5585}
5586
5587proc lineleave {id} {
5588 global hoverid hovertimer canv
5589
5590 if {[info exists hoverid] && $id == $hoverid} {
5591 $canv delete hover
5592 if {[info exists hovertimer]} {
5593 after cancel $hovertimer
5594 unset hovertimer
5595 }
5596 unset hoverid
5597 }
5598}
5599
5600proc linehover {} {
5601 global hoverx hovery hoverid hovertimer
5602 global canv linespc lthickness
5603 global commitinfo mainfont
5604
5605 set text [lindex $commitinfo($hoverid) 0]
5606 set ymax [lindex [$canv cget -scrollregion] 3]
5607 if {$ymax == {}} return
5608 set yfrac [lindex [$canv yview] 0]
5609 set x [expr {$hoverx + 2 * $linespc}]
5610 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
5611 set x0 [expr {$x - 2 * $lthickness}]
5612 set y0 [expr {$y - 2 * $lthickness}]
5613 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
5614 set y1 [expr {$y + $linespc + 2 * $lthickness}]
5615 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
5616 -fill \#ffff80 -outline black -width 1 -tags hover]
5617 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10005618 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
5619 -font $mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00005620 $canv raise $t
5621}
5622
Paul Mackerras9843c302005-08-30 10:57:11 +10005623proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005624 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10005625
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005626 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10005627 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005628 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005629 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005630 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005631 if {abs([yc $row] - $y) < $thresh} {
5632 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10005633 }
5634 }
5635 return {}
5636}
5637
Paul Mackerrasf6342482006-02-28 10:02:03 +11005638proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005639 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10005640
Paul Mackerrasf6342482006-02-28 10:02:03 +11005641 # 1 <-> 2, 3 <-> 4, etc...
5642 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005643 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005644 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10005645 set ymax [lindex [$canv cget -scrollregion] 3]
5646 if {$ymax eq {} || $ymax <= 0} return
5647 set view [$canv yview]
5648 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
5649 set yfrac [expr {$yt / $ymax - $yspan / 2}]
5650 if {$yfrac < 0} {
5651 set yfrac 0
5652 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11005653 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10005654}
5655
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005656proc lineclick {x y id isnew} {
Paul Mackerras03800812007-08-29 21:45:21 +10005657 global ctext commitinfo children canv thickerline curview commitrow
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005658
Paul Mackerras8ed16482006-03-02 22:56:44 +11005659 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005660 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005661 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10005662 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005663 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10005664 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10005665 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005666 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005667 if {$isnew} {
5668 set ymax [lindex [$canv cget -scrollregion] 3]
5669 if {$ymax eq {}} return
5670 set yfrac [lindex [$canv yview] 0]
5671 set y [expr {$y + $yfrac * $ymax}]
5672 }
5673 set dirn [clickisonarrow $id $y]
5674 if {$dirn ne {}} {
5675 arrowjump $id $dirn $y
5676 return
5677 }
5678
5679 if {$isnew} {
5680 addtohistory [list lineclick $x $y $id 0]
5681 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005682 # fill the details pane with info about this line
5683 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005684 clear_ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005685 $ctext insert end "Parent:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10005686 $ctext insert end $id link0
5687 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005688 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005689 $ctext insert end "\n\t[lindex $info 0]\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005690 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11005691 set date [formatdate [lindex $info 2]]
5692 $ctext insert end "\tDate:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005693 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005694 if {$kids ne {}} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005695 $ctext insert end "\nChildren:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005696 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10005697 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005698 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11005699 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005700 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005701 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10005702 $ctext insert end $child link$i
5703 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005704 $ctext insert end "\n\t[lindex $info 0]"
5705 $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11005706 set date [formatdate [lindex $info 2]]
5707 $ctext insert end "\n\tDate:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005708 }
5709 }
5710 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005711 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005712}
5713
Paul Mackerras9843c302005-08-30 10:57:11 +10005714proc normalline {} {
5715 global thickerline
5716 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005717 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10005718 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005719 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005720 }
5721}
5722
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005723proc selbyid {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005724 global commitrow curview
5725 if {[info exists commitrow($curview,$id)]} {
5726 selectline $commitrow($curview,$id) 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005727 }
5728}
5729
5730proc mstime {} {
5731 global startmstime
5732 if {![info exists startmstime]} {
5733 set startmstime [clock clicks -milliseconds]
5734 }
5735 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
5736}
5737
5738proc rowmenu {x y id} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005739 global rowctxmenu commitrow selectedline rowmenuid curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005740 global nullid nullid2 fakerowmenu mainhead
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005741
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005742 set rowmenuid $id
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005743 if {![info exists selectedline]
5744 || $commitrow($curview,$id) eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005745 set state disabled
5746 } else {
5747 set state normal
5748 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005749 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005750 set menu $rowctxmenu
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005751 $menu entryconfigure 7 -label "Reset $mainhead branch to here"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005752 } else {
5753 set menu $fakerowmenu
5754 }
5755 $menu entryconfigure "Diff this*" -state $state
5756 $menu entryconfigure "Diff selected*" -state $state
5757 $menu entryconfigure "Make patch" -state $state
5758 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005759}
5760
5761proc diffvssel {dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005762 global rowmenuid selectedline displayorder
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005763
5764 if {![info exists selectedline]} return
5765 if {$dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005766 set oldid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005767 set newid $rowmenuid
5768 } else {
5769 set oldid $rowmenuid
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005770 set newid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005771 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005772 addtohistory [list doseldiff $oldid $newid]
5773 doseldiff $oldid $newid
5774}
5775
5776proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005777 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005778 global commitinfo
5779
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005780 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005781 clear_ctext
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005782 init_flist "Top"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005783 $ctext insert end "From "
Paul Mackerras97645682007-08-23 22:24:38 +10005784 $ctext insert end $oldid link0
5785 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005786 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005787 $ctext insert end [lindex $commitinfo($oldid) 0]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005788 $ctext insert end "\n\nTo "
Paul Mackerras97645682007-08-23 22:24:38 +10005789 $ctext insert end $newid link1
5790 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005791 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005792 $ctext insert end [lindex $commitinfo($newid) 0]
5793 $ctext insert end "\n"
5794 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005795 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11005796 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005797}
5798
Paul Mackerras74daedb2005-06-27 19:27:32 +10005799proc mkpatch {} {
5800 global rowmenuid currentid commitinfo patchtop patchnum
5801
5802 if {![info exists currentid]} return
5803 set oldid $currentid
5804 set oldhead [lindex $commitinfo($oldid) 0]
5805 set newid $rowmenuid
5806 set newhead [lindex $commitinfo($newid) 0]
5807 set top .patch
5808 set patchtop $top
5809 catch {destroy $top}
5810 toplevel $top
5811 label $top.title -text "Generate patch"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005812 grid $top.title - -pady 10
Paul Mackerras74daedb2005-06-27 19:27:32 +10005813 label $top.from -text "From:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005814 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005815 $top.fromsha1 insert 0 $oldid
5816 $top.fromsha1 conf -state readonly
5817 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005818 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005819 $top.fromhead insert 0 $oldhead
5820 $top.fromhead conf -state readonly
5821 grid x $top.fromhead -sticky w
5822 label $top.to -text "To:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005823 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005824 $top.tosha1 insert 0 $newid
5825 $top.tosha1 conf -state readonly
5826 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005827 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005828 $top.tohead insert 0 $newhead
5829 $top.tohead conf -state readonly
5830 grid x $top.tohead -sticky w
5831 button $top.rev -text "Reverse" -command mkpatchrev -padx 5
5832 grid $top.rev x -pady 10
5833 label $top.flab -text "Output file:"
5834 entry $top.fname -width 60
5835 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
5836 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005837 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10005838 frame $top.buts
5839 button $top.buts.gen -text "Generate" -command mkpatchgo
5840 button $top.buts.can -text "Cancel" -command mkpatchcan
5841 grid $top.buts.gen $top.buts.can
5842 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5843 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5844 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005845 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10005846}
5847
5848proc mkpatchrev {} {
5849 global patchtop
5850
5851 set oldid [$patchtop.fromsha1 get]
5852 set oldhead [$patchtop.fromhead get]
5853 set newid [$patchtop.tosha1 get]
5854 set newhead [$patchtop.tohead get]
5855 foreach e [list fromsha1 fromhead tosha1 tohead] \
5856 v [list $newid $newhead $oldid $oldhead] {
5857 $patchtop.$e conf -state normal
5858 $patchtop.$e delete 0 end
5859 $patchtop.$e insert 0 $v
5860 $patchtop.$e conf -state readonly
5861 }
5862}
5863
5864proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005865 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10005866
5867 set oldid [$patchtop.fromsha1 get]
5868 set newid [$patchtop.tosha1 get]
5869 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10005870 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005871 lappend cmd >$fname &
5872 if {[catch {eval exec $cmd} err]} {
Paul Mackerras74daedb2005-06-27 19:27:32 +10005873 error_popup "Error creating patch: $err"
5874 }
5875 catch {destroy $patchtop}
5876 unset patchtop
5877}
5878
5879proc mkpatchcan {} {
5880 global patchtop
5881
5882 catch {destroy $patchtop}
5883 unset patchtop
5884}
5885
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005886proc mktag {} {
5887 global rowmenuid mktagtop commitinfo
5888
5889 set top .maketag
5890 set mktagtop $top
5891 catch {destroy $top}
5892 toplevel $top
5893 label $top.title -text "Create tag"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005894 grid $top.title - -pady 10
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005895 label $top.id -text "ID:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005896 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005897 $top.sha1 insert 0 $rowmenuid
5898 $top.sha1 conf -state readonly
5899 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005900 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005901 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5902 $top.head conf -state readonly
5903 grid x $top.head -sticky w
5904 label $top.tlab -text "Tag name:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005905 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005906 grid $top.tlab $top.tag -sticky w
5907 frame $top.buts
5908 button $top.buts.gen -text "Create" -command mktaggo
5909 button $top.buts.can -text "Cancel" -command mktagcan
5910 grid $top.buts.gen $top.buts.can
5911 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5912 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5913 grid $top.buts - -pady 10 -sticky ew
5914 focus $top.tag
5915}
5916
5917proc domktag {} {
5918 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005919
5920 set id [$mktagtop.sha1 get]
5921 set tag [$mktagtop.tag get]
5922 if {$tag == {}} {
5923 error_popup "No tag name specified"
5924 return
5925 }
5926 if {[info exists tagids($tag)]} {
5927 error_popup "Tag \"$tag\" already exists"
5928 return
5929 }
5930 if {[catch {
Junio C Hamano73b6a6c2005-07-28 00:28:44 -07005931 set dir [gitdir]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005932 set fname [file join $dir "refs/tags" $tag]
5933 set f [open $fname w]
5934 puts $f $id
5935 close $f
5936 } err]} {
5937 error_popup "Error creating tag: $err"
5938 return
5939 }
5940
5941 set tagids($tag) $id
5942 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005943 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10005944 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10005945 dispneartags 0
5946 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005947}
5948
5949proc redrawtags {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005950 global canv linehtag commitrow idpos selectedline curview
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005951 global mainfont canvxmax iddrawn
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005952
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005953 if {![info exists commitrow($curview,$id)]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005954 if {![info exists iddrawn($id)]} return
5955 drawcommits $commitrow($curview,$id)
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005956 $canv delete tag.$id
5957 set xt [eval drawtags $id $idpos($id)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005958 $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005959 set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text]
5960 set xr [expr {$xt + [font measure $mainfont $text]}]
5961 if {$xr > $canvxmax} {
5962 set canvxmax $xr
5963 setcanvscroll
5964 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005965 if {[info exists selectedline]
5966 && $selectedline == $commitrow($curview,$id)} {
Paul Mackerrasd6982062005-08-06 22:06:06 +10005967 selectline $selectedline 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005968 }
5969}
5970
5971proc mktagcan {} {
5972 global mktagtop
5973
5974 catch {destroy $mktagtop}
5975 unset mktagtop
5976}
5977
5978proc mktaggo {} {
5979 domktag
5980 mktagcan
5981}
5982
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005983proc writecommit {} {
5984 global rowmenuid wrcomtop commitinfo wrcomcmd
5985
5986 set top .writecommit
5987 set wrcomtop $top
5988 catch {destroy $top}
5989 toplevel $top
5990 label $top.title -text "Write commit to file"
5991 grid $top.title - -pady 10
5992 label $top.id -text "ID:"
5993 entry $top.sha1 -width 40 -relief flat
5994 $top.sha1 insert 0 $rowmenuid
5995 $top.sha1 conf -state readonly
5996 grid $top.id $top.sha1 -sticky w
5997 entry $top.head -width 60 -relief flat
5998 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5999 $top.head conf -state readonly
6000 grid x $top.head -sticky w
6001 label $top.clab -text "Command:"
6002 entry $top.cmd -width 60 -textvariable wrcomcmd
6003 grid $top.clab $top.cmd -sticky w -pady 10
6004 label $top.flab -text "Output file:"
6005 entry $top.fname -width 60
6006 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
6007 grid $top.flab $top.fname -sticky w
6008 frame $top.buts
6009 button $top.buts.gen -text "Write" -command wrcomgo
6010 button $top.buts.can -text "Cancel" -command wrcomcan
6011 grid $top.buts.gen $top.buts.can
6012 grid columnconfigure $top.buts 0 -weight 1 -uniform a
6013 grid columnconfigure $top.buts 1 -weight 1 -uniform a
6014 grid $top.buts - -pady 10 -sticky ew
6015 focus $top.fname
6016}
6017
6018proc wrcomgo {} {
6019 global wrcomtop
6020
6021 set id [$wrcomtop.sha1 get]
6022 set cmd "echo $id | [$wrcomtop.cmd get]"
6023 set fname [$wrcomtop.fname get]
6024 if {[catch {exec sh -c $cmd >$fname &} err]} {
6025 error_popup "Error writing commit: $err"
6026 }
6027 catch {destroy $wrcomtop}
6028 unset wrcomtop
6029}
6030
6031proc wrcomcan {} {
6032 global wrcomtop
6033
6034 catch {destroy $wrcomtop}
6035 unset wrcomtop
6036}
6037
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006038proc mkbranch {} {
6039 global rowmenuid mkbrtop
6040
6041 set top .makebranch
6042 catch {destroy $top}
6043 toplevel $top
6044 label $top.title -text "Create new branch"
6045 grid $top.title - -pady 10
6046 label $top.id -text "ID:"
6047 entry $top.sha1 -width 40 -relief flat
6048 $top.sha1 insert 0 $rowmenuid
6049 $top.sha1 conf -state readonly
6050 grid $top.id $top.sha1 -sticky w
6051 label $top.nlab -text "Name:"
6052 entry $top.name -width 40
6053 grid $top.nlab $top.name -sticky w
6054 frame $top.buts
6055 button $top.buts.go -text "Create" -command [list mkbrgo $top]
6056 button $top.buts.can -text "Cancel" -command "catch {destroy $top}"
6057 grid $top.buts.go $top.buts.can
6058 grid columnconfigure $top.buts 0 -weight 1 -uniform a
6059 grid columnconfigure $top.buts 1 -weight 1 -uniform a
6060 grid $top.buts - -pady 10 -sticky ew
6061 focus $top.name
6062}
6063
6064proc mkbrgo {top} {
6065 global headids idheads
6066
6067 set name [$top.name get]
6068 set id [$top.sha1 get]
6069 if {$name eq {}} {
6070 error_popup "Please specify a name for the new branch"
6071 return
6072 }
6073 catch {destroy $top}
6074 nowbusy newbranch
6075 update
6076 if {[catch {
6077 exec git branch $name $id
6078 } err]} {
6079 notbusy newbranch
6080 error_popup $err
6081 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006082 set headids($name) $id
6083 lappend idheads($id) $name
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006084 addedhead $id $name
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006085 notbusy newbranch
6086 redrawtags $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10006087 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10006088 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006089 }
6090}
6091
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006092proc cherrypick {} {
6093 global rowmenuid curview commitrow
Paul Mackerrase11f1232007-06-16 20:29:25 +10006094 global mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006095
Paul Mackerrase11f1232007-06-16 20:29:25 +10006096 set oldhead [exec git rev-parse HEAD]
6097 set dheads [descheads $rowmenuid]
6098 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006099 set ok [confirm_popup "Commit [string range $rowmenuid 0 7] is already\
6100 included in branch $mainhead -- really re-apply it?"]
6101 if {!$ok} return
6102 }
6103 nowbusy cherrypick
6104 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006105 # Unfortunately git-cherry-pick writes stuff to stderr even when
6106 # no error occurs, and exec takes that as an indication of error...
6107 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
6108 notbusy cherrypick
6109 error_popup $err
6110 return
6111 }
6112 set newhead [exec git rev-parse HEAD]
6113 if {$newhead eq $oldhead} {
6114 notbusy cherrypick
6115 error_popup "No changes committed"
6116 return
6117 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006118 addnewchild $newhead $oldhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006119 if {[info exists commitrow($curview,$oldhead)]} {
6120 insertrow $commitrow($curview,$oldhead) $newhead
6121 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006122 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006123 movedhead $newhead $mainhead
6124 }
6125 redrawtags $oldhead
6126 redrawtags $newhead
6127 }
6128 notbusy cherrypick
6129}
6130
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006131proc resethead {} {
6132 global mainheadid mainhead rowmenuid confirm_ok resettype
6133 global showlocalchanges
6134
6135 set confirm_ok 0
6136 set w ".confirmreset"
6137 toplevel $w
6138 wm transient $w .
6139 wm title $w "Confirm reset"
6140 message $w.m -text \
6141 "Reset branch $mainhead to [string range $rowmenuid 0 7]?" \
6142 -justify center -aspect 1000
6143 pack $w.m -side top -fill x -padx 20 -pady 20
6144 frame $w.f -relief sunken -border 2
6145 message $w.f.rt -text "Reset type:" -aspect 1000
6146 grid $w.f.rt -sticky w
6147 set resettype mixed
6148 radiobutton $w.f.soft -value soft -variable resettype -justify left \
6149 -text "Soft: Leave working tree and index untouched"
6150 grid $w.f.soft -sticky w
6151 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
6152 -text "Mixed: Leave working tree untouched, reset index"
6153 grid $w.f.mixed -sticky w
6154 radiobutton $w.f.hard -value hard -variable resettype -justify left \
6155 -text "Hard: Reset working tree and index\n(discard ALL local changes)"
6156 grid $w.f.hard -sticky w
6157 pack $w.f -side top -fill x
6158 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
6159 pack $w.ok -side left -fill x -padx 20 -pady 20
6160 button $w.cancel -text Cancel -command "destroy $w"
6161 pack $w.cancel -side right -fill x -padx 20 -pady 20
6162 bind $w <Visibility> "grab $w; focus $w"
6163 tkwait window $w
6164 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10006165 if {[catch {set fd [open \
6166 [list | sh -c "git reset --$resettype $rowmenuid 2>&1"] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006167 error_popup $err
6168 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10006169 dohidelocalchanges
6170 set w ".resetprogress"
6171 filerun $fd [list readresetstat $fd $w]
6172 toplevel $w
6173 wm transient $w
6174 wm title $w "Reset progress"
6175 message $w.m -text "Reset in progress, please wait..." \
6176 -justify center -aspect 1000
6177 pack $w.m -side top -fill x -padx 20 -pady 5
6178 canvas $w.c -width 150 -height 20 -bg white
6179 $w.c create rect 0 0 0 20 -fill green -tags rect
6180 pack $w.c -side top -fill x -padx 20 -pady 5 -expand 1
6181 nowbusy reset
6182 }
6183}
6184
6185proc readresetstat {fd w} {
6186 global mainhead mainheadid showlocalchanges
6187
6188 if {[gets $fd line] >= 0} {
6189 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
6190 set x [expr {($m * 150) / $n}]
6191 $w.c coords rect 0 0 $x 20
6192 }
6193 return 1
6194 }
6195 destroy $w
6196 notbusy reset
6197 if {[catch {close $fd} err]} {
6198 error_popup $err
6199 }
6200 set oldhead $mainheadid
6201 set newhead [exec git rev-parse HEAD]
6202 if {$newhead ne $oldhead} {
6203 movehead $newhead $mainhead
6204 movedhead $newhead $mainhead
6205 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006206 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10006207 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006208 }
6209 if {$showlocalchanges} {
6210 doshowlocalchanges
6211 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10006212 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006213}
6214
Paul Mackerras10299152006-08-02 09:52:01 +10006215# context menu for a head
6216proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10006217 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10006218
6219 set headmenuid $id
6220 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10006221 set state normal
6222 if {$head eq $mainhead} {
6223 set state disabled
6224 }
6225 $headctxmenu entryconfigure 0 -state $state
6226 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10006227 tk_popup $headctxmenu $x $y
6228}
6229
6230proc cobranch {} {
6231 global headmenuid headmenuhead mainhead headids
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006232 global showlocalchanges mainheadid
Paul Mackerras10299152006-08-02 09:52:01 +10006233
6234 # check the tree is clean first??
6235 set oldmainhead $mainhead
6236 nowbusy checkout
6237 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006238 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10006239 if {[catch {
Paul Mackerras696cf492007-05-22 09:52:00 +10006240 exec git checkout -q $headmenuhead
Paul Mackerras10299152006-08-02 09:52:01 +10006241 } err]} {
6242 notbusy checkout
6243 error_popup $err
6244 } else {
6245 notbusy checkout
Paul Mackerras53cda8d2006-08-02 19:43:34 +10006246 set mainhead $headmenuhead
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006247 set mainheadid $headmenuid
Paul Mackerras10299152006-08-02 09:52:01 +10006248 if {[info exists headids($oldmainhead)]} {
6249 redrawtags $headids($oldmainhead)
6250 }
6251 redrawtags $headmenuid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006252 }
6253 if {$showlocalchanges} {
6254 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10006255 }
6256}
6257
6258proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006259 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10006260 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10006261
6262 set head $headmenuhead
6263 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10006264 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10006265 if {$head eq $mainhead} {
6266 error_popup "Cannot delete the currently checked-out branch"
6267 return
6268 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006269 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10006270 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10006271 # the stuff on this branch isn't on any other branch
6272 if {![confirm_popup "The commits on branch $head aren't on any other\
6273 branch.\nReally delete branch $head?"]} return
6274 }
6275 nowbusy rmbranch
6276 update
6277 if {[catch {exec git branch -D $head} err]} {
6278 notbusy rmbranch
6279 error_popup $err
6280 return
6281 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006282 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006283 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10006284 redrawtags $id
6285 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10006286 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10006287 run refill_reflist
6288}
6289
6290# Display a list of tags and heads
6291proc showrefs {} {
6292 global showrefstop bgcolor fgcolor selectbgcolor mainfont
6293 global bglist fglist uifont reflistfilter reflist maincursor
6294
6295 set top .showrefs
6296 set showrefstop $top
6297 if {[winfo exists $top]} {
6298 raise $top
6299 refill_reflist
6300 return
6301 }
6302 toplevel $top
6303 wm title $top "Tags and heads: [file tail [pwd]]"
6304 text $top.list -background $bgcolor -foreground $fgcolor \
6305 -selectbackground $selectbgcolor -font $mainfont \
6306 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
6307 -width 30 -height 20 -cursor $maincursor \
6308 -spacing1 1 -spacing3 1 -state disabled
6309 $top.list tag configure highlight -background $selectbgcolor
6310 lappend bglist $top.list
6311 lappend fglist $top.list
6312 scrollbar $top.ysb -command "$top.list yview" -orient vertical
6313 scrollbar $top.xsb -command "$top.list xview" -orient horizontal
6314 grid $top.list $top.ysb -sticky nsew
6315 grid $top.xsb x -sticky ew
6316 frame $top.f
6317 label $top.f.l -text "Filter: " -font $uifont
6318 entry $top.f.e -width 20 -textvariable reflistfilter -font $uifont
6319 set reflistfilter "*"
6320 trace add variable reflistfilter write reflistfilter_change
6321 pack $top.f.e -side right -fill x -expand 1
6322 pack $top.f.l -side left
6323 grid $top.f - -sticky ew -pady 2
6324 button $top.close -command [list destroy $top] -text "Close" \
6325 -font $uifont
6326 grid $top.close -
6327 grid columnconfigure $top 0 -weight 1
6328 grid rowconfigure $top 0 -weight 1
6329 bind $top.list <1> {break}
6330 bind $top.list <B1-Motion> {break}
6331 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
6332 set reflist {}
6333 refill_reflist
6334}
6335
6336proc sel_reflist {w x y} {
6337 global showrefstop reflist headids tagids otherrefids
6338
6339 if {![winfo exists $showrefstop]} return
6340 set l [lindex [split [$w index "@$x,$y"] "."] 0]
6341 set ref [lindex $reflist [expr {$l-1}]]
6342 set n [lindex $ref 0]
6343 switch -- [lindex $ref 1] {
6344 "H" {selbyid $headids($n)}
6345 "T" {selbyid $tagids($n)}
6346 "o" {selbyid $otherrefids($n)}
6347 }
6348 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
6349}
6350
6351proc unsel_reflist {} {
6352 global showrefstop
6353
6354 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
6355 $showrefstop.list tag remove highlight 0.0 end
6356}
6357
6358proc reflistfilter_change {n1 n2 op} {
6359 global reflistfilter
6360
6361 after cancel refill_reflist
6362 after 200 refill_reflist
6363}
6364
6365proc refill_reflist {} {
6366 global reflist reflistfilter showrefstop headids tagids otherrefids
6367 global commitrow curview commitinterest
6368
6369 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
6370 set refs {}
6371 foreach n [array names headids] {
6372 if {[string match $reflistfilter $n]} {
6373 if {[info exists commitrow($curview,$headids($n))]} {
6374 lappend refs [list $n H]
6375 } else {
6376 set commitinterest($headids($n)) {run refill_reflist}
6377 }
6378 }
6379 }
6380 foreach n [array names tagids] {
6381 if {[string match $reflistfilter $n]} {
6382 if {[info exists commitrow($curview,$tagids($n))]} {
6383 lappend refs [list $n T]
6384 } else {
6385 set commitinterest($tagids($n)) {run refill_reflist}
6386 }
6387 }
6388 }
6389 foreach n [array names otherrefids] {
6390 if {[string match $reflistfilter $n]} {
6391 if {[info exists commitrow($curview,$otherrefids($n))]} {
6392 lappend refs [list $n o]
6393 } else {
6394 set commitinterest($otherrefids($n)) {run refill_reflist}
6395 }
6396 }
6397 }
6398 set refs [lsort -index 0 $refs]
6399 if {$refs eq $reflist} return
6400
6401 # Update the contents of $showrefstop.list according to the
6402 # differences between $reflist (old) and $refs (new)
6403 $showrefstop.list conf -state normal
6404 $showrefstop.list insert end "\n"
6405 set i 0
6406 set j 0
6407 while {$i < [llength $reflist] || $j < [llength $refs]} {
6408 if {$i < [llength $reflist]} {
6409 if {$j < [llength $refs]} {
6410 set cmp [string compare [lindex $reflist $i 0] \
6411 [lindex $refs $j 0]]
6412 if {$cmp == 0} {
6413 set cmp [string compare [lindex $reflist $i 1] \
6414 [lindex $refs $j 1]]
6415 }
6416 } else {
6417 set cmp -1
6418 }
6419 } else {
6420 set cmp 1
6421 }
6422 switch -- $cmp {
6423 -1 {
6424 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
6425 incr i
6426 }
6427 0 {
6428 incr i
6429 incr j
6430 }
6431 1 {
6432 set l [expr {$j + 1}]
6433 $showrefstop.list image create $l.0 -align baseline \
6434 -image reficon-[lindex $refs $j 1] -padx 2
6435 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
6436 incr j
6437 }
6438 }
6439 }
6440 set reflist $refs
6441 # delete last newline
6442 $showrefstop.list delete end-2c end-1c
6443 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10006444}
6445
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006446# Stuff for finding nearby tags
6447proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006448 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
6449 global idheads idtags idotherrefs allparents tagobjid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006450
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10006451 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10006452 set nextarc 0
6453 set allcommits 0
6454 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006455 set allcwait 0
6456 set cachedarcs 0
6457 set allccache [file join [gitdir] "gitk.cache"]
6458 if {![catch {
6459 set f [open $allccache r]
6460 set allcwait 1
6461 getcache $f
6462 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10006463 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006464
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006465 if {$allcwait} {
6466 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006467 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006468 set cmd [list | git rev-list --parents]
6469 set allcupdate [expr {$seeds ne {}}]
6470 if {!$allcupdate} {
6471 set ids "--all"
6472 } else {
6473 set refs [concat [array names idheads] [array names idtags] \
6474 [array names idotherrefs]]
6475 set ids {}
6476 set tagobjs {}
6477 foreach name [array names tagobjid] {
6478 lappend tagobjs $tagobjid($name)
6479 }
6480 foreach id [lsort -unique $refs] {
6481 if {![info exists allparents($id)] &&
6482 [lsearch -exact $tagobjs $id] < 0} {
6483 lappend ids $id
6484 }
6485 }
6486 if {$ids ne {}} {
6487 foreach id $seeds {
6488 lappend ids "^$id"
6489 }
6490 }
6491 }
6492 if {$ids ne {}} {
6493 set fd [open [concat $cmd $ids] r]
6494 fconfigure $fd -blocking 0
6495 incr allcommits
6496 nowbusy allcommits
6497 filerun $fd [list getallclines $fd]
6498 } else {
6499 dispneartags 0
6500 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006501}
6502
Paul Mackerrase11f1232007-06-16 20:29:25 +10006503# Since most commits have 1 parent and 1 child, we group strings of
6504# such commits into "arcs" joining branch/merge points (BMPs), which
6505# are commits that either don't have 1 parent or don't have 1 child.
6506#
6507# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
6508# arcout(id) - outgoing arcs for BMP
6509# arcids(a) - list of IDs on arc including end but not start
6510# arcstart(a) - BMP ID at start of arc
6511# arcend(a) - BMP ID at end of arc
6512# growing(a) - arc a is still growing
6513# arctags(a) - IDs out of arcids (excluding end) that have tags
6514# archeads(a) - IDs out of arcids (excluding end) that have heads
6515# The start of an arc is at the descendent end, so "incoming" means
6516# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006517
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006518proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006519 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10006520 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006521 global seeds allcommits cachedarcs allcupdate
6522
Paul Mackerrase11f1232007-06-16 20:29:25 +10006523 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006524 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006525 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10006526 if {[info exists allparents($id)]} {
6527 # seen it already
6528 continue
6529 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006530 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006531 set olds [lrange $line 1 end]
6532 set allparents($id) $olds
6533 if {![info exists allchildren($id)]} {
6534 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10006535 set arcnos($id) {}
6536 lappend seeds $id
6537 } else {
6538 set a $arcnos($id)
6539 if {[llength $olds] == 1 && [llength $a] == 1} {
6540 lappend arcids($a) $id
6541 if {[info exists idtags($id)]} {
6542 lappend arctags($a) $id
6543 }
6544 if {[info exists idheads($id)]} {
6545 lappend archeads($a) $id
6546 }
6547 if {[info exists allparents($olds)]} {
6548 # seen parent already
6549 if {![info exists arcout($olds)]} {
6550 splitarc $olds
6551 }
6552 lappend arcids($a) $olds
6553 set arcend($a) $olds
6554 unset growing($a)
6555 }
6556 lappend allchildren($olds) $id
6557 lappend arcnos($olds) $a
6558 continue
6559 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006560 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006561 foreach a $arcnos($id) {
6562 lappend arcids($a) $id
6563 set arcend($a) $id
6564 unset growing($a)
6565 }
6566
6567 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006568 foreach p $olds {
6569 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10006570 set a [incr nextarc]
6571 set arcstart($a) $id
6572 set archeads($a) {}
6573 set arctags($a) {}
6574 set archeads($a) {}
6575 set arcids($a) {}
6576 lappend ao $a
6577 set growing($a) 1
6578 if {[info exists allparents($p)]} {
6579 # seen it already, may need to make a new branch
6580 if {![info exists arcout($p)]} {
6581 splitarc $p
6582 }
6583 lappend arcids($a) $p
6584 set arcend($a) $p
6585 unset growing($a)
6586 }
6587 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006588 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006589 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006590 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10006591 if {$nid > 0} {
6592 global cached_dheads cached_dtags cached_atags
6593 catch {unset cached_dheads}
6594 catch {unset cached_dtags}
6595 catch {unset cached_atags}
6596 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006597 if {![eof $fd]} {
6598 return [expr {$nid >= 1000? 2: 1}]
6599 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006600 set cacheok 1
6601 if {[catch {
6602 fconfigure $fd -blocking 1
6603 close $fd
6604 } err]} {
6605 # got an error reading the list of commits
6606 # if we were updating, try rereading the whole thing again
6607 if {$allcupdate} {
6608 incr allcommits -1
6609 dropcache $err
6610 return
6611 }
6612 error_popup "Error reading commit topology information;\
6613 branch and preceding/following tag information\
6614 will be incomplete.\n($err)"
6615 set cacheok 0
6616 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006617 if {[incr allcommits -1] == 0} {
6618 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006619 if {$cacheok} {
6620 run savecache
6621 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006622 }
6623 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006624 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006625}
6626
6627proc recalcarc {a} {
6628 global arctags archeads arcids idtags idheads
6629
6630 set at {}
6631 set ah {}
6632 foreach id [lrange $arcids($a) 0 end-1] {
6633 if {[info exists idtags($id)]} {
6634 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006635 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006636 if {[info exists idheads($id)]} {
6637 lappend ah $id
6638 }
6639 }
6640 set arctags($a) $at
6641 set archeads($a) $ah
6642}
6643
6644proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006645 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +10006646 global arcstart arcend arcout allparents growing
6647
6648 set a $arcnos($p)
6649 if {[llength $a] != 1} {
6650 puts "oops splitarc called but [llength $a] arcs already"
6651 return
6652 }
6653 set a [lindex $a 0]
6654 set i [lsearch -exact $arcids($a) $p]
6655 if {$i < 0} {
6656 puts "oops splitarc $p not in arc $a"
6657 return
6658 }
6659 set na [incr nextarc]
6660 if {[info exists arcend($a)]} {
6661 set arcend($na) $arcend($a)
6662 } else {
6663 set l [lindex $allparents([lindex $arcids($a) end]) 0]
6664 set j [lsearch -exact $arcnos($l) $a]
6665 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
6666 }
6667 set tail [lrange $arcids($a) [expr {$i+1}] end]
6668 set arcids($a) [lrange $arcids($a) 0 $i]
6669 set arcend($a) $p
6670 set arcstart($na) $p
6671 set arcout($p) $na
6672 set arcids($na) $tail
6673 if {[info exists growing($a)]} {
6674 set growing($na) 1
6675 unset growing($a)
6676 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006677
6678 foreach id $tail {
6679 if {[llength $arcnos($id)] == 1} {
6680 set arcnos($id) $na
6681 } else {
6682 set j [lsearch -exact $arcnos($id) $a]
6683 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
6684 }
6685 }
6686
6687 # reconstruct tags and heads lists
6688 if {$arctags($a) ne {} || $archeads($a) ne {}} {
6689 recalcarc $a
6690 recalcarc $na
6691 } else {
6692 set arctags($na) {}
6693 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006694 }
6695}
6696
Paul Mackerrase11f1232007-06-16 20:29:25 +10006697# Update things for a new commit added that is a child of one
6698# existing commit. Used when cherry-picking.
6699proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006700 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10006701 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras6eaaccd2007-08-29 22:41:34 +10006702 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006703
Paul Mackerras6eaaccd2007-08-29 22:41:34 +10006704 if {![info exists allcommits]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006705 set allparents($id) [list $p]
6706 set allchildren($id) {}
6707 set arcnos($id) {}
6708 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10006709 lappend allchildren($p) $id
6710 set a [incr nextarc]
6711 set arcstart($a) $id
6712 set archeads($a) {}
6713 set arctags($a) {}
6714 set arcids($a) [list $p]
6715 set arcend($a) $p
6716 if {![info exists arcout($p)]} {
6717 splitarc $p
6718 }
6719 lappend arcnos($p) $a
6720 set arcout($id) [list $a]
6721}
6722
Paul Mackerras5cd15b62007-08-30 21:54:17 +10006723# This implements a cache for the topology information.
6724# The cache saves, for each arc, the start and end of the arc,
6725# the ids on the arc, and the outgoing arcs from the end.
6726proc readcache {f} {
6727 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
6728 global idtags idheads allparents cachedarcs possible_seeds seeds growing
6729 global allcwait
6730
6731 set a $nextarc
6732 set lim $cachedarcs
6733 if {$lim - $a > 500} {
6734 set lim [expr {$a + 500}]
6735 }
6736 if {[catch {
6737 if {$a == $lim} {
6738 # finish reading the cache and setting up arctags, etc.
6739 set line [gets $f]
6740 if {$line ne "1"} {error "bad final version"}
6741 close $f
6742 foreach id [array names idtags] {
6743 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
6744 [llength $allparents($id)] == 1} {
6745 set a [lindex $arcnos($id) 0]
6746 if {$arctags($a) eq {}} {
6747 recalcarc $a
6748 }
6749 }
6750 }
6751 foreach id [array names idheads] {
6752 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
6753 [llength $allparents($id)] == 1} {
6754 set a [lindex $arcnos($id) 0]
6755 if {$archeads($a) eq {}} {
6756 recalcarc $a
6757 }
6758 }
6759 }
6760 foreach id [lsort -unique $possible_seeds] {
6761 if {$arcnos($id) eq {}} {
6762 lappend seeds $id
6763 }
6764 }
6765 set allcwait 0
6766 } else {
6767 while {[incr a] <= $lim} {
6768 set line [gets $f]
6769 if {[llength $line] != 3} {error "bad line"}
6770 set s [lindex $line 0]
6771 set arcstart($a) $s
6772 lappend arcout($s) $a
6773 if {![info exists arcnos($s)]} {
6774 lappend possible_seeds $s
6775 set arcnos($s) {}
6776 }
6777 set e [lindex $line 1]
6778 if {$e eq {}} {
6779 set growing($a) 1
6780 } else {
6781 set arcend($a) $e
6782 if {![info exists arcout($e)]} {
6783 set arcout($e) {}
6784 }
6785 }
6786 set arcids($a) [lindex $line 2]
6787 foreach id $arcids($a) {
6788 lappend allparents($s) $id
6789 set s $id
6790 lappend arcnos($id) $a
6791 }
6792 if {![info exists allparents($s)]} {
6793 set allparents($s) {}
6794 }
6795 set arctags($a) {}
6796 set archeads($a) {}
6797 }
6798 set nextarc [expr {$a - 1}]
6799 }
6800 } err]} {
6801 dropcache $err
6802 return 0
6803 }
6804 if {!$allcwait} {
6805 getallcommits
6806 }
6807 return $allcwait
6808}
6809
6810proc getcache {f} {
6811 global nextarc cachedarcs possible_seeds
6812
6813 if {[catch {
6814 set line [gets $f]
6815 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
6816 # make sure it's an integer
6817 set cachedarcs [expr {int([lindex $line 1])}]
6818 if {$cachedarcs < 0} {error "bad number of arcs"}
6819 set nextarc 0
6820 set possible_seeds {}
6821 run readcache $f
6822 } err]} {
6823 dropcache $err
6824 }
6825 return 0
6826}
6827
6828proc dropcache {err} {
6829 global allcwait nextarc cachedarcs seeds
6830
6831 #puts "dropping cache ($err)"
6832 foreach v {arcnos arcout arcids arcstart arcend growing \
6833 arctags archeads allparents allchildren} {
6834 global $v
6835 catch {unset $v}
6836 }
6837 set allcwait 0
6838 set nextarc 0
6839 set cachedarcs 0
6840 set seeds {}
6841 getallcommits
6842}
6843
6844proc writecache {f} {
6845 global cachearc cachedarcs allccache
6846 global arcstart arcend arcnos arcids arcout
6847
6848 set a $cachearc
6849 set lim $cachedarcs
6850 if {$lim - $a > 1000} {
6851 set lim [expr {$a + 1000}]
6852 }
6853 if {[catch {
6854 while {[incr a] <= $lim} {
6855 if {[info exists arcend($a)]} {
6856 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
6857 } else {
6858 puts $f [list $arcstart($a) {} $arcids($a)]
6859 }
6860 }
6861 } err]} {
6862 catch {close $f}
6863 catch {file delete $allccache}
6864 #puts "writing cache failed ($err)"
6865 return 0
6866 }
6867 set cachearc [expr {$a - 1}]
6868 if {$a > $cachedarcs} {
6869 puts $f "1"
6870 close $f
6871 return 0
6872 }
6873 return 1
6874}
6875
6876proc savecache {} {
6877 global nextarc cachedarcs cachearc allccache
6878
6879 if {$nextarc == $cachedarcs} return
6880 set cachearc 0
6881 set cachedarcs $nextarc
6882 catch {
6883 set f [open $allccache w]
6884 puts $f [list 1 $cachedarcs]
6885 run writecache $f
6886 }
6887}
6888
Paul Mackerrase11f1232007-06-16 20:29:25 +10006889# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
6890# or 0 if neither is true.
6891proc anc_or_desc {a b} {
6892 global arcout arcstart arcend arcnos cached_isanc
6893
6894 if {$arcnos($a) eq $arcnos($b)} {
6895 # Both are on the same arc(s); either both are the same BMP,
6896 # or if one is not a BMP, the other is also not a BMP or is
6897 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +10006898 # Or both can be BMPs with no incoming arcs.
6899 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006900 return 0
6901 }
6902 # assert {[llength $arcnos($a)] == 1}
6903 set arc [lindex $arcnos($a) 0]
6904 set i [lsearch -exact $arcids($arc) $a]
6905 set j [lsearch -exact $arcids($arc) $b]
6906 if {$i < 0 || $i > $j} {
6907 return 1
6908 } else {
6909 return -1
6910 }
6911 }
6912
6913 if {![info exists arcout($a)]} {
6914 set arc [lindex $arcnos($a) 0]
6915 if {[info exists arcend($arc)]} {
6916 set aend $arcend($arc)
6917 } else {
6918 set aend {}
6919 }
6920 set a $arcstart($arc)
6921 } else {
6922 set aend $a
6923 }
6924 if {![info exists arcout($b)]} {
6925 set arc [lindex $arcnos($b) 0]
6926 if {[info exists arcend($arc)]} {
6927 set bend $arcend($arc)
6928 } else {
6929 set bend {}
6930 }
6931 set b $arcstart($arc)
6932 } else {
6933 set bend $b
6934 }
6935 if {$a eq $bend} {
6936 return 1
6937 }
6938 if {$b eq $aend} {
6939 return -1
6940 }
6941 if {[info exists cached_isanc($a,$bend)]} {
6942 if {$cached_isanc($a,$bend)} {
6943 return 1
6944 }
6945 }
6946 if {[info exists cached_isanc($b,$aend)]} {
6947 if {$cached_isanc($b,$aend)} {
6948 return -1
6949 }
6950 if {[info exists cached_isanc($a,$bend)]} {
6951 return 0
6952 }
6953 }
6954
6955 set todo [list $a $b]
6956 set anc($a) a
6957 set anc($b) b
6958 for {set i 0} {$i < [llength $todo]} {incr i} {
6959 set x [lindex $todo $i]
6960 if {$anc($x) eq {}} {
6961 continue
6962 }
6963 foreach arc $arcnos($x) {
6964 set xd $arcstart($arc)
6965 if {$xd eq $bend} {
6966 set cached_isanc($a,$bend) 1
6967 set cached_isanc($b,$aend) 0
6968 return 1
6969 } elseif {$xd eq $aend} {
6970 set cached_isanc($b,$aend) 1
6971 set cached_isanc($a,$bend) 0
6972 return -1
6973 }
6974 if {![info exists anc($xd)]} {
6975 set anc($xd) $anc($x)
6976 lappend todo $xd
6977 } elseif {$anc($xd) ne $anc($x)} {
6978 set anc($xd) {}
6979 }
6980 }
6981 }
6982 set cached_isanc($a,$bend) 0
6983 set cached_isanc($b,$aend) 0
6984 return 0
6985}
6986
6987# This identifies whether $desc has an ancestor that is
6988# a growing tip of the graph and which is not an ancestor of $anc
6989# and returns 0 if so and 1 if not.
6990# If we subsequently discover a tag on such a growing tip, and that
6991# turns out to be a descendent of $anc (which it could, since we
6992# don't necessarily see children before parents), then $desc
6993# isn't a good choice to display as a descendent tag of
6994# $anc (since it is the descendent of another tag which is
6995# a descendent of $anc). Similarly, $anc isn't a good choice to
6996# display as a ancestor tag of $desc.
6997#
6998proc is_certain {desc anc} {
6999 global arcnos arcout arcstart arcend growing problems
7000
7001 set certain {}
7002 if {[llength $arcnos($anc)] == 1} {
7003 # tags on the same arc are certain
7004 if {$arcnos($desc) eq $arcnos($anc)} {
7005 return 1
7006 }
7007 if {![info exists arcout($anc)]} {
7008 # if $anc is partway along an arc, use the start of the arc instead
7009 set a [lindex $arcnos($anc) 0]
7010 set anc $arcstart($a)
7011 }
7012 }
7013 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
7014 set x $desc
7015 } else {
7016 set a [lindex $arcnos($desc) 0]
7017 set x $arcend($a)
7018 }
7019 if {$x == $anc} {
7020 return 1
7021 }
7022 set anclist [list $x]
7023 set dl($x) 1
7024 set nnh 1
7025 set ngrowanc 0
7026 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
7027 set x [lindex $anclist $i]
7028 if {$dl($x)} {
7029 incr nnh -1
7030 }
7031 set done($x) 1
7032 foreach a $arcout($x) {
7033 if {[info exists growing($a)]} {
7034 if {![info exists growanc($x)] && $dl($x)} {
7035 set growanc($x) 1
7036 incr ngrowanc
7037 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007038 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007039 set y $arcend($a)
7040 if {[info exists dl($y)]} {
7041 if {$dl($y)} {
7042 if {!$dl($x)} {
7043 set dl($y) 0
7044 if {![info exists done($y)]} {
7045 incr nnh -1
7046 }
7047 if {[info exists growanc($x)]} {
7048 incr ngrowanc -1
7049 }
7050 set xl [list $y]
7051 for {set k 0} {$k < [llength $xl]} {incr k} {
7052 set z [lindex $xl $k]
7053 foreach c $arcout($z) {
7054 if {[info exists arcend($c)]} {
7055 set v $arcend($c)
7056 if {[info exists dl($v)] && $dl($v)} {
7057 set dl($v) 0
7058 if {![info exists done($v)]} {
7059 incr nnh -1
7060 }
7061 if {[info exists growanc($v)]} {
7062 incr ngrowanc -1
7063 }
7064 lappend xl $v
7065 }
7066 }
7067 }
7068 }
7069 }
7070 }
7071 } elseif {$y eq $anc || !$dl($x)} {
7072 set dl($y) 0
7073 lappend anclist $y
7074 } else {
7075 set dl($y) 1
7076 lappend anclist $y
7077 incr nnh
7078 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007079 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007080 }
7081 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007082 foreach x [array names growanc] {
7083 if {$dl($x)} {
7084 return 0
7085 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007086 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10007087 }
7088 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007089}
7090
Paul Mackerrase11f1232007-06-16 20:29:25 +10007091proc validate_arctags {a} {
7092 global arctags idtags
7093
7094 set i -1
7095 set na $arctags($a)
7096 foreach id $arctags($a) {
7097 incr i
7098 if {![info exists idtags($id)]} {
7099 set na [lreplace $na $i $i]
7100 incr i -1
7101 }
7102 }
7103 set arctags($a) $na
7104}
7105
7106proc validate_archeads {a} {
7107 global archeads idheads
7108
7109 set i -1
7110 set na $archeads($a)
7111 foreach id $archeads($a) {
7112 incr i
7113 if {![info exists idheads($id)]} {
7114 set na [lreplace $na $i $i]
7115 incr i -1
7116 }
7117 }
7118 set archeads($a) $na
7119}
7120
7121# Return the list of IDs that have tags that are descendents of id,
7122# ignoring IDs that are descendents of IDs already reported.
7123proc desctags {id} {
7124 global arcnos arcstart arcids arctags idtags allparents
7125 global growing cached_dtags
7126
7127 if {![info exists allparents($id)]} {
7128 return {}
7129 }
7130 set t1 [clock clicks -milliseconds]
7131 set argid $id
7132 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
7133 # part-way along an arc; check that arc first
7134 set a [lindex $arcnos($id) 0]
7135 if {$arctags($a) ne {}} {
7136 validate_arctags $a
7137 set i [lsearch -exact $arcids($a) $id]
7138 set tid {}
7139 foreach t $arctags($a) {
7140 set j [lsearch -exact $arcids($a) $t]
7141 if {$j >= $i} break
7142 set tid $t
7143 }
7144 if {$tid ne {}} {
7145 return $tid
7146 }
7147 }
7148 set id $arcstart($a)
7149 if {[info exists idtags($id)]} {
7150 return $id
7151 }
7152 }
7153 if {[info exists cached_dtags($id)]} {
7154 return $cached_dtags($id)
7155 }
7156
7157 set origid $id
7158 set todo [list $id]
7159 set queued($id) 1
7160 set nc 1
7161 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
7162 set id [lindex $todo $i]
7163 set done($id) 1
7164 set ta [info exists hastaggedancestor($id)]
7165 if {!$ta} {
7166 incr nc -1
7167 }
7168 # ignore tags on starting node
7169 if {!$ta && $i > 0} {
7170 if {[info exists idtags($id)]} {
7171 set tagloc($id) $id
7172 set ta 1
7173 } elseif {[info exists cached_dtags($id)]} {
7174 set tagloc($id) $cached_dtags($id)
7175 set ta 1
7176 }
7177 }
7178 foreach a $arcnos($id) {
7179 set d $arcstart($a)
7180 if {!$ta && $arctags($a) ne {}} {
7181 validate_arctags $a
7182 if {$arctags($a) ne {}} {
7183 lappend tagloc($id) [lindex $arctags($a) end]
7184 }
7185 }
7186 if {$ta || $arctags($a) ne {}} {
7187 set tomark [list $d]
7188 for {set j 0} {$j < [llength $tomark]} {incr j} {
7189 set dd [lindex $tomark $j]
7190 if {![info exists hastaggedancestor($dd)]} {
7191 if {[info exists done($dd)]} {
7192 foreach b $arcnos($dd) {
7193 lappend tomark $arcstart($b)
7194 }
7195 if {[info exists tagloc($dd)]} {
7196 unset tagloc($dd)
7197 }
7198 } elseif {[info exists queued($dd)]} {
7199 incr nc -1
7200 }
7201 set hastaggedancestor($dd) 1
7202 }
7203 }
7204 }
7205 if {![info exists queued($d)]} {
7206 lappend todo $d
7207 set queued($d) 1
7208 if {![info exists hastaggedancestor($d)]} {
7209 incr nc
7210 }
7211 }
7212 }
7213 }
7214 set tags {}
7215 foreach id [array names tagloc] {
7216 if {![info exists hastaggedancestor($id)]} {
7217 foreach t $tagloc($id) {
7218 if {[lsearch -exact $tags $t] < 0} {
7219 lappend tags $t
7220 }
7221 }
7222 }
7223 }
7224 set t2 [clock clicks -milliseconds]
7225 set loopix $i
7226
7227 # remove tags that are descendents of other tags
7228 for {set i 0} {$i < [llength $tags]} {incr i} {
7229 set a [lindex $tags $i]
7230 for {set j 0} {$j < $i} {incr j} {
7231 set b [lindex $tags $j]
7232 set r [anc_or_desc $a $b]
7233 if {$r == 1} {
7234 set tags [lreplace $tags $j $j]
7235 incr j -1
7236 incr i -1
7237 } elseif {$r == -1} {
7238 set tags [lreplace $tags $i $i]
7239 incr i -1
7240 break
7241 }
7242 }
7243 }
7244
7245 if {[array names growing] ne {}} {
7246 # graph isn't finished, need to check if any tag could get
7247 # eclipsed by another tag coming later. Simply ignore any
7248 # tags that could later get eclipsed.
7249 set ctags {}
7250 foreach t $tags {
7251 if {[is_certain $t $origid]} {
7252 lappend ctags $t
7253 }
7254 }
7255 if {$tags eq $ctags} {
7256 set cached_dtags($origid) $tags
7257 } else {
7258 set tags $ctags
7259 }
7260 } else {
7261 set cached_dtags($origid) $tags
7262 }
7263 set t3 [clock clicks -milliseconds]
7264 if {0 && $t3 - $t1 >= 100} {
7265 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
7266 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
7267 }
7268 return $tags
7269}
7270
7271proc anctags {id} {
7272 global arcnos arcids arcout arcend arctags idtags allparents
7273 global growing cached_atags
7274
7275 if {![info exists allparents($id)]} {
7276 return {}
7277 }
7278 set t1 [clock clicks -milliseconds]
7279 set argid $id
7280 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
7281 # part-way along an arc; check that arc first
7282 set a [lindex $arcnos($id) 0]
7283 if {$arctags($a) ne {}} {
7284 validate_arctags $a
7285 set i [lsearch -exact $arcids($a) $id]
7286 foreach t $arctags($a) {
7287 set j [lsearch -exact $arcids($a) $t]
7288 if {$j > $i} {
7289 return $t
7290 }
7291 }
7292 }
7293 if {![info exists arcend($a)]} {
7294 return {}
7295 }
7296 set id $arcend($a)
7297 if {[info exists idtags($id)]} {
7298 return $id
7299 }
7300 }
7301 if {[info exists cached_atags($id)]} {
7302 return $cached_atags($id)
7303 }
7304
7305 set origid $id
7306 set todo [list $id]
7307 set queued($id) 1
7308 set taglist {}
7309 set nc 1
7310 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
7311 set id [lindex $todo $i]
7312 set done($id) 1
7313 set td [info exists hastaggeddescendent($id)]
7314 if {!$td} {
7315 incr nc -1
7316 }
7317 # ignore tags on starting node
7318 if {!$td && $i > 0} {
7319 if {[info exists idtags($id)]} {
7320 set tagloc($id) $id
7321 set td 1
7322 } elseif {[info exists cached_atags($id)]} {
7323 set tagloc($id) $cached_atags($id)
7324 set td 1
7325 }
7326 }
7327 foreach a $arcout($id) {
7328 if {!$td && $arctags($a) ne {}} {
7329 validate_arctags $a
7330 if {$arctags($a) ne {}} {
7331 lappend tagloc($id) [lindex $arctags($a) 0]
7332 }
7333 }
7334 if {![info exists arcend($a)]} continue
7335 set d $arcend($a)
7336 if {$td || $arctags($a) ne {}} {
7337 set tomark [list $d]
7338 for {set j 0} {$j < [llength $tomark]} {incr j} {
7339 set dd [lindex $tomark $j]
7340 if {![info exists hastaggeddescendent($dd)]} {
7341 if {[info exists done($dd)]} {
7342 foreach b $arcout($dd) {
7343 if {[info exists arcend($b)]} {
7344 lappend tomark $arcend($b)
7345 }
7346 }
7347 if {[info exists tagloc($dd)]} {
7348 unset tagloc($dd)
7349 }
7350 } elseif {[info exists queued($dd)]} {
7351 incr nc -1
7352 }
7353 set hastaggeddescendent($dd) 1
7354 }
7355 }
7356 }
7357 if {![info exists queued($d)]} {
7358 lappend todo $d
7359 set queued($d) 1
7360 if {![info exists hastaggeddescendent($d)]} {
7361 incr nc
7362 }
7363 }
7364 }
7365 }
7366 set t2 [clock clicks -milliseconds]
7367 set loopix $i
7368 set tags {}
7369 foreach id [array names tagloc] {
7370 if {![info exists hastaggeddescendent($id)]} {
7371 foreach t $tagloc($id) {
7372 if {[lsearch -exact $tags $t] < 0} {
7373 lappend tags $t
7374 }
7375 }
7376 }
7377 }
7378
7379 # remove tags that are ancestors of other tags
7380 for {set i 0} {$i < [llength $tags]} {incr i} {
7381 set a [lindex $tags $i]
7382 for {set j 0} {$j < $i} {incr j} {
7383 set b [lindex $tags $j]
7384 set r [anc_or_desc $a $b]
7385 if {$r == -1} {
7386 set tags [lreplace $tags $j $j]
7387 incr j -1
7388 incr i -1
7389 } elseif {$r == 1} {
7390 set tags [lreplace $tags $i $i]
7391 incr i -1
7392 break
7393 }
7394 }
7395 }
7396
7397 if {[array names growing] ne {}} {
7398 # graph isn't finished, need to check if any tag could get
7399 # eclipsed by another tag coming later. Simply ignore any
7400 # tags that could later get eclipsed.
7401 set ctags {}
7402 foreach t $tags {
7403 if {[is_certain $origid $t]} {
7404 lappend ctags $t
7405 }
7406 }
7407 if {$tags eq $ctags} {
7408 set cached_atags($origid) $tags
7409 } else {
7410 set tags $ctags
7411 }
7412 } else {
7413 set cached_atags($origid) $tags
7414 }
7415 set t3 [clock clicks -milliseconds]
7416 if {0 && $t3 - $t1 >= 100} {
7417 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
7418 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
7419 }
7420 return $tags
7421}
7422
7423# Return the list of IDs that have heads that are descendents of id,
7424# including id itself if it has a head.
7425proc descheads {id} {
7426 global arcnos arcstart arcids archeads idheads cached_dheads
7427 global allparents
7428
7429 if {![info exists allparents($id)]} {
7430 return {}
7431 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10007432 set aret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10007433 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
7434 # part-way along an arc; check it first
7435 set a [lindex $arcnos($id) 0]
7436 if {$archeads($a) ne {}} {
7437 validate_archeads $a
7438 set i [lsearch -exact $arcids($a) $id]
7439 foreach t $archeads($a) {
7440 set j [lsearch -exact $arcids($a) $t]
7441 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +10007442 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +10007443 }
7444 }
7445 set id $arcstart($a)
7446 }
7447 set origid $id
7448 set todo [list $id]
7449 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +10007450 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10007451 for {set i 0} {$i < [llength $todo]} {incr i} {
7452 set id [lindex $todo $i]
7453 if {[info exists cached_dheads($id)]} {
7454 set ret [concat $ret $cached_dheads($id)]
7455 } else {
7456 if {[info exists idheads($id)]} {
7457 lappend ret $id
7458 }
7459 foreach a $arcnos($id) {
7460 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +10007461 validate_archeads $a
7462 if {$archeads($a) ne {}} {
7463 set ret [concat $ret $archeads($a)]
7464 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007465 }
7466 set d $arcstart($a)
7467 if {![info exists seen($d)]} {
7468 lappend todo $d
7469 set seen($d) 1
7470 }
7471 }
7472 }
7473 }
7474 set ret [lsort -unique $ret]
7475 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +10007476 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +10007477}
7478
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007479proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007480 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007481
Paul Mackerrase11f1232007-06-16 20:29:25 +10007482 if {![info exists arcnos($id)]} return
7483 if {![info exists arcout($id)]} {
7484 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007485 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007486 catch {unset cached_dtags}
7487 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007488}
7489
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007490proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007491 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007492
Paul Mackerrase11f1232007-06-16 20:29:25 +10007493 if {![info exists arcnos($hid)]} return
7494 if {![info exists arcout($hid)]} {
7495 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007496 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007497 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007498}
7499
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007500proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007501 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007502
Paul Mackerrase11f1232007-06-16 20:29:25 +10007503 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +10007504}
7505
Paul Mackerrase11f1232007-06-16 20:29:25 +10007506proc movedhead {hid head} {
7507 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007508
Paul Mackerrase11f1232007-06-16 20:29:25 +10007509 if {![info exists arcnos($hid)]} return
7510 if {![info exists arcout($hid)]} {
7511 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007512 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007513 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007514}
7515
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007516proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007517 global cached_dheads cached_dtags cached_atags
7518 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007519
Paul Mackerrase11f1232007-06-16 20:29:25 +10007520 foreach id [concat [array names idheads] [array names idtags]] {
7521 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
7522 set a [lindex $arcnos($id) 0]
7523 if {![info exists donearc($a)]} {
7524 recalcarc $a
7525 set donearc($a) 1
7526 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007527 }
7528 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007529 catch {unset cached_dtags}
7530 catch {unset cached_atags}
7531 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007532}
7533
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007534proc rereadrefs {} {
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007535 global idtags idheads idotherrefs mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007536
7537 set refids [concat [array names idtags] \
7538 [array names idheads] [array names idotherrefs]]
7539 foreach id $refids {
7540 if {![info exists ref($id)]} {
7541 set ref($id) [listrefs $id]
7542 }
7543 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007544 set oldmainhead $mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007545 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007546 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007547 set refids [lsort -unique [concat $refids [array names idtags] \
7548 [array names idheads] [array names idotherrefs]]]
7549 foreach id $refids {
7550 set v [listrefs $id]
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007551 if {![info exists ref($id)] || $ref($id) != $v ||
7552 ($id eq $oldmainhead && $id ne $mainhead) ||
7553 ($id eq $mainhead && $id ne $oldmainhead)} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007554 redrawtags $id
7555 }
7556 }
Paul Mackerras887c9962007-08-20 19:36:20 +10007557 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007558}
7559
Junio C Hamano2e1ded42006-06-11 09:50:47 -07007560proc listrefs {id} {
7561 global idtags idheads idotherrefs
7562
7563 set x {}
7564 if {[info exists idtags($id)]} {
7565 set x $idtags($id)
7566 }
7567 set y {}
7568 if {[info exists idheads($id)]} {
7569 set y $idheads($id)
7570 }
7571 set z {}
7572 if {[info exists idotherrefs($id)]} {
7573 set z $idotherrefs($id)
7574 }
7575 return [list $x $y $z]
7576}
7577
Paul Mackerras106288c2005-08-19 23:11:39 +10007578proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10007579 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +10007580
7581 if {$isnew} {
7582 addtohistory [list showtag $tag 0]
7583 }
7584 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007585 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007586 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +10007587 if {![info exists tagcontents($tag)]} {
7588 catch {
7589 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
7590 }
7591 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007592 if {[info exists tagcontents($tag)]} {
7593 set text $tagcontents($tag)
7594 } else {
7595 set text "Tag: $tag\nId: $tagids($tag)"
7596 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007597 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +10007598 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007599 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +10007600}
7601
Paul Mackerras1d10f362005-05-15 12:55:47 +00007602proc doquit {} {
7603 global stopped
7604 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -05007605 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +00007606 destroy .
7607}
7608
Paul Mackerras712fcc02005-11-30 09:28:16 +11007609proc doprefs {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10007610 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007611 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl60378c02007-05-20 12:12:48 -04007612 global bgcolor fgcolor ctext diffcolors selectbgcolor
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007613 global uifont tabstop
Paul Mackerras232475d2005-11-15 10:34:03 +11007614
Paul Mackerras712fcc02005-11-30 09:28:16 +11007615 set top .gitkprefs
7616 set prefstop $top
7617 if {[winfo exists $top]} {
7618 raise $top
7619 return
Paul Mackerras757f17b2005-11-21 09:56:07 +11007620 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007621 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11007622 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +11007623 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11007624 toplevel $top
7625 wm title $top "Gitk preferences"
7626 label $top.ldisp -text "Commit list display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007627 $top.ldisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11007628 grid $top.ldisp - -sticky w -pady 10
7629 label $top.spacer -text " "
7630 label $top.maxwidthl -text "Maximum graph width (lines)" \
7631 -font optionfont
7632 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
7633 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
7634 label $top.maxpctl -text "Maximum graph width (% of pane)" \
7635 -font optionfont
7636 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
7637 grid x $top.maxpctl $top.maxpct -sticky w
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007638 frame $top.showlocal
7639 label $top.showlocal.l -text "Show local changes" -font optionfont
7640 checkbutton $top.showlocal.b -variable showlocalchanges
7641 pack $top.showlocal.b $top.showlocal.l -side left
7642 grid x $top.showlocal -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007643
Paul Mackerras712fcc02005-11-30 09:28:16 +11007644 label $top.ddisp -text "Diff display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007645 $top.ddisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11007646 grid $top.ddisp - -sticky w -pady 10
7647 label $top.diffoptl -text "Options for diff program" \
7648 -font optionfont
7649 entry $top.diffopt -width 20 -textvariable diffopts
7650 grid x $top.diffoptl $top.diffopt -sticky w
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007651 frame $top.ntag
7652 label $top.ntag.l -text "Display nearby tags" -font optionfont
7653 checkbutton $top.ntag.b -variable showneartags
7654 pack $top.ntag.b $top.ntag.l -side left
7655 grid x $top.ntag -sticky w
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007656 label $top.tabstopl -text "tabstop" -font optionfont
Mark Levedahl6bc9d1e2007-06-26 21:51:35 -04007657 spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007658 grid x $top.tabstopl $top.tabstop -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007659
7660 label $top.cdisp -text "Colors: press to choose"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007661 $top.cdisp configure -font $uifont
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007662 grid $top.cdisp - -sticky w -pady 10
7663 label $top.bg -padx 40 -relief sunk -background $bgcolor
7664 button $top.bgbut -text "Background" -font optionfont \
7665 -command [list choosecolor bgcolor 0 $top.bg background setbg]
7666 grid x $top.bgbut $top.bg -sticky w
7667 label $top.fg -padx 40 -relief sunk -background $fgcolor
7668 button $top.fgbut -text "Foreground" -font optionfont \
7669 -command [list choosecolor fgcolor 0 $top.fg foreground setfg]
7670 grid x $top.fgbut $top.fg -sticky w
7671 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
7672 button $top.diffoldbut -text "Diff: old lines" -font optionfont \
7673 -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
7674 [list $ctext tag conf d0 -foreground]]
7675 grid x $top.diffoldbut $top.diffold -sticky w
7676 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
7677 button $top.diffnewbut -text "Diff: new lines" -font optionfont \
7678 -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
7679 [list $ctext tag conf d1 -foreground]]
7680 grid x $top.diffnewbut $top.diffnew -sticky w
7681 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
7682 button $top.hunksepbut -text "Diff: hunk header" -font optionfont \
7683 -command [list choosecolor diffcolors 2 $top.hunksep \
7684 "diff hunk header" \
7685 [list $ctext tag conf hunksep -foreground]]
7686 grid x $top.hunksepbut $top.hunksep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -04007687 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
7688 button $top.selbgbut -text "Select bg" -font optionfont \
Mark Levedahl281404c2007-06-26 21:51:34 -04007689 -command [list choosecolor selectbgcolor 0 $top.selbgsep background setselbg]
Mark Levedahl60378c02007-05-20 12:12:48 -04007690 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007691
Paul Mackerras712fcc02005-11-30 09:28:16 +11007692 frame $top.buts
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04007693 button $top.buts.ok -text "OK" -command prefsok -default active
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007694 $top.buts.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04007695 button $top.buts.can -text "Cancel" -command prefscan -default normal
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007696 $top.buts.can configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11007697 grid $top.buts.ok $top.buts.can
7698 grid columnconfigure $top.buts 0 -weight 1 -uniform a
7699 grid columnconfigure $top.buts 1 -weight 1 -uniform a
7700 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04007701 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +11007702}
7703
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007704proc choosecolor {v vi w x cmd} {
7705 global $v
7706
7707 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
7708 -title "Gitk: choose color for $x"]
7709 if {$c eq {}} return
7710 $w conf -background $c
7711 lset $v $vi $c
7712 eval $cmd $c
7713}
7714
Mark Levedahl60378c02007-05-20 12:12:48 -04007715proc setselbg {c} {
7716 global bglist cflist
7717 foreach w $bglist {
7718 $w configure -selectbackground $c
7719 }
7720 $cflist tag configure highlight \
7721 -background [$cflist cget -selectbackground]
7722 allcanvs itemconf secsel -fill $c
7723}
7724
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007725proc setbg {c} {
7726 global bglist
7727
7728 foreach w $bglist {
7729 $w conf -background $c
7730 }
7731}
7732
7733proc setfg {c} {
7734 global fglist canv
7735
7736 foreach w $fglist {
7737 $w conf -foreground $c
7738 }
7739 allcanvs itemconf text -fill $c
7740 $canv itemconf circle -outline $c
7741}
7742
Paul Mackerras712fcc02005-11-30 09:28:16 +11007743proc prefscan {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10007744 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007745 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras712fcc02005-11-30 09:28:16 +11007746
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007747 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11007748 set $v $oldprefs($v)
7749 }
7750 catch {destroy $prefstop}
7751 unset prefstop
7752}
7753
7754proc prefsok {} {
7755 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007756 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007757 global charspc ctext tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11007758
7759 catch {destroy $prefstop}
7760 unset prefstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007761 $ctext configure -tabs "[expr {$tabstop * $charspc}]"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007762 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
7763 if {$showlocalchanges} {
7764 doshowlocalchanges
7765 } else {
7766 dohidelocalchanges
7767 }
7768 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11007769 if {$maxwidth != $oldprefs(maxwidth)
7770 || $maxgraphpct != $oldprefs(maxgraphpct)} {
7771 redisplay
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007772 } elseif {$showneartags != $oldprefs(showneartags)} {
7773 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +11007774 }
7775}
7776
7777proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02007778 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007779 if {$d ne {}} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02007780 set d [clock format $d -format $datetimeformat]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007781 }
7782 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +11007783}
7784
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007785# This list of encoding names and aliases is distilled from
7786# http://www.iana.org/assignments/character-sets.
7787# Not all of them are supported by Tcl.
7788set encoding_aliases {
7789 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
7790 ISO646-US US-ASCII us IBM367 cp367 csASCII }
7791 { ISO-10646-UTF-1 csISO10646UTF1 }
7792 { ISO_646.basic:1983 ref csISO646basic1983 }
7793 { INVARIANT csINVARIANT }
7794 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
7795 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
7796 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
7797 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
7798 { NATS-DANO iso-ir-9-1 csNATSDANO }
7799 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
7800 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
7801 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
7802 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
7803 { ISO-2022-KR csISO2022KR }
7804 { EUC-KR csEUCKR }
7805 { ISO-2022-JP csISO2022JP }
7806 { ISO-2022-JP-2 csISO2022JP2 }
7807 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
7808 csISO13JISC6220jp }
7809 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
7810 { IT iso-ir-15 ISO646-IT csISO15Italian }
7811 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
7812 { ES iso-ir-17 ISO646-ES csISO17Spanish }
7813 { greek7-old iso-ir-18 csISO18Greek7Old }
7814 { latin-greek iso-ir-19 csISO19LatinGreek }
7815 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
7816 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
7817 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
7818 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
7819 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
7820 { BS_viewdata iso-ir-47 csISO47BSViewdata }
7821 { INIS iso-ir-49 csISO49INIS }
7822 { INIS-8 iso-ir-50 csISO50INIS8 }
7823 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
7824 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
7825 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
7826 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
7827 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
7828 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
7829 csISO60Norwegian1 }
7830 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
7831 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
7832 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
7833 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
7834 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
7835 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
7836 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
7837 { greek7 iso-ir-88 csISO88Greek7 }
7838 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
7839 { iso-ir-90 csISO90 }
7840 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
7841 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
7842 csISO92JISC62991984b }
7843 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
7844 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
7845 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
7846 csISO95JIS62291984handadd }
7847 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
7848 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
7849 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
7850 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
7851 CP819 csISOLatin1 }
7852 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
7853 { T.61-7bit iso-ir-102 csISO102T617bit }
7854 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
7855 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
7856 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
7857 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
7858 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
7859 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
7860 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
7861 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
7862 arabic csISOLatinArabic }
7863 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
7864 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
7865 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
7866 greek greek8 csISOLatinGreek }
7867 { T.101-G2 iso-ir-128 csISO128T101G2 }
7868 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
7869 csISOLatinHebrew }
7870 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
7871 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
7872 { CSN_369103 iso-ir-139 csISO139CSN369103 }
7873 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
7874 { ISO_6937-2-add iso-ir-142 csISOTextComm }
7875 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
7876 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
7877 csISOLatinCyrillic }
7878 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
7879 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
7880 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
7881 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
7882 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
7883 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
7884 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
7885 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
7886 { ISO_10367-box iso-ir-155 csISO10367Box }
7887 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
7888 { latin-lap lap iso-ir-158 csISO158Lap }
7889 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
7890 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
7891 { us-dk csUSDK }
7892 { dk-us csDKUS }
7893 { JIS_X0201 X0201 csHalfWidthKatakana }
7894 { KSC5636 ISO646-KR csKSC5636 }
7895 { ISO-10646-UCS-2 csUnicode }
7896 { ISO-10646-UCS-4 csUCS4 }
7897 { DEC-MCS dec csDECMCS }
7898 { hp-roman8 roman8 r8 csHPRoman8 }
7899 { macintosh mac csMacintosh }
7900 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
7901 csIBM037 }
7902 { IBM038 EBCDIC-INT cp038 csIBM038 }
7903 { IBM273 CP273 csIBM273 }
7904 { IBM274 EBCDIC-BE CP274 csIBM274 }
7905 { IBM275 EBCDIC-BR cp275 csIBM275 }
7906 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
7907 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
7908 { IBM280 CP280 ebcdic-cp-it csIBM280 }
7909 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
7910 { IBM284 CP284 ebcdic-cp-es csIBM284 }
7911 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
7912 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
7913 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
7914 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
7915 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
7916 { IBM424 cp424 ebcdic-cp-he csIBM424 }
7917 { IBM437 cp437 437 csPC8CodePage437 }
7918 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
7919 { IBM775 cp775 csPC775Baltic }
7920 { IBM850 cp850 850 csPC850Multilingual }
7921 { IBM851 cp851 851 csIBM851 }
7922 { IBM852 cp852 852 csPCp852 }
7923 { IBM855 cp855 855 csIBM855 }
7924 { IBM857 cp857 857 csIBM857 }
7925 { IBM860 cp860 860 csIBM860 }
7926 { IBM861 cp861 861 cp-is csIBM861 }
7927 { IBM862 cp862 862 csPC862LatinHebrew }
7928 { IBM863 cp863 863 csIBM863 }
7929 { IBM864 cp864 csIBM864 }
7930 { IBM865 cp865 865 csIBM865 }
7931 { IBM866 cp866 866 csIBM866 }
7932 { IBM868 CP868 cp-ar csIBM868 }
7933 { IBM869 cp869 869 cp-gr csIBM869 }
7934 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
7935 { IBM871 CP871 ebcdic-cp-is csIBM871 }
7936 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
7937 { IBM891 cp891 csIBM891 }
7938 { IBM903 cp903 csIBM903 }
7939 { IBM904 cp904 904 csIBBM904 }
7940 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
7941 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
7942 { IBM1026 CP1026 csIBM1026 }
7943 { EBCDIC-AT-DE csIBMEBCDICATDE }
7944 { EBCDIC-AT-DE-A csEBCDICATDEA }
7945 { EBCDIC-CA-FR csEBCDICCAFR }
7946 { EBCDIC-DK-NO csEBCDICDKNO }
7947 { EBCDIC-DK-NO-A csEBCDICDKNOA }
7948 { EBCDIC-FI-SE csEBCDICFISE }
7949 { EBCDIC-FI-SE-A csEBCDICFISEA }
7950 { EBCDIC-FR csEBCDICFR }
7951 { EBCDIC-IT csEBCDICIT }
7952 { EBCDIC-PT csEBCDICPT }
7953 { EBCDIC-ES csEBCDICES }
7954 { EBCDIC-ES-A csEBCDICESA }
7955 { EBCDIC-ES-S csEBCDICESS }
7956 { EBCDIC-UK csEBCDICUK }
7957 { EBCDIC-US csEBCDICUS }
7958 { UNKNOWN-8BIT csUnknown8BiT }
7959 { MNEMONIC csMnemonic }
7960 { MNEM csMnem }
7961 { VISCII csVISCII }
7962 { VIQR csVIQR }
7963 { KOI8-R csKOI8R }
7964 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
7965 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
7966 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
7967 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
7968 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
7969 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
7970 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
7971 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
7972 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
7973 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
7974 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
7975 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
7976 { IBM1047 IBM-1047 }
7977 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
7978 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
7979 { UNICODE-1-1 csUnicode11 }
7980 { CESU-8 csCESU-8 }
7981 { BOCU-1 csBOCU-1 }
7982 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
7983 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
7984 l8 }
7985 { ISO-8859-15 ISO_8859-15 Latin-9 }
7986 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
7987 { GBK CP936 MS936 windows-936 }
7988 { JIS_Encoding csJISEncoding }
7989 { Shift_JIS MS_Kanji csShiftJIS }
7990 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
7991 EUC-JP }
7992 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
7993 { ISO-10646-UCS-Basic csUnicodeASCII }
7994 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
7995 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
7996 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
7997 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
7998 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
7999 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
8000 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
8001 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
8002 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
8003 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
8004 { Adobe-Standard-Encoding csAdobeStandardEncoding }
8005 { Ventura-US csVenturaUS }
8006 { Ventura-International csVenturaInternational }
8007 { PC8-Danish-Norwegian csPC8DanishNorwegian }
8008 { PC8-Turkish csPC8Turkish }
8009 { IBM-Symbols csIBMSymbols }
8010 { IBM-Thai csIBMThai }
8011 { HP-Legal csHPLegal }
8012 { HP-Pi-font csHPPiFont }
8013 { HP-Math8 csHPMath8 }
8014 { Adobe-Symbol-Encoding csHPPSMath }
8015 { HP-DeskTop csHPDesktop }
8016 { Ventura-Math csVenturaMath }
8017 { Microsoft-Publishing csMicrosoftPublishing }
8018 { Windows-31J csWindows31J }
8019 { GB2312 csGB2312 }
8020 { Big5 csBig5 }
8021}
8022
8023proc tcl_encoding {enc} {
8024 global encoding_aliases
8025 set names [encoding names]
8026 set lcnames [string tolower $names]
8027 set enc [string tolower $enc]
8028 set i [lsearch -exact $lcnames $enc]
8029 if {$i < 0} {
8030 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
8031 if {[regsub {^iso[-_]} $enc iso encx]} {
8032 set i [lsearch -exact $lcnames $encx]
8033 }
8034 }
8035 if {$i < 0} {
8036 foreach l $encoding_aliases {
8037 set ll [string tolower $l]
8038 if {[lsearch -exact $ll $enc] < 0} continue
8039 # look through the aliases for one that tcl knows about
8040 foreach e $ll {
8041 set i [lsearch -exact $lcnames $e]
8042 if {$i < 0} {
8043 if {[regsub {^iso[-_]} $e iso ex]} {
8044 set i [lsearch -exact $lcnames $ex]
8045 }
8046 }
8047 if {$i >= 0} break
8048 }
8049 break
8050 }
8051 }
8052 if {$i >= 0} {
8053 return [lindex $names $i]
8054 }
8055 return {}
8056}
8057
Paul Mackerras1d10f362005-05-15 12:55:47 +00008058# defaults...
8059set datemode 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00008060set diffopts "-U 5 -p"
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03008061set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -08008062
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11008063set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -08008064catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +11008065 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -08008066}
8067if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11008068 set gitencoding "utf-8"
8069}
8070set tclencoding [tcl_encoding $gitencoding]
8071if {$tclencoding == {}} {
8072 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -08008073}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008074
8075set mainfont {Helvetica 9}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008076set textfont {Courier 9}
Keith Packard4840be62006-04-04 00:19:45 -07008077set uifont {Helvetica 9 bold}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04008078set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -04008079set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +10008080set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008081set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +11008082set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +11008083set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10008084set uparrowlen 5
8085set downarrowlen 5
8086set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10008087set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +04008088set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008089set showneartags 1
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10008090set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +10008091set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008092set showlocalchanges 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02008093set datetimeformat "%Y-%m-%d %H:%M:%S"
Paul Mackerras1d10f362005-05-15 12:55:47 +00008094
8095set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008096set bgcolor white
8097set fgcolor black
8098set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +02008099set diffcontext 3
Mark Levedahl60378c02007-05-20 12:12:48 -04008100set selectbgcolor gray85
Paul Mackerras1d10f362005-05-15 12:55:47 +00008101
8102catch {source ~/.gitk}
8103
Paul Mackerras712fcc02005-11-30 09:28:16 +11008104font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +00008105
Paul Mackerrasaa81d972006-02-28 11:27:12 +11008106# check that we can find a .git directory somewhere...
Alex Riesen6c87d602007-07-29 22:29:45 +02008107if {[catch {set gitdir [gitdir]}]} {
8108 show_error {} . "Cannot find a git repository here."
8109 exit 1
8110}
Paul Mackerrasaa81d972006-02-28 11:27:12 +11008111if {![file isdirectory $gitdir]} {
Paul Mackerrase54be9e2006-05-26 22:34:30 +10008112 show_error {} . "Cannot find the git directory \"$gitdir\"."
Paul Mackerrasaa81d972006-02-28 11:27:12 +11008113 exit 1
8114}
8115
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10008116set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008117set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10008118set i 0
8119foreach arg $argv {
Paul Mackerras6ebedab2007-07-13 13:45:55 +10008120 switch -- $arg {
8121 "" { }
8122 "-d" { set datemode 1 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10008123 "--" {
8124 set cmdline_files [lrange $argv [expr {$i + 1}] end]
8125 break
8126 }
8127 default {
8128 lappend revtreeargs $arg
8129 }
8130 }
8131 incr i
8132}
8133
8134if {$i >= [llength $argv] && $revtreeargs ne {}} {
8135 # no -- on command line, but some arguments (other than -d)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008136 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03008137 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008138 set cmdline_files [split $f "\n"]
8139 set n [llength $cmdline_files]
8140 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10008141 # Unfortunately git rev-parse doesn't produce an error when
8142 # something is both a revision and a filename. To be consistent
8143 # with git log and git rev-list, check revtreeargs for filenames.
8144 foreach arg $revtreeargs {
8145 if {[file exists $arg]} {
8146 show_error {} . "Ambiguous argument '$arg': both revision\
8147 and filename"
8148 exit 1
8149 }
8150 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008151 } err]} {
8152 # unfortunately we get both stdout and stderr in $err,
8153 # so look for "fatal:".
8154 set i [string first "fatal:" $err]
8155 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -07008156 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008157 }
Paul Mackerrase54be9e2006-05-26 22:34:30 +10008158 show_error {} . "Bad arguments to gitk:\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008159 exit 1
8160 }
8161}
8162
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008163set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +10008164set nullid2 "0000000000000000000000000000000000000001"
8165
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008166
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008167set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +10008168set history {}
8169set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +10008170set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +10008171set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +10008172set highlight_paths {}
Paul Mackerras1902c272006-05-25 21:25:13 +10008173set searchdirn -forwards
Paul Mackerras4e7d6772006-05-30 21:33:07 +10008174set boldrows {}
8175set boldnamerows {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008176set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10008177set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +10008178set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +10008179set need_redisplay 0
8180set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008181
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008182set nextviewnum 1
8183set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008184set selectedview 0
Paul Mackerras908c3582006-05-20 09:38:11 +10008185set selectedhlview None
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008186set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008187set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008188set viewargs(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008189
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008190set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00008191set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +00008192set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +10008193set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008194set lookingforhead 0
Paul Mackerras8f489362007-07-13 19:49:37 +10008195set localirow -1
8196set localfrow -1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008197set lserial 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00008198setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10008199makewindow
Paul Mackerras0eafba12007-07-23 21:35:03 +10008200# wait for the window to become visible
8201tkwait visibility .
Doug Maxey6c283322006-12-10 14:31:46 -06008202wm title . "[file tail $argv0]: [file tail [pwd]]"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008203readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10008204
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008205if {$cmdline_files ne {} || $revtreeargs ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008206 # create a view for the files/dirs specified on the command line
8207 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008208 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008209 set nextviewnum 2
8210 set viewname(1) "Command line"
8211 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008212 set viewargs(1) $revtreeargs
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008213 set viewperm(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008214 addviewmenu 1
Paul Mackerras3cd204e2006-11-23 21:06:16 +11008215 .bar.view entryconf Edit* -state normal
8216 .bar.view entryconf Delete* -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008217}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008218
8219if {[info exists permviews]} {
8220 foreach v $permviews {
8221 set n $nextviewnum
8222 incr nextviewnum
8223 set viewname($n) [lindex $v 0]
8224 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10008225 set viewargs($n) [lindex $v 2]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008226 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008227 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10008228 }
8229}
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10008230getcommits