blob: d5b71dd45dd2aa03050074c086d355a87fb76efb [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 Mackerras098dd8a2006-05-03 09:32:53 +100085 global viewargs viewfiles commitidx
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 Mackerras098dd8a2006-05-03 09:32:53 +100090 set args $viewargs($view)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100091 if {$viewfiles($view) ne {}} {
92 set args [concat $args "--" $viewfiles($view)]
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100093 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +110094 set order "--topo-order"
95 if {$datemode} {
96 set order "--date-order"
97 }
Paul Mackerras418c4c72006-02-07 09:10:18 +110098 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030099 set fd [open [concat | git rev-list --header $order \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000100 --parents --boundary --default HEAD $args] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100101 } err]} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300102 puts stderr "Error executing git rev-list: $err"
Paul Mackerras38ad0912005-12-01 22:42:46 +1100103 exit 1
104 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000105 set commfd($view) $fd
106 set leftover($view) {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000107 set lookingforhead $showlocalchanges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000108 fconfigure $fd -blocking 0 -translation lf
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100109 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000110 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100111 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000112 filerun $fd [list getcommitlines $fd $view]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000113 nowbusy $view
Paul Mackerras38ad0912005-12-01 22:42:46 +1100114}
115
Paul Mackerras22626ef2006-04-17 09:56:02 +1000116proc stop_rev_list {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000117 global commfd curview
Paul Mackerras22626ef2006-04-17 09:56:02 +1000118
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000119 if {![info exists commfd($curview)]} return
120 set fd $commfd($curview)
Paul Mackerras22626ef2006-04-17 09:56:02 +1000121 catch {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000122 set pid [pid $fd]
Paul Mackerras22626ef2006-04-17 09:56:02 +1000123 exec kill $pid
124 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000125 catch {close $fd}
126 unset commfd($curview)
Paul Mackerras22626ef2006-04-17 09:56:02 +1000127}
128
Paul Mackerrasa8aaf192006-04-23 22:45:55 +1000129proc getcommits {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000130 global phase canv mainfont curview
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100131
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100132 set phase getcommits
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000133 initlayout
134 start_rev_list $curview
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000135 show_status "Reading commits..."
Paul Mackerras1d10f362005-05-15 12:55:47 +0000136}
137
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000138proc getcommitlines {fd view} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000139 global commitlisted
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000140 global leftover commfd
Paul Mackerras8ed16482006-03-02 22:56:44 +1100141 global displayorder commitidx commitrow commitdata
Paul Mackerras6a90bff2007-06-18 09:48:23 +1000142 global parentlist children curview hlview
143 global vparentlist vdisporder vcmitlisted
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000144
Paul Mackerrasd1e46752006-08-16 20:02:32 +1000145 set stuff [read $fd 500000]
Paul Mackerrasb490a992005-06-22 10:25:38 +1000146 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000147 if {![eof $fd]} {
148 return 1
149 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000150 global viewname
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000151 unset commfd($view)
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000152 notbusy $view
Paul Mackerrasf0654862005-07-18 14:29:03 -0400153 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000154 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000155 if {[catch {close $fd} err]} {
156 set fv {}
157 if {$view != $curview} {
158 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000159 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000160 if {[string range $err 0 4] == "usage"} {
161 set err "Gitk: error reading commits$fv:\
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300162 bad arguments to git rev-list."
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000163 if {$viewname($view) eq "Command line"} {
164 append err \
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300165 " (Note: arguments to gitk are passed to git rev-list\
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000166 to allow selection of commits to be displayed.)"
167 }
168 } else {
169 set err "Error reading commits$fv: $err"
170 }
171 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +0000172 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000173 if {$view == $curview} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000174 run chewcommits $view
Paul Mackerras9a40c502005-05-12 23:46:16 +0000175 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000176 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +0000177 }
Paul Mackerrasb490a992005-06-22 10:25:38 +1000178 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100179 set gotsome 0
Paul Mackerrasb490a992005-06-22 10:25:38 +1000180 while 1 {
181 set i [string first "\0" $stuff $start]
182 if {$i < 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000183 append leftover($view) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100184 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000185 }
Paul Mackerrasb490a992005-06-22 10:25:38 +1000186 if {$start == 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000187 set cmit $leftover($view)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100188 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000189 set leftover($view) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100190 } else {
191 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +1000192 }
193 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000194 set j [string first "\n" $cmit]
195 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100196 set listed 1
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000197 if {$j >= 0} {
198 set ids [string range $cmit 0 [expr {$j - 1}]]
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100199 if {[string range $ids 0 0] == "-"} {
200 set listed 0
201 set ids [string range $ids 1 end]
202 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000203 set ok 1
204 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100205 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000206 set ok 0
207 break
208 }
209 }
210 }
211 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +1000212 set shortcmit $cmit
213 if {[string length $shortcmit] > 80} {
214 set shortcmit "[string range $shortcmit 0 80]..."
215 }
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300216 error_popup "Can't parse git rev-list output: {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +1000217 exit 1
218 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000219 set id [lindex $ids 0]
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100220 if {$listed} {
221 set olds [lrange $ids 1 end]
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000222 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +1000223 foreach p $olds {
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000224 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000225 lappend children($view,$p) $id
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000226 }
227 incr i
Paul Mackerras79b2c752006-04-02 20:47:40 +1000228 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100229 } else {
230 set olds {}
231 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000232 if {![info exists children($view,$id)]} {
233 set children($view,$id) {}
Paul Mackerras79b2c752006-04-02 20:47:40 +1000234 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100235 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000236 set commitrow($view,$id) $commitidx($view)
237 incr commitidx($view)
238 if {$view == $curview} {
239 lappend parentlist $olds
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000240 lappend displayorder $id
241 lappend commitlisted $listed
242 } else {
243 lappend vparentlist($view) $olds
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000244 lappend vdisporder($view) $id
245 lappend vcmitlisted($view) $listed
246 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100247 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100248 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100249 if {$gotsome} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000250 run chewcommits $view
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100251 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000252 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +0000253}
254
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000255proc chewcommits {view} {
256 global curview hlview commfd
257 global selectedline pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000258
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000259 set more 0
260 if {$view == $curview} {
261 set allread [expr {![info exists commfd($view)]}]
262 set tlimit [expr {[clock clicks -milliseconds] + 50}]
263 set more [layoutmore $tlimit $allread]
264 if {$allread && !$more} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000265 global displayorder nullid commitidx phase
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000266 global numcommits startmsecs
267
268 if {[info exists pending_select]} {
269 set row [expr {[lindex $displayorder 0] eq $nullid}]
270 selectline $row 1
271 }
272 if {$commitidx($curview) > 0} {
273 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
274 #puts "overall $ms ms for $numcommits commits"
275 } else {
276 show_status "No commits selected"
277 }
278 notbusy layout
279 set phase {}
280 }
Paul Mackerrasb6645502005-08-11 09:56:23 +1000281 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000282 if {[info exists hlview] && $view == $hlview} {
283 vhighlightmore
Paul Mackerrasb6645502005-08-11 09:56:23 +1000284 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000285 return $more
Paul Mackerras1db95b02005-05-09 04:08:39 +0000286}
287
288proc readcommit {id} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300289 if {[catch {set contents [exec git cat-file commit $id]}]} return
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100290 parsecommit $id $contents 0
Paul Mackerrasb490a992005-06-22 10:25:38 +1000291}
292
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000293proc updatecommits {} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000294 global viewdata curview phase displayorder
Paul Mackerras908c3582006-05-20 09:38:11 +1000295 global children commitrow selectedline thickerline
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000296
Paul Mackerras22626ef2006-04-17 09:56:02 +1000297 if {$phase ne {}} {
298 stop_rev_list
299 set phase {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100300 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000301 set n $curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000302 foreach id $displayorder {
303 catch {unset children($n,$id)}
304 catch {unset commitrow($n,$id)}
305 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000306 set curview -1
Paul Mackerras908c3582006-05-20 09:38:11 +1000307 catch {unset selectedline}
308 catch {unset thickerline}
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000309 catch {unset viewdata($n)}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100310 readrefs
Paul Mackerrase11f1232007-06-16 20:29:25 +1000311 changedrefs
312 regetallcommits
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000313 showview $n
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100314}
315
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100316proc parsecommit {id contents listed} {
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100317 global commitinfo cdate
318
319 set inhdr 1
320 set comment {}
321 set headline {}
322 set auname {}
323 set audate {}
324 set comname {}
325 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +1100326 set hdrend [string first "\n\n" $contents]
327 if {$hdrend < 0} {
328 # should never happen...
329 set hdrend [string length $contents]
330 }
331 set header [string range $contents 0 [expr {$hdrend - 1}]]
332 set comment [string range $contents [expr {$hdrend + 2}] end]
333 foreach line [split $header "\n"] {
334 set tag [lindex $line 0]
335 if {$tag == "author"} {
336 set audate [lindex $line end-1]
337 set auname [lrange $line 1 end-2]
338 } elseif {$tag == "committer"} {
339 set comdate [lindex $line end-1]
340 set comname [lrange $line 1 end-2]
Paul Mackerras1db95b02005-05-09 04:08:39 +0000341 }
342 }
Paul Mackerras232475d2005-11-15 10:34:03 +1100343 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +1000344 # take the first non-blank line of the comment as the headline
345 set headline [string trimleft $comment]
346 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +1100347 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +1000348 set headline [string range $headline 0 $i]
349 }
350 set headline [string trimright $headline]
351 set i [string first "\r" $headline]
352 if {$i >= 0} {
353 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +1100354 }
355 if {!$listed} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300356 # git rev-list indents the comment by 4 spaces;
357 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +1100358 set newcomment {}
359 foreach line [split $comment "\n"] {
360 append newcomment " "
361 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +1100362 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +1100363 }
364 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +0000365 }
366 if {$comdate != {}} {
Paul Mackerrascfb45632005-05-31 12:14:42 +0000367 set cdate($id) $comdate
Paul Mackerras1db95b02005-05-09 04:08:39 +0000368 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +0000369 set commitinfo($id) [list $headline $auname $audate \
370 $comname $comdate $comment]
Paul Mackerras1db95b02005-05-09 04:08:39 +0000371}
372
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100373proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +1000374 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +1100375
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100376 if {[info exists commitdata($id)]} {
377 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +1100378 } else {
379 readcommit $id
380 if {![info exists commitinfo($id)]} {
381 set commitinfo($id) {"No commit information available"}
Paul Mackerras8ed16482006-03-02 22:56:44 +1100382 }
383 }
384 return 1
385}
386
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000387proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000388 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000389 global otherrefids idotherrefs mainhead mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000390
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100391 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
392 catch {unset $v}
393 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000394 set refd [open [list | git show-ref -d] r]
395 while {[gets $refd line] >= 0} {
396 if {[string index $line 40] ne " "} continue
397 set id [string range $line 0 39]
398 set ref [string range $line 41 end]
399 if {![string match "refs/*" $ref]} continue
400 set name [string range $ref 5 end]
401 if {[string match "remotes/*" $name]} {
402 if {![string match "*/HEAD" $name]} {
403 set headids($name) $id
404 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000405 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000406 } elseif {[string match "heads/*" $name]} {
407 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800408 set headids($name) $id
409 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000410 } elseif {[string match "tags/*" $name]} {
411 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
412 # which is what we want since the former is the commit ID
413 set name [string range $name 5 end]
414 if {[string match "*^{}" $name]} {
415 set name [string range $name 0 end-3]
416 } else {
417 set tagobjid($name) $id
418 }
419 set tagids($name) $id
420 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800421 } else {
422 set otherrefids($name) $id
423 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000424 }
425 }
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800426 close $refd
Paul Mackerras8a485712006-07-06 10:21:23 +1000427 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000428 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +1000429 catch {
430 set thehead [exec git symbolic-ref HEAD]
431 if {[string match "refs/heads/*" $thehead]} {
432 set mainhead [string range $thehead 11 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000433 if {[info exists headids($mainhead)]} {
434 set mainheadid $headids($mainhead)
435 }
Paul Mackerras8a485712006-07-06 10:21:23 +1000436 }
437 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000438}
439
Paul Mackerrase11f1232007-06-16 20:29:25 +1000440# update things for a head moved to a child of its previous location
441proc movehead {id name} {
442 global headids idheads
443
444 removehead $headids($name) $name
445 set headids($name) $id
446 lappend idheads($id) $name
447}
448
449# update things when a head has been removed
450proc removehead {id name} {
451 global headids idheads
452
453 if {$idheads($id) eq $name} {
454 unset idheads($id)
455 } else {
456 set i [lsearch -exact $idheads($id) $name]
457 if {$i >= 0} {
458 set idheads($id) [lreplace $idheads($id) $i $i]
459 }
460 }
461 unset headids($name)
462}
463
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000464proc show_error {w top msg} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000465 message $w.m -text $msg -justify center -aspect 400
466 pack $w.m -side top -fill x -padx 20 -pady 20
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000467 button $w.ok -text OK -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000468 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000469 bind $top <Visibility> "grab $top; focus $top"
470 bind $top <Key-Return> "destroy $top"
471 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000472}
473
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000474proc error_popup msg {
475 set w .error
476 toplevel $w
477 wm transient $w .
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000478 show_error $w $w $msg
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000479}
480
Paul Mackerras10299152006-08-02 09:52:01 +1000481proc confirm_popup msg {
482 global confirm_ok
483 set confirm_ok 0
484 set w .confirm
485 toplevel $w
486 wm transient $w .
487 message $w.m -text $msg -justify center -aspect 400
488 pack $w.m -side top -fill x -padx 20 -pady 20
489 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
490 pack $w.ok -side left -fill x
491 button $w.cancel -text Cancel -command "destroy $w"
492 pack $w.cancel -side right -fill x
493 bind $w <Visibility> "grab $w; focus $w"
494 tkwait window $w
495 return $confirm_ok
496}
497
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000498proc makewindow {} {
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +1000499 global canv canv2 canv3 linespc charspc ctext cflist
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400500 global textfont mainfont uifont tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400501 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000502 global entries sha1entry sha1string sha1but
Paul Mackerras94a2eed2005-08-07 15:27:57 +1000503 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000504 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000505 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000506 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -0400507 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Paul Mackerras10299152006-08-02 09:52:01 +1000508 global headctxmenu
Paul Mackerras9a40c502005-05-12 23:46:16 +0000509
510 menu .bar
511 .bar add cascade -label "File" -menu .bar.file
Keith Packard4840be62006-04-04 00:19:45 -0700512 .bar configure -font $uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +0000513 menu .bar.file
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000514 .bar.file add command -label "Update" -command updatecommits
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000515 .bar.file add command -label "Reread references" -command rereadrefs
Paul Mackerras1d10f362005-05-15 12:55:47 +0000516 .bar.file add command -label "Quit" -command doquit
Keith Packard4840be62006-04-04 00:19:45 -0700517 .bar.file configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +1100518 menu .bar.edit
519 .bar add cascade -label "Edit" -menu .bar.edit
520 .bar.edit add command -label "Preferences" -command doprefs
Keith Packard4840be62006-04-04 00:19:45 -0700521 .bar.edit configure -font $uifont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000522
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +1000523 menu .bar.view -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000524 .bar add cascade -label "View" -menu .bar.view
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000525 .bar.view add command -label "New view..." -command {newview 0}
526 .bar.view add command -label "Edit view..." -command editview \
527 -state disabled
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000528 .bar.view add command -label "Delete view" -command delview -state disabled
529 .bar.view add separator
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000530 .bar.view add radiobutton -label "All files" -command {showview 0} \
531 -variable selectedview -value 0
Mark Levedahl40b87ff2007-02-01 08:44:46 -0500532
Paul Mackerras9a40c502005-05-12 23:46:16 +0000533 menu .bar.help
534 .bar add cascade -label "Help" -menu .bar.help
535 .bar.help add command -label "About gitk" -command about
Paul Mackerras4e95e1f2006-04-05 09:39:51 +1000536 .bar.help add command -label "Key bindings" -command keys
Keith Packard4840be62006-04-04 00:19:45 -0700537 .bar.help configure -font $uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +0000538 . configure -menu .bar
539
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500540 # the gui has upper and lower half, parts of a paned window.
Paul Mackerras0327d272005-05-10 00:23:42 +0000541 panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500542
543 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500544 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500545 set geometry(topheight) [expr {15 * $linespc}]
546 set geometry(topwidth) [expr {80 * $charspc}]
547 set geometry(botheight) [expr {15 * $linespc}]
548 set geometry(botwidth) [expr {50 * $charspc}]
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500549 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
550 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000551 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500552
553 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
554 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
555 frame .tf.histframe
556 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
557
558 # create three canvases
559 set cscroll .tf.histframe.csb
560 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500561 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -0400562 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000563 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100564 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500565 .tf.histframe.pwclist add $canv
566 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500567 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -0400568 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000569 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500570 .tf.histframe.pwclist add $canv2
571 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500572 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -0400573 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000574 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500575 .tf.histframe.pwclist add $canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500576 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
577 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Paul Mackerras98f350e2005-05-15 05:56:51 +0000578
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500579 # a scroll bar to rule them
580 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
581 pack $cscroll -side right -fill y
582 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
583 lappend bglist $canv $canv2 $canv3
584 pack .tf.histframe.pwclist -fill both -expand 1 -side left
585
586 # we have two button bars at bottom of top frame. Bar 1
587 frame .tf.bar
588 frame .tf.lbar -height 15
589
590 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000591 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500592 set sha1but .tf.bar.sha1label
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000593 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
Keith Packard4840be62006-04-04 00:19:45 -0700594 -command gotocommit -width 8 -font $uifont
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000595 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500596 pack .tf.bar.sha1label -side left
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000597 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
598 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +0000599 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +1000600
601 image create bitmap bm-left -data {
602 #define left_width 16
603 #define left_height 16
604 static unsigned char left_bits[] = {
605 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
606 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
607 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
608 }
609 image create bitmap bm-right -data {
610 #define right_width 16
611 #define right_height 16
612 static unsigned char right_bits[] = {
613 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
614 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
615 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
616 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500617 button .tf.bar.leftbut -image bm-left -command goback \
Paul Mackerrasd6982062005-08-06 22:06:06 +1000618 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500619 pack .tf.bar.leftbut -side left -fill y
620 button .tf.bar.rightbut -image bm-right -command goforw \
Paul Mackerrasd6982062005-08-06 22:06:06 +1000621 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500622 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +1000623
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500624 button .tf.bar.findbut -text "Find" -command dofind -font $uifont
625 pack .tf.bar.findbut -side left
Paul Mackerras98f350e2005-05-15 05:56:51 +0000626 set findstring {}
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500627 set fstring .tf.bar.findstring
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000628 lappend entries $fstring
Paul Mackerras908c3582006-05-20 09:38:11 +1000629 entry $fstring -width 30 -font $textfont -textvariable findstring
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000630 trace add variable findstring write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500631 pack $fstring -side left -expand 1 -fill x -in .tf.bar
Paul Mackerras98f350e2005-05-15 05:56:51 +0000632 set findtype Exact
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500633 set findtypemenu [tk_optionMenu .tf.bar.findtype \
634 findtype Exact IgnCase Regexp]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000635 trace add variable findtype write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500636 .tf.bar.findtype configure -font $uifont
637 .tf.bar.findtype.menu configure -font $uifont
Paul Mackerras98f350e2005-05-15 05:56:51 +0000638 set findloc "All fields"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500639 tk_optionMenu .tf.bar.findloc findloc "All fields" Headline \
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000640 Comments Author Committer
641 trace add variable findloc write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500642 .tf.bar.findloc configure -font $uifont
643 .tf.bar.findloc.menu configure -font $uifont
644 pack .tf.bar.findloc -side right
645 pack .tf.bar.findtype -side right
Paul Mackerrasb5721c72005-05-10 12:08:22 +0000646
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500647 # build up the bottom bar of upper window
648 label .tf.lbar.flabel -text "Highlight: Commits " \
649 -font $uifont
650 pack .tf.lbar.flabel -side left -fill y
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000651 set gdttype "touching paths:"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500652 set gm [tk_optionMenu .tf.lbar.gdttype gdttype "touching paths:" \
653 "adding/removing string:"]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000654 trace add variable gdttype write hfiles_change
655 $gm conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500656 .tf.lbar.gdttype conf -font $uifont
657 pack .tf.lbar.gdttype -side left -fill y
658 entry .tf.lbar.fent -width 25 -font $textfont \
Paul Mackerras908c3582006-05-20 09:38:11 +1000659 -textvariable highlight_files
660 trace add variable highlight_files write hfiles_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500661 lappend entries .tf.lbar.fent
662 pack .tf.lbar.fent -side left -fill x -expand 1
663 label .tf.lbar.vlabel -text " OR in view" -font $uifont
664 pack .tf.lbar.vlabel -side left -fill y
Paul Mackerras908c3582006-05-20 09:38:11 +1000665 global viewhlmenu selectedhlview
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500666 set viewhlmenu [tk_optionMenu .tf.lbar.vhl selectedhlview None]
Paul Mackerras3cd204e2006-11-23 21:06:16 +1100667 $viewhlmenu entryconf None -command delvhighlight
Paul Mackerras63b79192006-05-20 21:31:52 +1000668 $viewhlmenu conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500669 .tf.lbar.vhl conf -font $uifont
670 pack .tf.lbar.vhl -side left -fill y
671 label .tf.lbar.rlabel -text " OR " -font $uifont
672 pack .tf.lbar.rlabel -side left -fill y
Paul Mackerras164ff272006-05-29 19:50:02 +1000673 global highlight_related
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500674 set m [tk_optionMenu .tf.lbar.relm highlight_related None \
675 "Descendent" "Not descendent" "Ancestor" "Not ancestor"]
Paul Mackerras164ff272006-05-29 19:50:02 +1000676 $m conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500677 .tf.lbar.relm conf -font $uifont
Paul Mackerras164ff272006-05-29 19:50:02 +1000678 trace add variable highlight_related write vrel_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500679 pack .tf.lbar.relm -side left -fill y
Paul Mackerras908c3582006-05-20 09:38:11 +1000680
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500681 # Finish putting the upper half of the viewer together
682 pack .tf.lbar -in .tf -side bottom -fill x
683 pack .tf.bar -in .tf -side bottom -fill x
684 pack .tf.histframe -fill both -side top -expand 1
685 .ctop add .tf
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500686 .ctop paneconfigure .tf -height $geometry(topheight)
687 .ctop paneconfigure .tf -width $geometry(topwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500688
689 # now build up the bottom
690 panedwindow .pwbottom -orient horizontal
691
692 # lower left, a text box over search bar, scroll bar to the right
693 # if we know window height, then that will set the lower text height, otherwise
694 # we set lower text height which will drive window height
695 if {[info exists geometry(main)]} {
696 frame .bleft -width $geometry(botwidth)
697 } else {
698 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
699 }
700 frame .bleft.top
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000701 frame .bleft.mid
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500702
703 button .bleft.top.search -text "Search" -command dosearch \
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000704 -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500705 pack .bleft.top.search -side left -padx 5
706 set sstring .bleft.top.sstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000707 entry $sstring -width 20 -font $textfont -textvariable searchstring
708 lappend entries $sstring
709 trace add variable searchstring write incrsearch
710 pack $sstring -side left -expand 1 -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000711 radiobutton .bleft.mid.diff -text "Diff" \
712 -command changediffdisp -variable diffelide -value {0 0}
713 radiobutton .bleft.mid.old -text "Old version" \
714 -command changediffdisp -variable diffelide -value {0 1}
715 radiobutton .bleft.mid.new -text "New version" \
716 -command changediffdisp -variable diffelide -value {1 0}
717 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500718 set ctext .bleft.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000719 text $ctext -background $bgcolor -foreground $fgcolor \
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400720 -tabs "[expr {$tabstop * $charspc}]" \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000721 -state disabled -font $textfont \
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000722 -yscrollcommand scrolltext -wrap none
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500723 scrollbar .bleft.sb -command "$ctext yview"
724 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000725 pack .bleft.mid -side top -fill x
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500726 pack .bleft.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000727 pack $ctext -side left -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000728 lappend bglist $ctext
729 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000730
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400731 $ctext tag conf comment -wrap $wrapcomment
Paul Mackerrasf0654862005-07-18 14:29:03 -0400732 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000733 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
734 $ctext tag conf d0 -fore [lindex $diffcolors 0]
735 $ctext tag conf d1 -fore [lindex $diffcolors 1]
Paul Mackerras712fcc02005-11-30 09:28:16 +1100736 $ctext tag conf m0 -fore red
737 $ctext tag conf m1 -fore blue
738 $ctext tag conf m2 -fore green
739 $ctext tag conf m3 -fore purple
740 $ctext tag conf m4 -fore brown
Paul Mackerrasb77b0272006-02-07 09:13:52 +1100741 $ctext tag conf m5 -fore "#009090"
742 $ctext tag conf m6 -fore magenta
743 $ctext tag conf m7 -fore "#808000"
744 $ctext tag conf m8 -fore "#009000"
745 $ctext tag conf m9 -fore "#ff0080"
746 $ctext tag conf m10 -fore cyan
747 $ctext tag conf m11 -fore "#b07070"
748 $ctext tag conf m12 -fore "#70b0f0"
749 $ctext tag conf m13 -fore "#70f0b0"
750 $ctext tag conf m14 -fore "#f0b070"
751 $ctext tag conf m15 -fore "#ff70b0"
Paul Mackerras712fcc02005-11-30 09:28:16 +1100752 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +1100753 set mergemax 16
Paul Mackerras712fcc02005-11-30 09:28:16 +1100754 $ctext tag conf mresult -font [concat $textfont bold]
755 $ctext tag conf msep -font [concat $textfont bold]
756 $ctext tag conf found -back yellow
Paul Mackerrase5c2d852005-05-11 23:44:54 +0000757
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500758 .pwbottom add .bleft
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500759 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500760
761 # lower right
762 frame .bright
763 frame .bright.mode
764 radiobutton .bright.mode.patch -text "Patch" \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000765 -command reselectline -variable cmitmode -value "patch"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +0400766 .bright.mode.patch configure -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500767 radiobutton .bright.mode.tree -text "Tree" \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000768 -command reselectline -variable cmitmode -value "tree"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +0400769 .bright.mode.tree configure -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500770 grid .bright.mode.patch .bright.mode.tree -sticky ew
771 pack .bright.mode -side top -fill x
772 set cflist .bright.cfiles
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000773 set indent [font measure $mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500774 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -0400775 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000776 -background $bgcolor -foreground $fgcolor \
777 -font $mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000778 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500779 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000780 -cursor [. cget -cursor] \
781 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000782 lappend bglist $cflist
783 lappend fglist $cflist
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500784 scrollbar .bright.sb -command "$cflist yview"
785 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000786 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +1000787 $cflist tag configure highlight \
788 -background [$cflist cget -selectbackground]
Paul Mackerras63b79192006-05-20 21:31:52 +1000789 $cflist tag configure bold -font [concat $mainfont bold]
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000790
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500791 .pwbottom add .bright
792 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +0000793
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500794 # restore window position if known
795 if {[info exists geometry(main)]} {
796 wm geometry . "$geometry(main)"
797 }
798
799 bind .pwbottom <Configure> {resizecdetpanes %W %w}
800 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +1000801 bindall <1> {selcanvline %W %x %y}
802 #bindall <B1-Motion> {selcanvline %W %x %y}
Paul Mackerrascfb45632005-05-31 12:14:42 +0000803 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
804 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Paul Mackerrasbe0cd092006-03-31 09:55:11 +1100805 bindall <2> "canvscan mark %W %x %y"
806 bindall <B2-Motion> "canvscan dragto %W %x %y"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +1000807 bindkey <Home> selfirstline
808 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +0000809 bind . <Key-Up> "selnextline -1"
810 bind . <Key-Down> "selnextline 1"
Paul Mackerras4e7d6772006-05-30 21:33:07 +1000811 bind . <Shift-Key-Up> "next_highlight -1"
812 bind . <Shift-Key-Down> "next_highlight 1"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +1000813 bindkey <Key-Right> "goforw"
814 bindkey <Key-Left> "goback"
815 bind . <Key-Prior> "selnextpage -1"
816 bind . <Key-Next> "selnextpage 1"
817 bind . <Control-Home> "allcanvs yview moveto 0.0"
818 bind . <Control-End> "allcanvs yview moveto 1.0"
819 bind . <Control-Key-Up> "allcanvs yview scroll -1 units"
820 bind . <Control-Key-Down> "allcanvs yview scroll 1 units"
821 bind . <Control-Key-Prior> "allcanvs yview scroll -1 pages"
822 bind . <Control-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +0000823 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
824 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
825 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000826 bindkey p "selnextline -1"
827 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +1000828 bindkey z "goback"
829 bindkey x "goforw"
830 bindkey i "selnextline -1"
831 bindkey k "selnextline 1"
832 bindkey j "goback"
833 bindkey l "goforw"
Paul Mackerrascfb45632005-05-31 12:14:42 +0000834 bindkey b "$ctext yview scroll -1 pages"
835 bindkey d "$ctext yview scroll 18 units"
836 bindkey u "$ctext yview scroll -18 units"
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400837 bindkey / {findnext 1}
838 bindkey <Key-Return> {findnext 0}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000839 bindkey ? findprev
Paul Mackerras39ad8572005-05-19 12:35:53 +0000840 bindkey f nextfile
Eric Wonge7a09192007-02-23 12:36:34 -0800841 bindkey <F5> updatecommits
Paul Mackerras1d10f362005-05-15 12:55:47 +0000842 bind . <Control-q> doquit
Paul Mackerras98f350e2005-05-15 05:56:51 +0000843 bind . <Control-f> dofind
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400844 bind . <Control-g> {findnext 0}
Paul Mackerras1902c272006-05-25 21:25:13 +1000845 bind . <Control-r> dosearchback
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000846 bind . <Control-s> dosearch
Paul Mackerras1d10f362005-05-15 12:55:47 +0000847 bind . <Control-equal> {incrfont 1}
848 bind . <Control-KP_Add> {incrfont 1}
849 bind . <Control-minus> {incrfont -1}
850 bind . <Control-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -0500851 wm protocol . WM_DELETE_WINDOW doquit
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000852 bind . <Button-1> "click %W"
Paul Mackerras17386062005-05-18 22:51:00 +0000853 bind $fstring <Key-Return> dofind
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000854 bind $sha1entry <Key-Return> gotocommit
Paul Mackerrasee3dc722005-06-25 16:37:13 +1000855 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000856 bind $cflist <1> {sel_flist %W %x %y; break}
857 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000858 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasea13cba2005-06-16 10:54:04 +0000859
860 set maincursor [. cget -cursor]
861 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +1000862 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +0000863
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +1000864 set rowctxmenu .rowctxmenu
865 menu $rowctxmenu -tearoff 0
866 $rowctxmenu add command -label "Diff this -> selected" \
867 -command {diffvssel 0}
868 $rowctxmenu add command -label "Diff selected -> this" \
869 -command {diffvssel 1}
Paul Mackerras74daedb2005-06-27 19:27:32 +1000870 $rowctxmenu add command -label "Make patch" -command mkpatch
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +1000871 $rowctxmenu add command -label "Create tag" -command mktag
Paul Mackerras4a2139f2005-06-29 09:47:48 +1000872 $rowctxmenu add command -label "Write commit to file" -command writecommit
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +1000873 $rowctxmenu add command -label "Create new branch" -command mkbranch
Paul Mackerrasca6d8f52006-08-06 21:08:05 +1000874 $rowctxmenu add command -label "Cherry-pick this commit" \
875 -command cherrypick
Paul Mackerras6fb735a2006-10-19 10:09:06 +1000876 $rowctxmenu add command -label "Reset HEAD branch to here" \
877 -command resethead
Paul Mackerras10299152006-08-02 09:52:01 +1000878
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000879 set fakerowmenu .fakerowmenu
880 menu $fakerowmenu -tearoff 0
881 $fakerowmenu add command -label "Diff this -> selected" \
882 -command {diffvssel 0}
883 $fakerowmenu add command -label "Diff selected -> this" \
884 -command {diffvssel 1}
885 $fakerowmenu add command -label "Make patch" -command mkpatch
886# $fakerowmenu add command -label "Commit" -command {mkcommit 0}
887# $fakerowmenu add command -label "Commit all" -command {mkcommit 1}
888# $fakerowmenu add command -label "Revert local changes" -command revertlocal
889
Paul Mackerras10299152006-08-02 09:52:01 +1000890 set headctxmenu .headctxmenu
891 menu $headctxmenu -tearoff 0
892 $headctxmenu add command -label "Check out this branch" \
893 -command cobranch
894 $headctxmenu add command -label "Remove this branch" \
895 -command rmbranch
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000896}
897
Paul Mackerrasbe0cd092006-03-31 09:55:11 +1100898# mouse-2 makes all windows scan vertically, but only the one
899# the cursor is in scans horizontally
900proc canvscan {op w x y} {
901 global canv canv2 canv3
902 foreach c [list $canv $canv2 $canv3] {
903 if {$c == $w} {
904 $c scan $op $x $y
905 } else {
906 $c scan $op 0 $y
907 }
908 }
909}
910
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100911proc scrollcanv {cscroll f0 f1} {
912 $cscroll set $f0 $f1
913 drawfrac $f0 $f1
Paul Mackerras908c3582006-05-20 09:38:11 +1000914 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100915}
916
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000917# when we make a key binding for the toplevel, make sure
918# it doesn't get triggered when that key is pressed in the
919# find string entry widget.
920proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000921 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000922 bind . $ev $script
923 set escript [bind Entry $ev]
924 if {$escript == {}} {
925 set escript [bind Entry <Key>]
926 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000927 foreach e $entries {
928 bind $e $ev "$escript; break"
929 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000930}
931
932# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000933# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000934proc click {w} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000935 global entries
936 foreach e $entries {
937 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000938 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000939 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000940}
941
942proc savestuff {w} {
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400943 global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +1100944 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000945 global maxwidth showneartags showlocalchanges
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000946 global viewname viewfiles viewargs viewperm nextviewnum
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400947 global cmitmode wrapcomment
Mark Levedahl60378c02007-05-20 12:12:48 -0400948 global colors bgcolor fgcolor diffcolors selectbgcolor
Paul Mackerras4ef17532005-07-27 22:16:51 -0500949
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000950 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000951 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000952 catch {
953 set f [open "~/.gitk-new" w]
Paul Mackerrasf0654862005-07-18 14:29:03 -0400954 puts $f [list set mainfont $mainfont]
955 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -0700956 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400957 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -0400958 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +1000959 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +1000960 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000961 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400962 puts $f [list set wrapcomment $wrapcomment]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +1000963 puts $f [list set showneartags $showneartags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000964 puts $f [list set showlocalchanges $showlocalchanges]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000965 puts $f [list set bgcolor $bgcolor]
966 puts $f [list set fgcolor $fgcolor]
967 puts $f [list set colors $colors]
968 puts $f [list set diffcolors $diffcolors]
Mark Levedahl60378c02007-05-20 12:12:48 -0400969 puts $f [list set selectbgcolor $selectbgcolor]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500970
Mark Levedahlb6047c52007-02-08 22:22:24 -0500971 puts $f "set geometry(main) [wm geometry .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500972 puts $f "set geometry(topwidth) [winfo width .tf]"
973 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500974 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
975 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500976 puts $f "set geometry(botwidth) [winfo width .bleft]"
977 puts $f "set geometry(botheight) [winfo height .bleft]"
978
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000979 puts -nonewline $f "set permviews {"
980 for {set v 0} {$v < $nextviewnum} {incr v} {
981 if {$viewperm($v)} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000982 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000983 }
984 }
985 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000986 close $f
987 file rename -force "~/.gitk-new" "~/.gitk"
988 }
989 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +0000990}
991
Paul Mackerras43bddeb2005-05-15 23:19:18 +0000992proc resizeclistpanes {win w} {
993 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +1100994 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +0000995 set s0 [$win sash coord 0]
996 set s1 [$win sash coord 1]
997 if {$w < 60} {
998 set sash0 [expr {int($w/2 - 2)}]
999 set sash1 [expr {int($w*5/6 - 2)}]
1000 } else {
1001 set factor [expr {1.0 * $w / $oldwidth($win)}]
1002 set sash0 [expr {int($factor * [lindex $s0 0])}]
1003 set sash1 [expr {int($factor * [lindex $s1 0])}]
1004 if {$sash0 < 30} {
1005 set sash0 30
1006 }
1007 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001008 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001009 }
1010 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001011 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001012 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001013 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001014 }
1015 }
1016 }
1017 $win sash place 0 $sash0 [lindex $s0 1]
1018 $win sash place 1 $sash1 [lindex $s1 1]
1019 }
1020 set oldwidth($win) $w
1021}
1022
1023proc resizecdetpanes {win w} {
1024 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11001025 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001026 set s0 [$win sash coord 0]
1027 if {$w < 60} {
1028 set sash0 [expr {int($w*3/4 - 2)}]
1029 } else {
1030 set factor [expr {1.0 * $w / $oldwidth($win)}]
1031 set sash0 [expr {int($factor * [lindex $s0 0])}]
1032 if {$sash0 < 45} {
1033 set sash0 45
1034 }
1035 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001036 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001037 }
1038 }
1039 $win sash place 0 $sash0 [lindex $s0 1]
1040 }
1041 set oldwidth($win) $w
1042}
1043
Paul Mackerrasb5721c72005-05-10 12:08:22 +00001044proc allcanvs args {
1045 global canv canv2 canv3
1046 eval $canv $args
1047 eval $canv2 $args
1048 eval $canv3 $args
1049}
1050
1051proc bindall {event action} {
1052 global canv canv2 canv3
1053 bind $canv $event $action
1054 bind $canv2 $event $action
1055 bind $canv3 $event $action
1056}
1057
Paul Mackerras9a40c502005-05-12 23:46:16 +00001058proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001059 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00001060 set w .about
1061 if {[winfo exists $w]} {
1062 raise $w
1063 return
1064 }
1065 toplevel $w
1066 wm title $w "About gitk"
1067 message $w.m -text {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001068Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00001069
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001070Copyright © 2005-2006 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00001071
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10001072Use and redistribute under the terms of the GNU General Public License} \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001073 -justify center -aspect 400 -border 2 -bg white -relief groove
1074 pack $w.m -side top -fill x -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001075 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001076 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00001077 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001078 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001079 bind $w <Visibility> "focus $w.ok"
1080 bind $w <Key-Escape> "destroy $w"
1081 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00001082}
1083
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001084proc keys {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001085 global uifont
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001086 set w .keys
1087 if {[winfo exists $w]} {
1088 raise $w
1089 return
1090 }
1091 toplevel $w
1092 wm title $w "Gitk key bindings"
1093 message $w.m -text {
1094Gitk key bindings:
1095
1096<Ctrl-Q> Quit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001097<Home> Move to first commit
1098<End> Move to last commit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001099<Up>, p, i Move up one commit
1100<Down>, n, k Move down one commit
1101<Left>, z, j Go back in history list
1102<Right>, x, l Go forward in history list
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001103<PageUp> Move up one page in commit list
1104<PageDown> Move down one page in commit list
1105<Ctrl-Home> Scroll to top of commit list
1106<Ctrl-End> Scroll to bottom of commit list
1107<Ctrl-Up> Scroll commit list up one line
1108<Ctrl-Down> Scroll commit list down one line
1109<Ctrl-PageUp> Scroll commit list up one page
1110<Ctrl-PageDown> Scroll commit list down one page
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001111<Shift-Up> Move to previous highlighted line
1112<Shift-Down> Move to next highlighted line
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001113<Delete>, b Scroll diff view up one page
1114<Backspace> Scroll diff view up one page
1115<Space> Scroll diff view down one page
1116u Scroll diff view up 18 lines
1117d Scroll diff view down 18 lines
1118<Ctrl-F> Find
1119<Ctrl-G> Move to next find hit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001120<Return> Move to next find hit
1121/ Move to next find hit, or redo find
1122? Move to previous find hit
1123f Scroll diff view to next file
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001124<Ctrl-S> Search for next hit in diff view
1125<Ctrl-R> Search for previous hit in diff view
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001126<Ctrl-KP+> Increase font size
1127<Ctrl-plus> Increase font size
1128<Ctrl-KP-> Decrease font size
1129<Ctrl-minus> Decrease font size
Eric Wonge7a09192007-02-23 12:36:34 -08001130<F5> Update
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001131} \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001132 -justify left -bg white -border 2 -relief groove
1133 pack $w.m -side top -fill both -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001134 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001135 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001136 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001137 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001138 bind $w <Visibility> "focus $w.ok"
1139 bind $w <Key-Escape> "destroy $w"
1140 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001141}
1142
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001143# Procedures for manipulating the file list window at the
1144# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001145
1146proc treeview {w l openlevs} {
1147 global treecontents treediropen treeheight treeparent treeindex
1148
1149 set ix 0
1150 set treeindex() 0
1151 set lev 0
1152 set prefix {}
1153 set prefixend -1
1154 set prefendstack {}
1155 set htstack {}
1156 set ht 0
1157 set treecontents() {}
1158 $w conf -state normal
1159 foreach f $l {
1160 while {[string range $f 0 $prefixend] ne $prefix} {
1161 if {$lev <= $openlevs} {
1162 $w mark set e:$treeindex($prefix) "end -1c"
1163 $w mark gravity e:$treeindex($prefix) left
1164 }
1165 set treeheight($prefix) $ht
1166 incr ht [lindex $htstack end]
1167 set htstack [lreplace $htstack end end]
1168 set prefixend [lindex $prefendstack end]
1169 set prefendstack [lreplace $prefendstack end end]
1170 set prefix [string range $prefix 0 $prefixend]
1171 incr lev -1
1172 }
1173 set tail [string range $f [expr {$prefixend+1}] end]
1174 while {[set slash [string first "/" $tail]] >= 0} {
1175 lappend htstack $ht
1176 set ht 0
1177 lappend prefendstack $prefixend
1178 incr prefixend [expr {$slash + 1}]
1179 set d [string range $tail 0 $slash]
1180 lappend treecontents($prefix) $d
1181 set oldprefix $prefix
1182 append prefix $d
1183 set treecontents($prefix) {}
1184 set treeindex($prefix) [incr ix]
1185 set treeparent($prefix) $oldprefix
1186 set tail [string range $tail [expr {$slash+1}] end]
1187 if {$lev <= $openlevs} {
1188 set ht 1
1189 set treediropen($prefix) [expr {$lev < $openlevs}]
1190 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
1191 $w mark set d:$ix "end -1c"
1192 $w mark gravity d:$ix left
1193 set str "\n"
1194 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1195 $w insert end $str
1196 $w image create end -align center -image $bm -padx 1 \
1197 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10001198 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001199 $w mark set s:$ix "end -1c"
1200 $w mark gravity s:$ix left
1201 }
1202 incr lev
1203 }
1204 if {$tail ne {}} {
1205 if {$lev <= $openlevs} {
1206 incr ht
1207 set str "\n"
1208 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1209 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001210 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001211 }
1212 lappend treecontents($prefix) $tail
1213 }
1214 }
1215 while {$htstack ne {}} {
1216 set treeheight($prefix) $ht
1217 incr ht [lindex $htstack end]
1218 set htstack [lreplace $htstack end end]
1219 }
1220 $w conf -state disabled
1221}
1222
1223proc linetoelt {l} {
1224 global treeheight treecontents
1225
1226 set y 2
1227 set prefix {}
1228 while {1} {
1229 foreach e $treecontents($prefix) {
1230 if {$y == $l} {
1231 return "$prefix$e"
1232 }
1233 set n 1
1234 if {[string index $e end] eq "/"} {
1235 set n $treeheight($prefix$e)
1236 if {$y + $n > $l} {
1237 append prefix $e
1238 incr y
1239 break
1240 }
1241 }
1242 incr y $n
1243 }
1244 }
1245}
1246
Paul Mackerras45a9d502006-05-20 22:56:27 +10001247proc highlight_tree {y prefix} {
1248 global treeheight treecontents cflist
1249
1250 foreach e $treecontents($prefix) {
1251 set path $prefix$e
1252 if {[highlight_tag $path] ne {}} {
1253 $cflist tag add bold $y.0 "$y.0 lineend"
1254 }
1255 incr y
1256 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
1257 set y [highlight_tree $y $path]
1258 }
1259 }
1260 return $y
1261}
1262
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001263proc treeclosedir {w dir} {
1264 global treediropen treeheight treeparent treeindex
1265
1266 set ix $treeindex($dir)
1267 $w conf -state normal
1268 $w delete s:$ix e:$ix
1269 set treediropen($dir) 0
1270 $w image configure a:$ix -image tri-rt
1271 $w conf -state disabled
1272 set n [expr {1 - $treeheight($dir)}]
1273 while {$dir ne {}} {
1274 incr treeheight($dir) $n
1275 set dir $treeparent($dir)
1276 }
1277}
1278
1279proc treeopendir {w dir} {
1280 global treediropen treeheight treeparent treecontents treeindex
1281
1282 set ix $treeindex($dir)
1283 $w conf -state normal
1284 $w image configure a:$ix -image tri-dn
1285 $w mark set e:$ix s:$ix
1286 $w mark gravity e:$ix right
1287 set lev 0
1288 set str "\n"
1289 set n [llength $treecontents($dir)]
1290 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
1291 incr lev
1292 append str "\t"
1293 incr treeheight($x) $n
1294 }
1295 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001296 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001297 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001298 set iy $treeindex($de)
1299 $w mark set d:$iy e:$ix
1300 $w mark gravity d:$iy left
1301 $w insert e:$ix $str
1302 set treediropen($de) 0
1303 $w image create e:$ix -align center -image tri-rt -padx 1 \
1304 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10001305 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001306 $w mark set s:$iy e:$ix
1307 $w mark gravity s:$iy left
1308 set treeheight($de) 1
1309 } else {
1310 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001311 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001312 }
1313 }
1314 $w mark gravity e:$ix left
1315 $w conf -state disabled
1316 set treediropen($dir) 1
1317 set top [lindex [split [$w index @0,0] .] 0]
1318 set ht [$w cget -height]
1319 set l [lindex [split [$w index s:$ix] .] 0]
1320 if {$l < $top} {
1321 $w yview $l.0
1322 } elseif {$l + $n + 1 > $top + $ht} {
1323 set top [expr {$l + $n + 2 - $ht}]
1324 if {$l < $top} {
1325 set top $l
1326 }
1327 $w yview $top.0
1328 }
1329}
1330
1331proc treeclick {w x y} {
1332 global treediropen cmitmode ctext cflist cflist_top
1333
1334 if {$cmitmode ne "tree"} return
1335 if {![info exists cflist_top]} return
1336 set l [lindex [split [$w index "@$x,$y"] "."] 0]
1337 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1338 $cflist tag add highlight $l.0 "$l.0 lineend"
1339 set cflist_top $l
1340 if {$l == 1} {
1341 $ctext yview 1.0
1342 return
1343 }
1344 set e [linetoelt $l]
1345 if {[string index $e end] ne "/"} {
1346 showfile $e
1347 } elseif {$treediropen($e)} {
1348 treeclosedir $w $e
1349 } else {
1350 treeopendir $w $e
1351 }
1352}
1353
1354proc setfilelist {id} {
1355 global treefilelist cflist
1356
1357 treeview $cflist $treefilelist($id) 0
1358}
1359
1360image create bitmap tri-rt -background black -foreground blue -data {
1361 #define tri-rt_width 13
1362 #define tri-rt_height 13
1363 static unsigned char tri-rt_bits[] = {
1364 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
1365 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
1366 0x00, 0x00};
1367} -maskdata {
1368 #define tri-rt-mask_width 13
1369 #define tri-rt-mask_height 13
1370 static unsigned char tri-rt-mask_bits[] = {
1371 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
1372 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
1373 0x08, 0x00};
1374}
1375image create bitmap tri-dn -background black -foreground blue -data {
1376 #define tri-dn_width 13
1377 #define tri-dn_height 13
1378 static unsigned char tri-dn_bits[] = {
1379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
1380 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x00, 0x00};
1382} -maskdata {
1383 #define tri-dn-mask_width 13
1384 #define tri-dn-mask_height 13
1385 static unsigned char tri-dn-mask_bits[] = {
1386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
1387 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
1388 0x00, 0x00};
1389}
1390
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001391proc init_flist {first} {
Paul Mackerras89b11d32006-05-02 19:55:31 +10001392 global cflist cflist_top selectedline difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001393
1394 $cflist conf -state normal
1395 $cflist delete 0.0 end
1396 if {$first ne {}} {
1397 $cflist insert end $first
1398 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001399 $cflist tag add highlight 1.0 "1.0 lineend"
1400 } else {
1401 catch {unset cflist_top}
1402 }
1403 $cflist conf -state disabled
1404 set difffilestart {}
1405}
1406
Paul Mackerras63b79192006-05-20 21:31:52 +10001407proc highlight_tag {f} {
1408 global highlight_paths
1409
1410 foreach p $highlight_paths {
1411 if {[string match $p $f]} {
1412 return "bold"
1413 }
1414 }
1415 return {}
1416}
1417
1418proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001419 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001420
Paul Mackerras45a9d502006-05-20 22:56:27 +10001421 $cflist conf -state normal
1422 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10001423 set end [lindex [split [$cflist index end] .] 0]
1424 for {set l 2} {$l < $end} {incr l} {
1425 set line [$cflist get $l.0 "$l.0 lineend"]
1426 if {[highlight_tag $line] ne {}} {
1427 $cflist tag add bold $l.0 "$l.0 lineend"
1428 }
1429 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001430 } else {
1431 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10001432 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001433 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001434}
1435
1436proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001437 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001438
Paul Mackerras45a9d502006-05-20 22:56:27 +10001439 $cflist conf -state normal
1440 $cflist tag remove bold 1.0 end
1441 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001442}
1443
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001444proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001445 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001446
Paul Mackerras45a9d502006-05-20 22:56:27 +10001447 $cflist conf -state normal
1448 foreach f $fl {
1449 $cflist insert end "\n"
1450 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001451 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001452 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001453}
1454
1455proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001456 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001457
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001458 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001459 if {![info exists cflist_top]} return
1460 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10001461 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1462 $cflist tag add highlight $l.0 "$l.0 lineend"
1463 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001464 if {$l == 1} {
1465 $ctext yview 1.0
1466 } else {
1467 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001468 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001469}
1470
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001471# Functions for adding and removing shell-type quoting
1472
1473proc shellquote {str} {
1474 if {![string match "*\['\"\\ \t]*" $str]} {
1475 return $str
1476 }
1477 if {![string match "*\['\"\\]*" $str]} {
1478 return "\"$str\""
1479 }
1480 if {![string match "*'*" $str]} {
1481 return "'$str'"
1482 }
1483 return "\"[string map {\" \\\" \\ \\\\} $str]\""
1484}
1485
1486proc shellarglist {l} {
1487 set str {}
1488 foreach a $l {
1489 if {$str ne {}} {
1490 append str " "
1491 }
1492 append str [shellquote $a]
1493 }
1494 return $str
1495}
1496
1497proc shelldequote {str} {
1498 set ret {}
1499 set used -1
1500 while {1} {
1501 incr used
1502 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
1503 append ret [string range $str $used end]
1504 set used [string length $str]
1505 break
1506 }
1507 set first [lindex $first 0]
1508 set ch [string index $str $first]
1509 if {$first > $used} {
1510 append ret [string range $str $used [expr {$first - 1}]]
1511 set used $first
1512 }
1513 if {$ch eq " " || $ch eq "\t"} break
1514 incr used
1515 if {$ch eq "'"} {
1516 set first [string first "'" $str $used]
1517 if {$first < 0} {
1518 error "unmatched single-quote"
1519 }
1520 append ret [string range $str $used [expr {$first - 1}]]
1521 set used $first
1522 continue
1523 }
1524 if {$ch eq "\\"} {
1525 if {$used >= [string length $str]} {
1526 error "trailing backslash"
1527 }
1528 append ret [string index $str $used]
1529 continue
1530 }
1531 # here ch == "\""
1532 while {1} {
1533 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
1534 error "unmatched double-quote"
1535 }
1536 set first [lindex $first 0]
1537 set ch [string index $str $first]
1538 if {$first > $used} {
1539 append ret [string range $str $used [expr {$first - 1}]]
1540 set used $first
1541 }
1542 if {$ch eq "\""} break
1543 incr used
1544 append ret [string index $str $used]
1545 incr used
1546 }
1547 }
1548 return [list $used $ret]
1549}
1550
1551proc shellsplit {str} {
1552 set l {}
1553 while {1} {
1554 set str [string trimleft $str]
1555 if {$str eq {}} break
1556 set dq [shelldequote $str]
1557 set n [lindex $dq 0]
1558 set word [lindex $dq 1]
1559 set str [string range $str $n end]
1560 lappend l $word
1561 }
1562 return $l
1563}
1564
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001565# Code to implement multiple views
1566
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001567proc newview {ishighlight} {
1568 global nextviewnum newviewname newviewperm uifont newishighlight
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001569 global newviewargs revtreeargs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001570
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001571 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001572 set top .gitkview
1573 if {[winfo exists $top]} {
1574 raise $top
1575 return
1576 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001577 set newviewname($nextviewnum) "View $nextviewnum"
1578 set newviewperm($nextviewnum) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001579 set newviewargs($nextviewnum) [shellarglist $revtreeargs]
Mark Levedahl40b87ff2007-02-01 08:44:46 -05001580 vieweditor $top $nextviewnum "Gitk view definition"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001581}
1582
1583proc editview {} {
1584 global curview
1585 global viewname viewperm newviewname newviewperm
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001586 global viewargs newviewargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001587
1588 set top .gitkvedit-$curview
1589 if {[winfo exists $top]} {
1590 raise $top
1591 return
1592 }
1593 set newviewname($curview) $viewname($curview)
1594 set newviewperm($curview) $viewperm($curview)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001595 set newviewargs($curview) [shellarglist $viewargs($curview)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001596 vieweditor $top $curview "Gitk: edit view $viewname($curview)"
1597}
1598
1599proc vieweditor {top n title} {
1600 global newviewname newviewperm viewfiles
1601 global uifont
1602
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001603 toplevel $top
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001604 wm title $top $title
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001605 label $top.nl -text "Name" -font $uifont
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001606 entry $top.name -width 20 -textvariable newviewname($n) -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001607 grid $top.nl $top.name -sticky w -pady 5
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001608 checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) \
1609 -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001610 grid $top.perm - -pady 5 -sticky w
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001611 message $top.al -aspect 1000 -font $uifont \
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001612 -text "Commits to include (arguments to git rev-list):"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001613 grid $top.al - -sticky w -pady 5
1614 entry $top.args -width 50 -textvariable newviewargs($n) \
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001615 -background white -font $uifont
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001616 grid $top.args - -sticky ew -padx 5
1617 message $top.l -aspect 1000 -font $uifont \
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001618 -text "Enter files and directories to include, one per line:"
1619 grid $top.l - -sticky w
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001620 text $top.t -width 40 -height 10 -background white -font $uifont
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001621 if {[info exists viewfiles($n)]} {
1622 foreach f $viewfiles($n) {
1623 $top.t insert end $f
1624 $top.t insert end "\n"
1625 }
1626 $top.t delete {end - 1c} end
1627 $top.t mark set insert 0.0
1628 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001629 grid $top.t - -sticky ew -padx 5
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001630 frame $top.buts
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001631 button $top.buts.ok -text "OK" -command [list newviewok $top $n] \
1632 -font $uifont
1633 button $top.buts.can -text "Cancel" -command [list destroy $top] \
1634 -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001635 grid $top.buts.ok $top.buts.can
1636 grid columnconfigure $top.buts 0 -weight 1 -uniform a
1637 grid columnconfigure $top.buts 1 -weight 1 -uniform a
1638 grid $top.buts - -pady 10 -sticky ew
1639 focus $top.t
1640}
1641
Paul Mackerras908c3582006-05-20 09:38:11 +10001642proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001643 set nmenu [$m index end]
1644 for {set i $first} {$i <= $nmenu} {incr i} {
1645 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001646 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001647 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001648 }
1649 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001650}
1651
1652proc allviewmenus {n op args} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001653 global viewhlmenu
1654
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001655 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras908c3582006-05-20 09:38:11 +10001656 doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001657}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001658
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001659proc newviewok {top n} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001660 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001661 global viewname viewfiles viewperm selectedview curview
Paul Mackerras908c3582006-05-20 09:38:11 +10001662 global viewargs newviewargs viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001663
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001664 if {[catch {
1665 set newargs [shellsplit $newviewargs($n)]
1666 } err]} {
1667 error_popup "Error in commit selection arguments: $err"
1668 wm raise $top
1669 focus $top
1670 return
1671 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001672 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001673 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001674 set ft [string trim $f]
1675 if {$ft ne {}} {
1676 lappend files $ft
1677 }
1678 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001679 if {![info exists viewfiles($n)]} {
1680 # creating a new view
1681 incr nextviewnum
1682 set viewname($n) $newviewname($n)
1683 set viewperm($n) $newviewperm($n)
1684 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001685 set viewargs($n) $newargs
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001686 addviewmenu $n
1687 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001688 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001689 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001690 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001691 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001692 } else {
1693 # editing an existing view
1694 set viewperm($n) $newviewperm($n)
1695 if {$newviewname($n) ne $viewname($n)} {
1696 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001697 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10001698 entryconf [list -label $viewname($n)]
1699 doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
1700 entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001701 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001702 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001703 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001704 set viewargs($n) $newargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001705 if {$curview == $n} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001706 run updatecommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001707 }
1708 }
1709 }
1710 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001711}
1712
1713proc delview {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001714 global curview viewdata viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001715
1716 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10001717 if {[info exists hlview] && $hlview == $curview} {
1718 set selectedhlview None
1719 unset hlview
1720 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001721 allviewmenus $curview delete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001722 set viewdata($curview) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001723 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001724 showview 0
1725}
1726
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001727proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001728 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001729
1730 .bar.view add radiobutton -label $viewname($n) \
1731 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras908c3582006-05-20 09:38:11 +10001732 $viewhlmenu add radiobutton -label $viewname($n) \
1733 -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001734}
1735
Paul Mackerras22626ef2006-04-17 09:56:02 +10001736proc flatten {var} {
1737 global $var
1738
1739 set ret {}
1740 foreach i [array names $var] {
1741 lappend ret $i [set $var\($i\)]
1742 }
1743 return $ret
1744}
1745
1746proc unflatten {var l} {
1747 global $var
1748
1749 catch {unset $var}
1750 foreach {i v} $l {
1751 set $var\($i\) $v
1752 }
1753}
1754
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001755proc showview {n} {
1756 global curview viewdata viewfiles
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001757 global displayorder parentlist rowidlist rowoffsets
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001758 global colormap rowtextx commitrow nextcolor canvxmax
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001759 global numcommits rowrangelist commitlisted idrowranges rowchk
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001760 global selectedline currentid canv canvy0
1761 global matchinglines treediffs
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001762 global pending_select phase
Paul Mackerras322a8cc2006-10-15 18:03:46 +10001763 global commitidx rowlaidout rowoptim
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001764 global commfd
Paul Mackerrase507fd42007-06-16 21:51:08 +10001765 global selectedview selectfirst
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001766 global vparentlist vdisporder vcmitlisted
Paul Mackerras908c3582006-05-20 09:38:11 +10001767 global hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001768
1769 if {$n == $curview} return
1770 set selid {}
1771 if {[info exists selectedline]} {
1772 set selid $currentid
1773 set y [yc $selectedline]
1774 set ymax [lindex [$canv cget -scrollregion] 3]
1775 set span [$canv yview]
1776 set ytop [expr {[lindex $span 0] * $ymax}]
1777 set ybot [expr {[lindex $span 1] * $ymax}]
1778 if {$ytop < $y && $y < $ybot} {
1779 set yscreen [expr {$y - $ytop}]
1780 } else {
1781 set yscreen [expr {($ybot - $ytop) / 2}]
1782 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10001783 } elseif {[info exists pending_select]} {
1784 set selid $pending_select
1785 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001786 }
1787 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10001788 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001789 stopfindproc
Paul Mackerras22626ef2006-04-17 09:56:02 +10001790 if {$curview >= 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001791 set vparentlist($curview) $parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001792 set vdisporder($curview) $displayorder
1793 set vcmitlisted($curview) $commitlisted
Paul Mackerras22626ef2006-04-17 09:56:02 +10001794 if {$phase ne {}} {
1795 set viewdata($curview) \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001796 [list $phase $rowidlist $rowoffsets $rowrangelist \
1797 [flatten idrowranges] [flatten idinlist] \
Paul Mackerras322a8cc2006-10-15 18:03:46 +10001798 $rowlaidout $rowoptim $numcommits]
Paul Mackerras2516dae2006-04-21 10:35:31 +10001799 } elseif {![info exists viewdata($curview)]
1800 || [lindex $viewdata($curview) 0] ne {}} {
Paul Mackerras22626ef2006-04-17 09:56:02 +10001801 set viewdata($curview) \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001802 [list {} $rowidlist $rowoffsets $rowrangelist]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001803 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001804 }
1805 catch {unset matchinglines}
1806 catch {unset treediffs}
1807 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10001808 if {[info exists hlview] && $hlview == $n} {
1809 unset hlview
1810 set selectedhlview None
1811 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001812
1813 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001814 set selectedview $n
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001815 .bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}]
1816 .bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001817
1818 if {![info exists viewdata($n)]} {
Paul Mackerrase507fd42007-06-16 21:51:08 +10001819 if {$selid ne {}} {
1820 set pending_select $selid
1821 }
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10001822 getcommits
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001823 return
1824 }
1825
Paul Mackerras22626ef2006-04-17 09:56:02 +10001826 set v $viewdata($n)
1827 set phase [lindex $v 0]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001828 set displayorder $vdisporder($n)
1829 set parentlist $vparentlist($n)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001830 set commitlisted $vcmitlisted($n)
1831 set rowidlist [lindex $v 1]
1832 set rowoffsets [lindex $v 2]
1833 set rowrangelist [lindex $v 3]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001834 if {$phase eq {}} {
1835 set numcommits [llength $displayorder]
1836 catch {unset idrowranges}
Paul Mackerras22626ef2006-04-17 09:56:02 +10001837 } else {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001838 unflatten idrowranges [lindex $v 4]
1839 unflatten idinlist [lindex $v 5]
1840 set rowlaidout [lindex $v 6]
1841 set rowoptim [lindex $v 7]
1842 set numcommits [lindex $v 8]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001843 catch {unset rowchk}
Paul Mackerras22626ef2006-04-17 09:56:02 +10001844 }
1845
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001846 catch {unset colormap}
1847 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001848 set nextcolor 0
1849 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001850 set curview $n
1851 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001852 setcanvscroll
1853 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10001854 set row {}
1855 set selectfirst 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001856 if {$selid ne {} && [info exists commitrow($n,$selid)]} {
1857 set row $commitrow($n,$selid)
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001858 # try to get the selected row in the same position on the screen
1859 set ymax [lindex [$canv cget -scrollregion] 3]
1860 set ytop [expr {[yc $row] - $yscreen}]
1861 if {$ytop < 0} {
1862 set ytop 0
1863 }
1864 set yf [expr {$ytop * 1.0 / $ymax}]
1865 }
1866 allcanvs yview moveto $yf
1867 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10001868 if {$row ne {}} {
1869 selectline $row 0
1870 } elseif {$selid ne {}} {
1871 set pending_select $selid
1872 } else {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001873 set row [expr {[lindex $displayorder 0] eq $nullid}]
1874 if {$row < $numcommits} {
1875 selectline $row 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10001876 } else {
1877 set selectfirst 1
1878 }
1879 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001880 if {$phase ne {}} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001881 if {$phase eq "getcommits"} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001882 show_status "Reading commits..."
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001883 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001884 run chewcommits $n
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001885 } elseif {$numcommits == 0} {
1886 show_status "No commits selected"
Paul Mackerras2516dae2006-04-21 10:35:31 +10001887 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001888}
1889
Paul Mackerras908c3582006-05-20 09:38:11 +10001890# Stuff relating to the highlighting facility
1891
1892proc ishighlighted {row} {
Paul Mackerras164ff272006-05-29 19:50:02 +10001893 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10001894
1895 if {[info exists nhighlights($row)] && $nhighlights($row) > 0} {
1896 return $nhighlights($row)
1897 }
1898 if {[info exists vhighlights($row)] && $vhighlights($row) > 0} {
1899 return $vhighlights($row)
1900 }
1901 if {[info exists fhighlights($row)] && $fhighlights($row) > 0} {
1902 return $fhighlights($row)
1903 }
Paul Mackerras164ff272006-05-29 19:50:02 +10001904 if {[info exists rhighlights($row)] && $rhighlights($row) > 0} {
1905 return $rhighlights($row)
1906 }
Paul Mackerras908c3582006-05-20 09:38:11 +10001907 return 0
1908}
1909
1910proc bolden {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001911 global canv linehtag selectedline boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10001912
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001913 lappend boldrows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10001914 $canv itemconf $linehtag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10001915 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001916 $canv delete secsel
1917 set t [eval $canv create rect [$canv bbox $linehtag($row)] \
1918 -outline {{}} -tags secsel \
1919 -fill [$canv cget -selectbackground]]
1920 $canv lower $t
1921 }
1922}
1923
1924proc bolden_name {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001925 global canv2 linentag selectedline boldnamerows
Paul Mackerras908c3582006-05-20 09:38:11 +10001926
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001927 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10001928 $canv2 itemconf $linentag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10001929 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001930 $canv2 delete secsel
1931 set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
1932 -outline {{}} -tags secsel \
1933 -fill [$canv2 cget -selectbackground]]
1934 $canv2 lower $t
1935 }
1936}
1937
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001938proc unbolden {} {
1939 global mainfont boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10001940
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001941 set stillbold {}
1942 foreach row $boldrows {
Paul Mackerras908c3582006-05-20 09:38:11 +10001943 if {![ishighlighted $row]} {
1944 bolden $row $mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001945 } else {
1946 lappend stillbold $row
Paul Mackerras908c3582006-05-20 09:38:11 +10001947 }
1948 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001949 set boldrows $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10001950}
1951
1952proc addvhighlight {n} {
1953 global hlview curview viewdata vhl_done vhighlights commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001954
1955 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001956 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001957 }
1958 set hlview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001959 if {$n != $curview && ![info exists viewdata($n)]} {
1960 set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}]
1961 set vparentlist($n) {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001962 set vdisporder($n) {}
1963 set vcmitlisted($n) {}
1964 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10001965 }
1966 set vhl_done $commitidx($hlview)
1967 if {$vhl_done > 0} {
1968 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001969 }
1970}
1971
Paul Mackerras908c3582006-05-20 09:38:11 +10001972proc delvhighlight {} {
1973 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001974
1975 if {![info exists hlview]} return
1976 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001977 catch {unset vhighlights}
1978 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001979}
1980
Paul Mackerras908c3582006-05-20 09:38:11 +10001981proc vhighlightmore {} {
1982 global hlview vhl_done commitidx vhighlights
1983 global displayorder vdisporder curview mainfont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001984
1985 set font [concat $mainfont bold]
1986 set max $commitidx($hlview)
1987 if {$hlview == $curview} {
1988 set disp $displayorder
1989 } else {
1990 set disp $vdisporder($hlview)
1991 }
Paul Mackerras908c3582006-05-20 09:38:11 +10001992 set vr [visiblerows]
1993 set r0 [lindex $vr 0]
1994 set r1 [lindex $vr 1]
1995 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001996 set id [lindex $disp $i]
1997 if {[info exists commitrow($curview,$id)]} {
1998 set row $commitrow($curview,$id)
Paul Mackerras908c3582006-05-20 09:38:11 +10001999 if {$r0 <= $row && $row <= $r1} {
2000 if {![highlighted $row]} {
2001 bolden $row $font
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002002 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002003 set vhighlights($row) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002004 }
2005 }
2006 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002007 set vhl_done $max
2008}
2009
2010proc askvhighlight {row id} {
2011 global hlview vhighlights commitrow iddrawn mainfont
2012
2013 if {[info exists commitrow($hlview,$id)]} {
2014 if {[info exists iddrawn($id)] && ![ishighlighted $row]} {
2015 bolden $row [concat $mainfont bold]
2016 }
2017 set vhighlights($row) 1
2018 } else {
2019 set vhighlights($row) 0
2020 }
2021}
2022
2023proc hfiles_change {name ix op} {
2024 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras63b79192006-05-20 21:31:52 +10002025 global mainfont highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10002026
2027 if {[info exists filehighlight]} {
2028 # delete previous highlights
2029 catch {close $filehighlight}
2030 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002031 catch {unset fhighlights}
2032 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10002033 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10002034 }
Paul Mackerras63b79192006-05-20 21:31:52 +10002035 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002036 after cancel do_file_hl $fh_serial
2037 incr fh_serial
2038 if {$highlight_files ne {}} {
2039 after 300 do_file_hl $fh_serial
2040 }
2041}
2042
Paul Mackerras63b79192006-05-20 21:31:52 +10002043proc makepatterns {l} {
2044 set ret {}
2045 foreach e $l {
2046 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
2047 if {[string index $ee end] eq "/"} {
2048 lappend ret "$ee*"
2049 } else {
2050 lappend ret $ee
2051 lappend ret "$ee/*"
2052 }
2053 }
2054 return $ret
2055}
2056
Paul Mackerras908c3582006-05-20 09:38:11 +10002057proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002058 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002059
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002060 if {$gdttype eq "touching paths:"} {
2061 if {[catch {set paths [shellsplit $highlight_files]}]} return
2062 set highlight_paths [makepatterns $paths]
2063 highlight_filelist
2064 set gdtargs [concat -- $paths]
2065 } else {
2066 set gdtargs [list "-S$highlight_files"]
2067 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002068 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10002069 set filehighlight [open $cmd r+]
2070 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002071 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002072 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002073 drawvisible
2074 flushhighlights
2075}
2076
2077proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002078 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002079
2080 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002081 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002082 puts $filehighlight ""
2083 flush $filehighlight
2084 }
2085}
2086
2087proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002088 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002089
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002090 lappend fhl_list $id
2091 set fhighlights($row) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10002092 puts $filehighlight $id
2093}
2094
2095proc readfhighlight {} {
2096 global filehighlight fhighlights commitrow curview mainfont iddrawn
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002097 global fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002098
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002099 if {![info exists filehighlight]} {
2100 return 0
2101 }
2102 set nr 0
2103 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002104 set line [string trim $line]
2105 set i [lsearch -exact $fhl_list $line]
2106 if {$i < 0} continue
2107 for {set j 0} {$j < $i} {incr j} {
2108 set id [lindex $fhl_list $j]
2109 if {[info exists commitrow($curview,$id)]} {
2110 set fhighlights($commitrow($curview,$id)) 0
2111 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002112 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002113 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
2114 if {$line eq {}} continue
2115 if {![info exists commitrow($curview,$line)]} continue
2116 set row $commitrow($curview,$line)
2117 if {[info exists iddrawn($line)] && ![ishighlighted $row]} {
2118 bolden $row [concat $mainfont bold]
2119 }
2120 set fhighlights($row) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002121 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002122 if {[eof $filehighlight]} {
2123 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002124 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002125 catch {close $filehighlight}
2126 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002127 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10002128 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002129 next_hlcont
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002130 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002131}
2132
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002133proc find_change {name ix op} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002134 global nhighlights mainfont boldnamerows
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002135 global findstring findpattern findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10002136
2137 # delete previous highlights, if any
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002138 foreach row $boldnamerows {
2139 bolden_name $row $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10002140 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002141 set boldnamerows {}
2142 catch {unset nhighlights}
2143 unbolden
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002144 if {$findtype ne "Regexp"} {
2145 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
2146 $findstring]
2147 set findpattern "*$e*"
Paul Mackerras908c3582006-05-20 09:38:11 +10002148 }
2149 drawvisible
2150}
2151
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002152proc askfindhighlight {row id} {
2153 global nhighlights commitinfo iddrawn mainfont
2154 global findstring findtype findloc findpattern
Paul Mackerras908c3582006-05-20 09:38:11 +10002155
2156 if {![info exists commitinfo($id)]} {
2157 getcommit $id
2158 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002159 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10002160 set isbold 0
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002161 set fldtypes {Headline Author Date Committer CDate Comments}
2162 foreach f $info ty $fldtypes {
2163 if {$findloc ne "All fields" && $findloc ne $ty} {
2164 continue
Paul Mackerras908c3582006-05-20 09:38:11 +10002165 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002166 if {$findtype eq "Regexp"} {
2167 set doesmatch [regexp $findstring $f]
2168 } elseif {$findtype eq "IgnCase"} {
2169 set doesmatch [string match -nocase $findpattern $f]
2170 } else {
2171 set doesmatch [string match $findpattern $f]
2172 }
2173 if {$doesmatch} {
2174 if {$ty eq "Author"} {
2175 set isbold 2
2176 } else {
2177 set isbold 1
2178 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002179 }
2180 }
2181 if {[info exists iddrawn($id)]} {
2182 if {$isbold && ![ishighlighted $row]} {
2183 bolden $row [concat $mainfont bold]
2184 }
2185 if {$isbold >= 2} {
2186 bolden_name $row [concat $mainfont bold]
2187 }
2188 }
2189 set nhighlights($row) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002190}
2191
Paul Mackerras164ff272006-05-29 19:50:02 +10002192proc vrel_change {name ix op} {
2193 global highlight_related
2194
2195 rhighlight_none
2196 if {$highlight_related ne "None"} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002197 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002198 }
2199}
2200
2201# prepare for testing whether commits are descendents or ancestors of a
2202proc rhighlight_sel {a} {
2203 global descendent desc_todo ancestor anc_todo
2204 global highlight_related rhighlights
2205
2206 catch {unset descendent}
2207 set desc_todo [list $a]
2208 catch {unset ancestor}
2209 set anc_todo [list $a]
2210 if {$highlight_related ne "None"} {
2211 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002212 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002213 }
2214}
2215
2216proc rhighlight_none {} {
2217 global rhighlights
2218
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002219 catch {unset rhighlights}
2220 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10002221}
2222
2223proc is_descendent {a} {
2224 global curview children commitrow descendent desc_todo
2225
2226 set v $curview
2227 set la $commitrow($v,$a)
2228 set todo $desc_todo
2229 set leftover {}
2230 set done 0
2231 for {set i 0} {$i < [llength $todo]} {incr i} {
2232 set do [lindex $todo $i]
2233 if {$commitrow($v,$do) < $la} {
2234 lappend leftover $do
2235 continue
2236 }
2237 foreach nk $children($v,$do) {
2238 if {![info exists descendent($nk)]} {
2239 set descendent($nk) 1
2240 lappend todo $nk
2241 if {$nk eq $a} {
2242 set done 1
2243 }
2244 }
2245 }
2246 if {$done} {
2247 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2248 return
2249 }
2250 }
2251 set descendent($a) 0
2252 set desc_todo $leftover
2253}
2254
2255proc is_ancestor {a} {
2256 global curview parentlist commitrow ancestor anc_todo
2257
2258 set v $curview
2259 set la $commitrow($v,$a)
2260 set todo $anc_todo
2261 set leftover {}
2262 set done 0
2263 for {set i 0} {$i < [llength $todo]} {incr i} {
2264 set do [lindex $todo $i]
2265 if {![info exists commitrow($v,$do)] || $commitrow($v,$do) > $la} {
2266 lappend leftover $do
2267 continue
2268 }
2269 foreach np [lindex $parentlist $commitrow($v,$do)] {
2270 if {![info exists ancestor($np)]} {
2271 set ancestor($np) 1
2272 lappend todo $np
2273 if {$np eq $a} {
2274 set done 1
2275 }
2276 }
2277 }
2278 if {$done} {
2279 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2280 return
2281 }
2282 }
2283 set ancestor($a) 0
2284 set anc_todo $leftover
2285}
2286
2287proc askrelhighlight {row id} {
2288 global descendent highlight_related iddrawn mainfont rhighlights
2289 global selectedline ancestor
2290
2291 if {![info exists selectedline]} return
2292 set isbold 0
2293 if {$highlight_related eq "Descendent" ||
2294 $highlight_related eq "Not descendent"} {
2295 if {![info exists descendent($id)]} {
2296 is_descendent $id
2297 }
2298 if {$descendent($id) == ($highlight_related eq "Descendent")} {
2299 set isbold 1
2300 }
2301 } elseif {$highlight_related eq "Ancestor" ||
2302 $highlight_related eq "Not ancestor"} {
2303 if {![info exists ancestor($id)]} {
2304 is_ancestor $id
2305 }
2306 if {$ancestor($id) == ($highlight_related eq "Ancestor")} {
2307 set isbold 1
2308 }
2309 }
2310 if {[info exists iddrawn($id)]} {
2311 if {$isbold && ![ishighlighted $row]} {
2312 bolden $row [concat $mainfont bold]
2313 }
2314 }
2315 set rhighlights($row) $isbold
2316}
2317
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002318proc next_hlcont {} {
2319 global fhl_row fhl_dirn displayorder numcommits
2320 global vhighlights fhighlights nhighlights rhighlights
2321 global hlview filehighlight findstring highlight_related
2322
2323 if {![info exists fhl_dirn] || $fhl_dirn == 0} return
2324 set row $fhl_row
2325 while {1} {
2326 if {$row < 0 || $row >= $numcommits} {
2327 bell
2328 set fhl_dirn 0
2329 return
2330 }
2331 set id [lindex $displayorder $row]
2332 if {[info exists hlview]} {
2333 if {![info exists vhighlights($row)]} {
2334 askvhighlight $row $id
2335 }
2336 if {$vhighlights($row) > 0} break
2337 }
2338 if {$findstring ne {}} {
2339 if {![info exists nhighlights($row)]} {
2340 askfindhighlight $row $id
2341 }
2342 if {$nhighlights($row) > 0} break
2343 }
2344 if {$highlight_related ne "None"} {
2345 if {![info exists rhighlights($row)]} {
2346 askrelhighlight $row $id
2347 }
2348 if {$rhighlights($row) > 0} break
2349 }
2350 if {[info exists filehighlight]} {
2351 if {![info exists fhighlights($row)]} {
2352 # ask for a few more while we're at it...
2353 set r $row
2354 for {set n 0} {$n < 100} {incr n} {
2355 if {![info exists fhighlights($r)]} {
2356 askfilehighlight $r [lindex $displayorder $r]
2357 }
2358 incr r $fhl_dirn
2359 if {$r < 0 || $r >= $numcommits} break
2360 }
2361 flushhighlights
2362 }
2363 if {$fhighlights($row) < 0} {
2364 set fhl_row $row
2365 return
2366 }
2367 if {$fhighlights($row) > 0} break
2368 }
2369 incr row $fhl_dirn
2370 }
2371 set fhl_dirn 0
2372 selectline $row 1
2373}
2374
2375proc next_highlight {dirn} {
2376 global selectedline fhl_row fhl_dirn
2377 global hlview filehighlight findstring highlight_related
2378
2379 if {![info exists selectedline]} return
2380 if {!([info exists hlview] || $findstring ne {} ||
2381 $highlight_related ne "None" || [info exists filehighlight])} return
2382 set fhl_row [expr {$selectedline + $dirn}]
2383 set fhl_dirn $dirn
2384 next_hlcont
2385}
2386
2387proc cancel_next_highlight {} {
2388 global fhl_dirn
2389
2390 set fhl_dirn 0
2391}
2392
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002393# Graph layout functions
2394
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002395proc shortids {ids} {
2396 set res {}
2397 foreach id $ids {
2398 if {[llength $id] > 1} {
2399 lappend res [shortids $id]
2400 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
2401 lappend res [string range $id 0 7]
2402 } else {
2403 lappend res $id
2404 }
2405 }
2406 return $res
2407}
2408
2409proc incrange {l x o} {
2410 set n [llength $l]
2411 while {$x < $n} {
2412 set e [lindex $l $x]
2413 if {$e ne {}} {
2414 lset l $x [expr {$e + $o}]
2415 }
2416 incr x
2417 }
2418 return $l
2419}
2420
2421proc ntimes {n o} {
2422 set ret {}
2423 for {} {$n > 0} {incr n -1} {
2424 lappend ret $o
2425 }
2426 return $ret
2427}
2428
2429proc usedinrange {id l1 l2} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002430 global children commitrow curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002431
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002432 if {[info exists commitrow($curview,$id)]} {
2433 set r $commitrow($curview,$id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002434 if {$l1 <= $r && $r <= $l2} {
2435 return [expr {$r - $l1 + 1}]
2436 }
2437 }
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002438 set kids $children($curview,$id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002439 foreach c $kids {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002440 set r $commitrow($curview,$c)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002441 if {$l1 <= $r && $r <= $l2} {
2442 return [expr {$r - $l1 + 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002443 }
2444 }
2445 return 0
2446}
2447
2448proc sanity {row {full 0}} {
2449 global rowidlist rowoffsets
2450
2451 set col -1
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002452 set ids [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002453 foreach id $ids {
2454 incr col
2455 if {$id eq {}} continue
2456 if {$col < [llength $ids] - 1 &&
2457 [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002458 puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}"
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002459 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002460 set o [lindex $rowoffsets $row $col]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002461 set y $row
2462 set x $col
2463 while {$o ne {}} {
2464 incr y -1
2465 incr x $o
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002466 if {[lindex $rowidlist $y $x] != $id} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002467 puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]"
2468 puts " id=[shortids $id] check started at row $row"
2469 for {set i $row} {$i >= $y} {incr i -1} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002470 puts " row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}"
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002471 }
2472 break
2473 }
2474 if {!$full} break
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002475 set o [lindex $rowoffsets $y $x]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002476 }
2477 }
2478}
2479
2480proc makeuparrow {oid x y z} {
Paul Mackerras66e46f32006-10-14 19:21:02 +10002481 global rowidlist rowoffsets uparrowlen idrowranges displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002482
2483 for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
2484 incr y -1
2485 incr x $z
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002486 set off0 [lindex $rowoffsets $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002487 for {set x0 $x} {1} {incr x0} {
2488 if {$x0 >= [llength $off0]} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002489 set x0 [llength [lindex $rowoffsets [expr {$y-1}]]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002490 break
2491 }
2492 set z [lindex $off0 $x0]
2493 if {$z ne {}} {
2494 incr x0 $z
2495 break
2496 }
2497 }
2498 set z [expr {$x0 - $x}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002499 lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid]
2500 lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002501 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002502 set tmp [lreplace [lindex $rowoffsets $y] $x $x {}]
2503 lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1]
Paul Mackerras66e46f32006-10-14 19:21:02 +10002504 lappend idrowranges($oid) [lindex $displayorder $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002505}
2506
2507proc initlayout {} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10002508 global rowidlist rowoffsets displayorder commitlisted
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002509 global rowlaidout rowoptim
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002510 global idinlist rowchk rowrangelist idrowranges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002511 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002512 global nextcolor
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002513 global parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002514 global colormap rowtextx
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002515 global selectfirst
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002516
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002517 set numcommits 0
2518 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002519 set commitlisted {}
2520 set parentlist {}
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002521 set rowrangelist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002522 set nextcolor 0
2523 set rowidlist {{}}
2524 set rowoffsets {{}}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002525 catch {unset idinlist}
2526 catch {unset rowchk}
2527 set rowlaidout 0
2528 set rowoptim 0
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002529 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002530 catch {unset colormap}
2531 catch {unset rowtextx}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002532 catch {unset idrowranges}
Paul Mackerrase507fd42007-06-16 21:51:08 +10002533 set selectfirst 1
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002534}
2535
2536proc setcanvscroll {} {
2537 global canv canv2 canv3 numcommits linespc canvxmax canvy0
2538
2539 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
2540 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
2541 $canv2 conf -scrollregion [list 0 0 0 $ymax]
2542 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002543}
2544
2545proc visiblerows {} {
2546 global canv numcommits linespc
2547
2548 set ymax [lindex [$canv cget -scrollregion] 3]
2549 if {$ymax eq {} || $ymax == 0} return
2550 set f [$canv yview]
2551 set y0 [expr {int([lindex $f 0] * $ymax)}]
2552 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
2553 if {$r0 < 0} {
2554 set r0 0
2555 }
2556 set y1 [expr {int([lindex $f 1] * $ymax)}]
2557 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
2558 if {$r1 >= $numcommits} {
2559 set r1 [expr {$numcommits - 1}]
2560 }
2561 return [list $r0 $r1]
2562}
2563
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002564proc layoutmore {tmax allread} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002565 global rowlaidout rowoptim commitidx numcommits optim_delay
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002566 global uparrowlen curview rowidlist idinlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002567
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002568 set showlast 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002569 set showdelay $optim_delay
2570 set optdelay [expr {$uparrowlen + 1}]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002571 while {1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002572 if {$rowoptim - $showdelay > $numcommits} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002573 showstuff [expr {$rowoptim - $showdelay}] $showlast
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002574 } elseif {$rowlaidout - $optdelay > $rowoptim} {
2575 set nr [expr {$rowlaidout - $optdelay - $rowoptim}]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002576 if {$nr > 100} {
2577 set nr 100
2578 }
2579 optimize_rows $rowoptim 0 [expr {$rowoptim + $nr}]
2580 incr rowoptim $nr
2581 } elseif {$commitidx($curview) > $rowlaidout} {
2582 set nr [expr {$commitidx($curview) - $rowlaidout}]
2583 # may need to increase this threshold if uparrowlen or
2584 # mingaplen are increased...
2585 if {$nr > 150} {
2586 set nr 150
2587 }
2588 set row $rowlaidout
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002589 set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002590 if {$rowlaidout == $row} {
2591 return 0
2592 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002593 } elseif {$allread} {
2594 set optdelay 0
2595 set nrows $commitidx($curview)
2596 if {[lindex $rowidlist $nrows] ne {} ||
2597 [array names idinlist] ne {}} {
2598 layouttail
2599 set rowlaidout $commitidx($curview)
2600 } elseif {$rowoptim == $nrows} {
2601 set showdelay 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002602 set showlast 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002603 if {$numcommits == $nrows} {
2604 return 0
2605 }
2606 }
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002607 } else {
2608 return 0
2609 }
2610 if {$tmax ne {} && [clock clicks -milliseconds] >= $tmax} {
2611 return 1
2612 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002613 }
2614}
2615
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002616proc showstuff {canshow last} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002617 global numcommits commitrow pending_select selectedline curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002618 global lookingforhead mainheadid displayorder nullid selectfirst
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002619 global lastscrollset
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002620
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002621 if {$numcommits == 0} {
2622 global phase
2623 set phase "incrdraw"
2624 allcanvs delete all
2625 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002626 set r0 $numcommits
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002627 set prev $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002628 set numcommits $canshow
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002629 set t [clock clicks -milliseconds]
2630 if {$prev < 100 || $last || $t - $lastscrollset > 500} {
2631 set lastscrollset $t
2632 setcanvscroll
2633 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002634 set rows [visiblerows]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002635 set r1 [lindex $rows 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002636 if {$r1 >= $canshow} {
2637 set r1 [expr {$canshow - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002638 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002639 if {$r0 <= $r1} {
2640 drawcommits $r0 $r1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002641 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002642 if {[info exists pending_select] &&
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002643 [info exists commitrow($curview,$pending_select)] &&
2644 $commitrow($curview,$pending_select) < $numcommits} {
2645 selectline $commitrow($curview,$pending_select) 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002646 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10002647 if {$selectfirst} {
2648 if {[info exists selectedline] || [info exists pending_select]} {
2649 set selectfirst 0
2650 } else {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002651 set l [expr {[lindex $displayorder 0] eq $nullid}]
2652 selectline $l 1
Paul Mackerrase507fd42007-06-16 21:51:08 +10002653 set selectfirst 0
2654 }
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10002655 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002656 if {$lookingforhead && [info exists commitrow($curview,$mainheadid)]
2657 && ($last || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2658 set lookingforhead 0
2659 dodiffindex
2660 }
2661}
2662
2663proc doshowlocalchanges {} {
2664 global lookingforhead curview mainheadid phase commitrow
2665
2666 if {[info exists commitrow($curview,$mainheadid)] &&
2667 ($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2668 dodiffindex
2669 } elseif {$phase ne {}} {
2670 set lookingforhead 1
2671 }
2672}
2673
2674proc dohidelocalchanges {} {
2675 global lookingforhead localrow lserial
2676
2677 set lookingforhead 0
2678 if {$localrow >= 0} {
2679 removerow $localrow
2680 set localrow -1
2681 }
2682 incr lserial
2683}
2684
2685# spawn off a process to do git diff-index HEAD
2686proc dodiffindex {} {
2687 global localrow lserial
2688
2689 incr lserial
2690 set localrow -1
2691 set fd [open "|git diff-index HEAD" r]
2692 fconfigure $fd -blocking 0
2693 filerun $fd [list readdiffindex $fd $lserial]
2694}
2695
2696proc readdiffindex {fd serial} {
2697 global localrow commitrow mainheadid nullid curview
2698 global commitinfo commitdata lserial
2699
2700 if {[gets $fd line] < 0} {
2701 if {[eof $fd]} {
2702 close $fd
2703 return 0
2704 }
2705 return 1
2706 }
2707 # we only need to see one line and we don't really care what it says...
2708 close $fd
2709
2710 if {$serial == $lserial && $localrow == -1} {
2711 # add the line for the local diff to the graph
2712 set localrow $commitrow($curview,$mainheadid)
2713 set hl "Local uncommitted changes"
2714 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
2715 set commitdata($nullid) "\n $hl\n"
2716 insertrow $localrow $nullid
2717 }
2718 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002719}
2720
2721proc layoutrows {row endrow last} {
2722 global rowidlist rowoffsets displayorder
2723 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002724 global children parentlist
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002725 global idrowranges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002726 global commitidx curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002727 global idinlist rowchk rowrangelist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002728
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002729 set idlist [lindex $rowidlist $row]
2730 set offs [lindex $rowoffsets $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002731 while {$row < $endrow} {
2732 set id [lindex $displayorder $row]
2733 set oldolds {}
2734 set newolds {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002735 foreach p [lindex $parentlist $row] {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002736 if {![info exists idinlist($p)]} {
2737 lappend newolds $p
2738 } elseif {!$idinlist($p)} {
2739 lappend oldolds $p
2740 }
2741 }
2742 set nev [expr {[llength $idlist] + [llength $newolds]
2743 + [llength $oldolds] - $maxwidth + 1}]
2744 if {$nev > 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002745 if {!$last &&
2746 $row + $uparrowlen + $mingaplen >= $commitidx($curview)} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002747 for {set x [llength $idlist]} {[incr x -1] >= 0} {} {
2748 set i [lindex $idlist $x]
2749 if {![info exists rowchk($i)] || $row >= $rowchk($i)} {
2750 set r [usedinrange $i [expr {$row - $downarrowlen}] \
2751 [expr {$row + $uparrowlen + $mingaplen}]]
2752 if {$r == 0} {
2753 set idlist [lreplace $idlist $x $x]
2754 set offs [lreplace $offs $x $x]
2755 set offs [incrange $offs $x 1]
2756 set idinlist($i) 0
Paul Mackerrasd8d2df02006-03-18 20:42:46 +11002757 set rm1 [expr {$row - 1}]
Paul Mackerras66e46f32006-10-14 19:21:02 +10002758 lappend idrowranges($i) [lindex $displayorder $rm1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002759 if {[incr nev -1] <= 0} break
2760 continue
2761 }
2762 set rowchk($id) [expr {$row + $r}]
2763 }
2764 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002765 lset rowidlist $row $idlist
2766 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002767 }
2768 set col [lsearch -exact $idlist $id]
2769 if {$col < 0} {
2770 set col [llength $idlist]
2771 lappend idlist $id
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002772 lset rowidlist $row $idlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002773 set z {}
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002774 if {$children($curview,$id) ne {}} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002775 set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002776 unset idinlist($id)
2777 }
2778 lappend offs $z
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002779 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002780 if {$z ne {}} {
2781 makeuparrow $id $col $row $z
2782 }
2783 } else {
2784 unset idinlist($id)
2785 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002786 set ranges {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002787 if {[info exists idrowranges($id)]} {
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002788 set ranges $idrowranges($id)
Paul Mackerras66e46f32006-10-14 19:21:02 +10002789 lappend ranges $id
Paul Mackerras22626ef2006-04-17 09:56:02 +10002790 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002791 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002792 lappend rowrangelist $ranges
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002793 incr row
2794 set offs [ntimes [llength $idlist] 0]
2795 set l [llength $newolds]
2796 set idlist [eval lreplace \$idlist $col $col $newolds]
2797 set o 0
2798 if {$l != 1} {
2799 set offs [lrange $offs 0 [expr {$col - 1}]]
2800 foreach x $newolds {
2801 lappend offs {}
2802 incr o -1
2803 }
2804 incr o
2805 set tmp [expr {[llength $idlist] - [llength $offs]}]
2806 if {$tmp > 0} {
2807 set offs [concat $offs [ntimes $tmp $o]]
2808 }
2809 } else {
2810 lset offs $col {}
2811 }
2812 foreach i $newolds {
2813 set idinlist($i) 1
Paul Mackerras66e46f32006-10-14 19:21:02 +10002814 set idrowranges($i) $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002815 }
2816 incr col $l
2817 foreach oid $oldolds {
2818 set idinlist($oid) 1
2819 set idlist [linsert $idlist $col $oid]
2820 set offs [linsert $offs $col $o]
2821 makeuparrow $oid $col $row $o
2822 incr col
2823 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002824 lappend rowidlist $idlist
2825 lappend rowoffsets $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002826 }
2827 return $row
2828}
2829
2830proc addextraid {id row} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10002831 global displayorder commitrow commitinfo
Paul Mackerrase7da3472006-04-17 10:27:59 +10002832 global commitidx commitlisted
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002833 global parentlist children curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002834
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002835 incr commitidx($curview)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002836 lappend displayorder $id
Paul Mackerrase7da3472006-04-17 10:27:59 +10002837 lappend commitlisted 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10002838 lappend parentlist {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002839 set commitrow($curview,$id) $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002840 readcommit $id
2841 if {![info exists commitinfo($id)]} {
2842 set commitinfo($id) {"No commit information available"}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002843 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002844 if {![info exists children($curview,$id)]} {
2845 set children($curview,$id) {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002846 }
2847}
2848
2849proc layouttail {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002850 global rowidlist rowoffsets idinlist commitidx curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002851 global idrowranges rowrangelist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002852
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002853 set row $commitidx($curview)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002854 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002855 while {$idlist ne {}} {
2856 set col [expr {[llength $idlist] - 1}]
2857 set id [lindex $idlist $col]
2858 addextraid $id $row
2859 unset idinlist($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002860 lappend idrowranges($id) $row
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002861 lappend rowrangelist $idrowranges($id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002862 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002863 incr row
2864 set offs [ntimes $col 0]
2865 set idlist [lreplace $idlist $col $col]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002866 lappend rowidlist $idlist
2867 lappend rowoffsets $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002868 }
2869
2870 foreach id [array names idinlist] {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002871 unset idinlist($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002872 addextraid $id $row
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002873 lset rowidlist $row [list $id]
2874 lset rowoffsets $row 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002875 makeuparrow $id 0 $row 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002876 lappend idrowranges($id) $row
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002877 lappend rowrangelist $idrowranges($id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002878 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002879 incr row
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002880 lappend rowidlist {}
2881 lappend rowoffsets {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002882 }
2883}
2884
2885proc insert_pad {row col npad} {
2886 global rowidlist rowoffsets
2887
2888 set pad [ntimes $npad {}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002889 lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad]
2890 set tmp [eval linsert [list [lindex $rowoffsets $row]] $col $pad]
2891 lset rowoffsets $row [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002892}
2893
2894proc optimize_rows {row col endrow} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002895 global rowidlist rowoffsets displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002896
2897 for {} {$row < $endrow} {incr row} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002898 set idlist [lindex $rowidlist $row]
2899 set offs [lindex $rowoffsets $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002900 set haspad 0
2901 for {} {$col < [llength $offs]} {incr col} {
2902 if {[lindex $idlist $col] eq {}} {
2903 set haspad 1
2904 continue
2905 }
2906 set z [lindex $offs $col]
2907 if {$z eq {}} continue
2908 set isarrow 0
2909 set x0 [expr {$col + $z}]
2910 set y0 [expr {$row - 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002911 set z0 [lindex $rowoffsets $y0 $x0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002912 if {$z0 eq {}} {
2913 set id [lindex $idlist $col]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002914 set ranges [rowranges $id]
2915 if {$ranges ne {} && $y0 > [lindex $ranges 0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002916 set isarrow 1
2917 }
2918 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10002919 # Looking at lines from this row to the previous row,
2920 # make them go straight up if they end in an arrow on
2921 # the previous row; otherwise make them go straight up
2922 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002923 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10002924 # Line currently goes left too much;
2925 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002926 set npad [expr {-1 - $z + $isarrow}]
2927 set offs [incrange $offs $col $npad]
2928 insert_pad $y0 $x0 $npad
2929 if {$y0 > 0} {
2930 optimize_rows $y0 $x0 $row
2931 }
2932 set z [lindex $offs $col]
2933 set x0 [expr {$col + $z}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002934 set z0 [lindex $rowoffsets $y0 $x0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002935 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10002936 # Line currently goes right too much;
2937 # insert pads in this line and adjust the next's rowoffsets
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002938 set npad [expr {$z - 1 + $isarrow}]
2939 set y1 [expr {$row + 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002940 set offs2 [lindex $rowoffsets $y1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002941 set x1 -1
2942 foreach z $offs2 {
2943 incr x1
2944 if {$z eq {} || $x1 + $z < $col} continue
2945 if {$x1 + $z > $col} {
2946 incr npad
2947 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002948 lset rowoffsets $y1 [incrange $offs2 $x1 $npad]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002949 break
2950 }
2951 set pad [ntimes $npad {}]
2952 set idlist [eval linsert \$idlist $col $pad]
2953 set tmp [eval linsert \$offs $col $pad]
2954 incr col $npad
2955 set offs [incrange $tmp $col [expr {-$npad}]]
2956 set z [lindex $offs $col]
2957 set haspad 1
2958 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11002959 if {$z0 eq {} && !$isarrow} {
2960 # this line links to its first child on row $row-2
2961 set rm2 [expr {$row - 2}]
2962 set id [lindex $displayorder $rm2]
2963 set xc [lsearch -exact [lindex $rowidlist $rm2] $id]
2964 if {$xc >= 0} {
2965 set z0 [expr {$xc - $x0}]
2966 }
2967 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10002968 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002969 if {$z0 ne {} && $z < 0 && $z0 > 0} {
2970 insert_pad $y0 $x0 1
2971 set offs [incrange $offs $col 1]
2972 optimize_rows $y0 [expr {$x0 + 1}] $row
2973 }
2974 }
2975 if {!$haspad} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11002976 set o {}
Paul Mackerras3fc42792006-09-15 09:45:23 +10002977 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002978 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
2979 set o [lindex $offs $col]
Paul Mackerraseb447a12006-03-18 23:11:37 +11002980 if {$o eq {}} {
2981 # check if this is the link to the first child
2982 set id [lindex $idlist $col]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002983 set ranges [rowranges $id]
2984 if {$ranges ne {} && $row == [lindex $ranges 0]} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11002985 # it is, work out offset to child
2986 set y0 [expr {$row - 1}]
2987 set id [lindex $displayorder $y0]
2988 set x0 [lsearch -exact [lindex $rowidlist $y0] $id]
2989 if {$x0 >= 0} {
2990 set o [expr {$x0 - $col}]
2991 }
2992 }
2993 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002994 if {$o eq {} || $o <= 0} break
2995 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10002996 # Insert a pad at that column as long as it has a line and
2997 # isn't the last column, and adjust the next row' offsets
Paul Mackerraseb447a12006-03-18 23:11:37 +11002998 if {$o ne {} && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002999 set y1 [expr {$row + 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003000 set offs2 [lindex $rowoffsets $y1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003001 set x1 -1
3002 foreach z $offs2 {
3003 incr x1
3004 if {$z eq {} || $x1 + $z < $col} continue
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003005 lset rowoffsets $y1 [incrange $offs2 $x1 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003006 break
3007 }
3008 set idlist [linsert $idlist $col {}]
3009 set tmp [linsert $offs $col {}]
3010 incr col
3011 set offs [incrange $tmp $col -1]
3012 }
3013 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003014 lset rowidlist $row $idlist
3015 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003016 set col 0
3017 }
3018}
3019
3020proc xc {row col} {
3021 global canvx0 linespc
3022 return [expr {$canvx0 + $col * $linespc}]
3023}
3024
3025proc yc {row} {
3026 global canvy0 linespc
3027 return [expr {$canvy0 + $row * $linespc}]
3028}
3029
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003030proc linewidth {id} {
3031 global thickerline lthickness
3032
3033 set wid $lthickness
3034 if {[info exists thickerline] && $id eq $thickerline} {
3035 set wid [expr {2 * $lthickness}]
3036 }
3037 return $wid
3038}
3039
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003040proc rowranges {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003041 global phase idrowranges commitrow rowlaidout rowrangelist curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003042
3043 set ranges {}
Paul Mackerras22626ef2006-04-17 09:56:02 +10003044 if {$phase eq {} ||
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003045 ([info exists commitrow($curview,$id)]
3046 && $commitrow($curview,$id) < $rowlaidout)} {
3047 set ranges [lindex $rowrangelist $commitrow($curview,$id)]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003048 } elseif {[info exists idrowranges($id)]} {
3049 set ranges $idrowranges($id)
3050 }
Paul Mackerras66e46f32006-10-14 19:21:02 +10003051 set linenos {}
3052 foreach rid $ranges {
3053 lappend linenos $commitrow($curview,$rid)
3054 }
3055 if {$linenos ne {}} {
3056 lset linenos 0 [expr {[lindex $linenos 0] + 1}]
3057 }
3058 return $linenos
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003059}
3060
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003061# work around tk8.4 refusal to draw arrows on diagonal segments
3062proc adjarrowhigh {coords} {
3063 global linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003064
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003065 set x0 [lindex $coords 0]
3066 set x1 [lindex $coords 2]
3067 if {$x0 != $x1} {
3068 set y0 [lindex $coords 1]
3069 set y1 [lindex $coords 3]
3070 if {$y0 - $y1 <= 2 * $linespc && $x1 == [lindex $coords 4]} {
3071 # we have a nearby vertical segment, just trim off the diag bit
3072 set coords [lrange $coords 2 end]
3073 } else {
3074 set slope [expr {($x0 - $x1) / ($y0 - $y1)}]
3075 set xi [expr {$x0 - $slope * $linespc / 2}]
3076 set yi [expr {$y0 - $linespc / 2}]
3077 set coords [lreplace $coords 0 1 $xi $y0 $xi $yi]
Paul Mackerraseb447a12006-03-18 23:11:37 +11003078 }
3079 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003080 return $coords
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003081}
3082
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003083proc drawlineseg {id row endrow arrowlow} {
3084 global rowidlist displayorder iddrawn linesegs
3085 global canv colormap linespc curview maxlinelen
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003086
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003087 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
3088 set le [expr {$row + 1}]
3089 set arrowhigh 1
3090 while {1} {
3091 set c [lsearch -exact [lindex $rowidlist $le] $id]
3092 if {$c < 0} {
3093 incr le -1
3094 break
3095 }
3096 lappend cols $c
3097 set x [lindex $displayorder $le]
3098 if {$x eq $id} {
3099 set arrowhigh 0
3100 break
3101 }
3102 if {[info exists iddrawn($x)] || $le == $endrow} {
3103 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
3104 if {$c >= 0} {
3105 lappend cols $c
3106 set arrowhigh 0
3107 }
3108 break
3109 }
3110 incr le
3111 }
3112 if {$le <= $row} {
3113 return $row
3114 }
3115
3116 set lines {}
3117 set i 0
3118 set joinhigh 0
3119 if {[info exists linesegs($id)]} {
3120 set lines $linesegs($id)
3121 foreach li $lines {
3122 set r0 [lindex $li 0]
3123 if {$r0 > $row} {
3124 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
3125 set joinhigh 1
3126 }
3127 break
3128 }
3129 incr i
3130 }
3131 }
3132 set joinlow 0
3133 if {$i > 0} {
3134 set li [lindex $lines [expr {$i-1}]]
3135 set r1 [lindex $li 1]
3136 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
3137 set joinlow 1
3138 }
3139 }
3140
3141 set x [lindex $cols [expr {$le - $row}]]
3142 set xp [lindex $cols [expr {$le - 1 - $row}]]
3143 set dir [expr {$xp - $x}]
3144 if {$joinhigh} {
3145 set ith [lindex $lines $i 2]
3146 set coords [$canv coords $ith]
3147 set ah [$canv itemcget $ith -arrow]
3148 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
3149 set x2 [lindex $cols [expr {$le + 1 - $row}]]
3150 if {$x2 ne {} && $x - $x2 == $dir} {
3151 set coords [lrange $coords 0 end-2]
3152 }
3153 } else {
3154 set coords [list [xc $le $x] [yc $le]]
3155 }
3156 if {$joinlow} {
3157 set itl [lindex $lines [expr {$i-1}] 2]
3158 set al [$canv itemcget $itl -arrow]
3159 set arrowlow [expr {$al eq "last" || $al eq "both"}]
3160 } elseif {$arrowlow &&
3161 [lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0} {
3162 set arrowlow 0
3163 }
3164 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
3165 for {set y $le} {[incr y -1] > $row} {} {
3166 set x $xp
3167 set xp [lindex $cols [expr {$y - 1 - $row}]]
3168 set ndir [expr {$xp - $x}]
3169 if {$dir != $ndir || $xp < 0} {
3170 lappend coords [xc $y $x] [yc $y]
3171 }
3172 set dir $ndir
3173 }
3174 if {!$joinlow} {
3175 if {$xp < 0} {
3176 # join parent line to first child
3177 set ch [lindex $displayorder $row]
3178 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
3179 if {$xc < 0} {
3180 puts "oops: drawlineseg: child $ch not on row $row"
3181 } else {
3182 if {$xc < $x - 1} {
3183 lappend coords [xc $row [expr {$x-1}]] [yc $row]
3184 } elseif {$xc > $x + 1} {
3185 lappend coords [xc $row [expr {$x+1}]] [yc $row]
3186 }
3187 set x $xc
3188 }
3189 lappend coords [xc $row $x] [yc $row]
3190 } else {
3191 set xn [xc $row $xp]
3192 set yn [yc $row]
3193 # work around tk8.4 refusal to draw arrows on diagonal segments
3194 if {$arrowlow && $xn != [lindex $coords end-1]} {
3195 if {[llength $coords] < 4 ||
3196 [lindex $coords end-3] != [lindex $coords end-1] ||
3197 [lindex $coords end] - $yn > 2 * $linespc} {
3198 set xn [xc $row [expr {$xp - 0.5 * $dir}]]
3199 set yo [yc [expr {$row + 0.5}]]
3200 lappend coords $xn $yo $xn $yn
3201 }
3202 } else {
3203 lappend coords $xn $yn
3204 }
3205 }
3206 if {!$joinhigh} {
3207 if {$arrowhigh} {
3208 set coords [adjarrowhigh $coords]
3209 }
3210 assigncolor $id
3211 set t [$canv create line $coords -width [linewidth $id] \
3212 -fill $colormap($id) -tags lines.$id -arrow $arrow]
3213 $canv lower $t
3214 bindline $t $id
3215 set lines [linsert $lines $i [list $row $le $t]]
3216 } else {
3217 $canv coords $ith $coords
3218 if {$arrow ne $ah} {
3219 $canv itemconf $ith -arrow $arrow
3220 }
3221 lset lines $i 0 $row
3222 }
3223 } else {
3224 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
3225 set ndir [expr {$xo - $xp}]
3226 set clow [$canv coords $itl]
3227 if {$dir == $ndir} {
3228 set clow [lrange $clow 2 end]
3229 }
3230 set coords [concat $coords $clow]
3231 if {!$joinhigh} {
3232 lset lines [expr {$i-1}] 1 $le
3233 if {$arrowhigh} {
3234 set coords [adjarrowhigh $coords]
3235 }
3236 } else {
3237 # coalesce two pieces
3238 $canv delete $ith
3239 set b [lindex $lines [expr {$i-1}] 0]
3240 set e [lindex $lines $i 1]
3241 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
3242 }
3243 $canv coords $itl $coords
3244 if {$arrow ne $al} {
3245 $canv itemconf $itl -arrow $arrow
3246 }
3247 }
3248
3249 set linesegs($id) $lines
3250 return $le
3251}
3252
3253proc drawparentlinks {id row} {
3254 global rowidlist canv colormap curview parentlist
3255 global idpos
3256
3257 set rowids [lindex $rowidlist $row]
3258 set col [lsearch -exact $rowids $id]
3259 if {$col < 0} return
3260 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003261 set row2 [expr {$row + 1}]
3262 set x [xc $row $col]
3263 set y [yc $row]
3264 set y2 [yc $row2]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003265 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003266 # rmx = right-most X coord used
3267 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003268 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11003269 set i [lsearch -exact $ids $p]
3270 if {$i < 0} {
3271 puts "oops, parent $p of $id not in list"
3272 continue
3273 }
3274 set x2 [xc $row2 $i]
3275 if {$x2 > $rmx} {
3276 set rmx $x2
3277 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003278 if {[lsearch -exact $rowids $p] < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003279 # drawlineseg will do this one for us
3280 continue
3281 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003282 assigncolor $p
3283 # should handle duplicated parents here...
3284 set coords [list $x $y]
3285 if {$i < $col - 1} {
3286 lappend coords [xc $row [expr {$i + 1}]] $y
3287 } elseif {$i > $col + 1} {
3288 lappend coords [xc $row [expr {$i - 1}]] $y
3289 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003290 lappend coords $x2 $y2
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003291 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003292 -fill $colormap($p) -tags lines.$p]
3293 $canv lower $t
3294 bindline $t $p
3295 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003296 if {$rmx > [lindex $idpos($id) 1]} {
3297 lset idpos($id) 1 $rmx
3298 redrawtags $id
3299 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003300}
3301
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003302proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003303 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003304
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003305 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003306}
3307
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003308proc drawcmittext {id row col} {
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003309 global linespc canv canv2 canv3 canvy0 fgcolor
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003310 global commitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003311 global rowtextx idpos idtags idheads idotherrefs
3312 global linehtag linentag linedtag
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003313 global mainfont canvxmax boldrows boldnamerows fgcolor nullid
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003314
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003315 if {$id eq $nullid} {
3316 set ofill red
3317 } else {
3318 set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}]
3319 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003320 set x [xc $row $col]
3321 set y [yc $row]
3322 set orad [expr {$linespc / 3}]
3323 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
3324 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003325 -fill $ofill -outline $fgcolor -width 1 -tags circle]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003326 $canv raise $t
3327 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003328 set rmx [llength [lindex $rowidlist $row]]
3329 set olds [lindex $parentlist $row]
3330 if {$olds ne {}} {
3331 set nextids [lindex $rowidlist [expr {$row + 1}]]
3332 foreach p $olds {
3333 set i [lsearch -exact $nextids $p]
3334 if {$i > $rmx} {
3335 set rmx $i
3336 }
3337 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003338 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003339 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003340 set rowtextx($row) $xt
3341 set idpos($id) [list $x $xt $y]
3342 if {[info exists idtags($id)] || [info exists idheads($id)]
3343 || [info exists idotherrefs($id)]} {
3344 set xt [drawtags $id $x $xt $y]
3345 }
3346 set headline [lindex $commitinfo($id) 0]
3347 set name [lindex $commitinfo($id) 1]
3348 set date [lindex $commitinfo($id) 2]
3349 set date [formatdate $date]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003350 set font $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10003351 set nfont $mainfont
3352 set isbold [ishighlighted $row]
3353 if {$isbold > 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003354 lappend boldrows $row
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003355 lappend font bold
Paul Mackerras908c3582006-05-20 09:38:11 +10003356 if {$isbold > 1} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003357 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003358 lappend nfont bold
3359 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003360 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003361 set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
3362 -text $headline -font $font -tags text]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003363 $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003364 set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
3365 -text $name -font $nfont -tags text]
3366 set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
3367 -text $date -font $mainfont -tags text]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11003368 set xr [expr {$xt + [font measure $mainfont $headline]}]
3369 if {$xr > $canvxmax} {
3370 set canvxmax $xr
3371 setcanvscroll
3372 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003373}
3374
3375proc drawcmitrow {row} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003376 global displayorder rowidlist
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003377 global iddrawn
Paul Mackerrase7da3472006-04-17 10:27:59 +10003378 global commitinfo parentlist numcommits
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003379 global filehighlight fhighlights findstring nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10003380 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10003381 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003382
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003383 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003384
3385 set id [lindex $displayorder $row]
Paul Mackerras908c3582006-05-20 09:38:11 +10003386 if {[info exists hlview] && ![info exists vhighlights($row)]} {
3387 askvhighlight $row $id
3388 }
3389 if {[info exists filehighlight] && ![info exists fhighlights($row)]} {
3390 askfilehighlight $row $id
3391 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003392 if {$findstring ne {} && ![info exists nhighlights($row)]} {
3393 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10003394 }
Paul Mackerras164ff272006-05-29 19:50:02 +10003395 if {$highlight_related ne "None" && ![info exists rhighlights($row)]} {
3396 askrelhighlight $row $id
3397 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003398 if {[info exists iddrawn($id)]} return
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003399 set col [lsearch -exact [lindex $rowidlist $row] $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003400 if {$col < 0} {
3401 puts "oops, row $row id $id not in list"
3402 return
3403 }
3404 if {![info exists commitinfo($id)]} {
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11003405 getcommit $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003406 }
3407 assigncolor $id
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003408 drawcmittext $id $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003409 set iddrawn($id) 1
3410}
3411
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003412proc drawcommits {row {endrow {}}} {
3413 global numcommits iddrawn displayorder curview
3414 global parentlist rowidlist
3415
3416 if {$row < 0} {
3417 set row 0
3418 }
3419 if {$endrow eq {}} {
3420 set endrow $row
3421 }
3422 if {$endrow >= $numcommits} {
3423 set endrow [expr {$numcommits - 1}]
3424 }
3425
3426 # make the lines join to already-drawn rows either side
3427 set r [expr {$row - 1}]
3428 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
3429 set r $row
3430 }
3431 set er [expr {$endrow + 1}]
3432 if {$er >= $numcommits ||
3433 ![info exists iddrawn([lindex $displayorder $er])]} {
3434 set er $endrow
3435 }
3436 for {} {$r <= $er} {incr r} {
3437 set id [lindex $displayorder $r]
3438 set wasdrawn [info exists iddrawn($id)]
3439 if {!$wasdrawn} {
3440 drawcmitrow $r
3441 }
3442 if {$r == $er} break
3443 set nextid [lindex $displayorder [expr {$r + 1}]]
3444 if {$wasdrawn && [info exists iddrawn($nextid)]} {
3445 catch {unset prevlines}
3446 continue
3447 }
3448 drawparentlinks $id $r
3449
3450 if {[info exists lineends($r)]} {
3451 foreach lid $lineends($r) {
3452 unset prevlines($lid)
3453 }
3454 }
3455 set rowids [lindex $rowidlist $r]
3456 foreach lid $rowids {
3457 if {$lid eq {}} continue
3458 if {$lid eq $id} {
3459 # see if this is the first child of any of its parents
3460 foreach p [lindex $parentlist $r] {
3461 if {[lsearch -exact $rowids $p] < 0} {
3462 # make this line extend up to the child
3463 set le [drawlineseg $p $r $er 0]
3464 lappend lineends($le) $p
3465 set prevlines($p) 1
3466 }
3467 }
3468 } elseif {![info exists prevlines($lid)]} {
3469 set le [drawlineseg $lid $r $er 1]
3470 lappend lineends($le) $lid
3471 set prevlines($lid) 1
3472 }
3473 }
3474 }
3475}
3476
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003477proc drawfrac {f0 f1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003478 global canv linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003479
3480 set ymax [lindex [$canv cget -scrollregion] 3]
3481 if {$ymax eq {} || $ymax == 0} return
3482 set y0 [expr {int($f0 * $ymax)}]
3483 set row [expr {int(($y0 - 3) / $linespc) - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003484 set y1 [expr {int($f1 * $ymax)}]
3485 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003486 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003487}
3488
3489proc drawvisible {} {
3490 global canv
3491 eval drawfrac [$canv yview]
3492}
3493
3494proc clear_display {} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003495 global iddrawn linesegs
Paul Mackerras164ff272006-05-29 19:50:02 +10003496 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003497
3498 allcanvs delete all
3499 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003500 catch {unset linesegs}
Paul Mackerras908c3582006-05-20 09:38:11 +10003501 catch {unset vhighlights}
3502 catch {unset fhighlights}
3503 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10003504 catch {unset rhighlights}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003505}
3506
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003507proc findcrossings {id} {
3508 global rowidlist parentlist numcommits rowoffsets displayorder
3509
3510 set cross {}
3511 set ccross {}
3512 foreach {s e} [rowranges $id] {
3513 if {$e >= $numcommits} {
3514 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003515 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10003516 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003517 set x [lsearch -exact [lindex $rowidlist $e] $id]
3518 if {$x < 0} {
3519 puts "findcrossings: oops, no [shortids $id] in row $e"
3520 continue
3521 }
3522 for {set row $e} {[incr row -1] >= $s} {} {
3523 set olds [lindex $parentlist $row]
3524 set kid [lindex $displayorder $row]
3525 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
3526 if {$kidx < 0} continue
3527 set nextrow [lindex $rowidlist [expr {$row + 1}]]
3528 foreach p $olds {
3529 set px [lsearch -exact $nextrow $p]
3530 if {$px < 0} continue
3531 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
3532 if {[lsearch -exact $ccross $p] >= 0} continue
3533 if {$x == $px + ($kidx < $px? -1: 1)} {
3534 lappend ccross $p
3535 } elseif {[lsearch -exact $cross $p] < 0} {
3536 lappend cross $p
3537 }
3538 }
3539 }
3540 set inc [lindex $rowoffsets $row $x]
3541 if {$inc eq {}} break
3542 incr x $inc
3543 }
3544 }
3545 return [concat $ccross {{}} $cross]
3546}
3547
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003548proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11003549 global colormap colors nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003550 global commitrow parentlist children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003551
Paul Mackerras418c4c72006-02-07 09:10:18 +11003552 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003553 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003554 if {[info exists children($curview,$id)]} {
3555 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10003556 } else {
3557 set kids {}
3558 }
3559 if {[llength $kids] == 1} {
3560 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003561 if {[info exists colormap($child)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003562 && [llength [lindex $parentlist $commitrow($curview,$child)]] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003563 set colormap($id) $colormap($child)
3564 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003565 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003566 }
3567 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003568 set origbad {}
3569 foreach x [findcrossings $id] {
3570 if {$x eq {}} {
3571 # delimiter between corner crossings and other crossings
3572 if {[llength $badcolors] >= $ncolors - 1} break
3573 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003574 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003575 if {[info exists colormap($x)]
3576 && [lsearch -exact $badcolors $colormap($x)] < 0} {
3577 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003578 }
3579 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003580 if {[llength $badcolors] >= $ncolors} {
3581 set badcolors $origbad
3582 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003583 set origbad $badcolors
3584 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003585 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003586 if {[info exists colormap($child)]
3587 && [lsearch -exact $badcolors $colormap($child)] < 0} {
3588 lappend badcolors $colormap($child)
3589 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003590 foreach p [lindex $parentlist $commitrow($curview,$child)] {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003591 if {[info exists colormap($p)]
3592 && [lsearch -exact $badcolors $colormap($p)] < 0} {
3593 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003594 }
3595 }
3596 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003597 if {[llength $badcolors] >= $ncolors} {
3598 set badcolors $origbad
3599 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003600 }
3601 for {set i 0} {$i <= $ncolors} {incr i} {
3602 set c [lindex $colors $nextcolor]
3603 if {[incr nextcolor] >= $ncolors} {
3604 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003605 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003606 if {[lsearch -exact $badcolors $c]} break
3607 }
3608 set colormap($id) $c
3609}
3610
Paul Mackerrasa823a912005-06-21 10:01:38 +10003611proc bindline {t id} {
3612 global canv
3613
Paul Mackerrasa823a912005-06-21 10:01:38 +10003614 $canv bind $t <Enter> "lineenter %x %y $id"
3615 $canv bind $t <Motion> "linemotion %x %y $id"
3616 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10003617 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10003618}
3619
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003620proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10003621 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003622 global linespc lthickness
Paul Mackerras8a485712006-07-06 10:21:23 +10003623 global canv mainfont commitrow rowtextx curview fgcolor bgcolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003624
3625 set marks {}
3626 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003627 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003628 if {[info exists idtags($id)]} {
3629 set marks $idtags($id)
3630 set ntags [llength $marks]
3631 }
3632 if {[info exists idheads($id)]} {
3633 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003634 set nheads [llength $idheads($id)]
3635 }
3636 if {[info exists idotherrefs($id)]} {
3637 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003638 }
3639 if {$marks eq {}} {
3640 return $xt
3641 }
3642
3643 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003644 set yt [expr {$y1 - 0.5 * $linespc}]
3645 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003646 set xvals {}
3647 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10003648 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003649 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10003650 incr i
3651 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
3652 set wid [font measure [concat $mainfont bold] $tag]
3653 } else {
3654 set wid [font measure $mainfont $tag]
3655 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003656 lappend xvals $xt
3657 lappend wvals $wid
3658 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
3659 }
3660 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
3661 -width $lthickness -fill black -tags tag.$id]
3662 $canv lower $t
3663 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003664 set xl [expr {$x + $delta}]
3665 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras8a485712006-07-06 10:21:23 +10003666 set font $mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003667 if {[incr ntags -1] >= 0} {
3668 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003669 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
3670 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10003671 -width 1 -outline black -fill yellow -tags tag.$id]
3672 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003673 set rowtextx($commitrow($curview,$id)) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003674 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003675 # draw a head or other ref
3676 if {[incr nheads -1] >= 0} {
3677 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10003678 if {$tag eq $mainhead} {
3679 lappend font bold
3680 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003681 } else {
3682 set col "#ddddff"
3683 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003684 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003685 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003686 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02003687 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
3688 set rwid [font measure $mainfont $remoteprefix]
3689 set xi [expr {$x + 1}]
3690 set yti [expr {$yt + 1}]
3691 set xri [expr {$x + $rwid}]
3692 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
3693 -width 0 -fill "#ffddaa" -tags tag.$id
3694 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003695 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003696 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10003697 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10003698 if {$ntags >= 0} {
3699 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10003700 } elseif {$nheads >= 0} {
3701 $canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10003702 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003703 }
3704 return $xt
3705}
3706
Paul Mackerras8d858d12005-08-05 09:52:16 +10003707proc xcoord {i level ln} {
3708 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003709
Paul Mackerras8d858d12005-08-05 09:52:16 +10003710 set x [expr {$canvx0 + $i * $xspc1($ln)}]
3711 if {$i > 0 && $i == $level} {
3712 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
3713 } elseif {$i > $level} {
3714 set x [expr {$x + $xspc2 - $xspc1($ln)}]
3715 }
3716 return $x
3717}
3718
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003719proc show_status {msg} {
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003720 global canv mainfont fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003721
3722 clear_display
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003723 $canv create text 3 3 -anchor nw -text $msg -font $mainfont \
3724 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003725}
3726
Paul Mackerras561d0382006-08-28 22:41:09 +10003727# Insert a new commit as the child of the commit on row $row.
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003728# The new commit will be displayed on row $row and the commits
3729# on that row and below will move down one row.
3730proc insertrow {row newcmit} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003731 global displayorder parentlist commitlisted children
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003732 global commitrow curview rowidlist rowoffsets numcommits
Paul Mackerras66e46f32006-10-14 19:21:02 +10003733 global rowrangelist rowlaidout rowoptim numcommits
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003734 global selectedline rowchk commitidx
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003735
3736 if {$row >= $numcommits} {
3737 puts "oops, inserting new row $row but only have $numcommits rows"
3738 return
3739 }
3740 set p [lindex $displayorder $row]
3741 set displayorder [linsert $displayorder $row $newcmit]
3742 set parentlist [linsert $parentlist $row $p]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003743 set kids $children($curview,$p)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003744 lappend kids $newcmit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003745 set children($curview,$p) $kids
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003746 set children($curview,$newcmit) {}
Paul Mackerras561d0382006-08-28 22:41:09 +10003747 set commitlisted [linsert $commitlisted $row 1]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003748 set l [llength $displayorder]
3749 for {set r $row} {$r < $l} {incr r} {
3750 set id [lindex $displayorder $r]
3751 set commitrow($curview,$id) $r
3752 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003753 incr commitidx($curview)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003754
3755 set idlist [lindex $rowidlist $row]
3756 set offs [lindex $rowoffsets $row]
3757 set newoffs {}
3758 foreach x $idlist {
3759 if {$x eq {} || ($x eq $p && [llength $kids] == 1)} {
3760 lappend newoffs {}
3761 } else {
3762 lappend newoffs 0
3763 }
3764 }
3765 if {[llength $kids] == 1} {
3766 set col [lsearch -exact $idlist $p]
3767 lset idlist $col $newcmit
3768 } else {
3769 set col [llength $idlist]
3770 lappend idlist $newcmit
3771 lappend offs {}
3772 lset rowoffsets $row $offs
3773 }
3774 set rowidlist [linsert $rowidlist $row $idlist]
3775 set rowoffsets [linsert $rowoffsets [expr {$row+1}] $newoffs]
3776
3777 set rowrangelist [linsert $rowrangelist $row {}]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003778 if {[llength $kids] > 1} {
3779 set rp1 [expr {$row + 1}]
3780 set ranges [lindex $rowrangelist $rp1]
3781 if {$ranges eq {}} {
Paul Mackerras66e46f32006-10-14 19:21:02 +10003782 set ranges [list $newcmit $p]
3783 } elseif {[lindex $ranges end-1] eq $p} {
3784 lset ranges end-1 $newcmit
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003785 }
3786 lset rowrangelist $rp1 $ranges
3787 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003788
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003789 catch {unset rowchk}
3790
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003791 incr rowlaidout
3792 incr rowoptim
3793 incr numcommits
3794
Paul Mackerras561d0382006-08-28 22:41:09 +10003795 if {[info exists selectedline] && $selectedline >= $row} {
3796 incr selectedline
3797 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003798 redisplay
3799}
3800
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003801# Remove a commit that was inserted with insertrow on row $row.
3802proc removerow {row} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003803 global displayorder parentlist commitlisted children
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003804 global commitrow curview rowidlist rowoffsets numcommits
3805 global rowrangelist idrowranges rowlaidout rowoptim numcommits
3806 global linesegends selectedline rowchk commitidx
3807
3808 if {$row >= $numcommits} {
3809 puts "oops, removing row $row but only have $numcommits rows"
3810 return
3811 }
3812 set rp1 [expr {$row + 1}]
3813 set id [lindex $displayorder $row]
3814 set p [lindex $parentlist $row]
3815 set displayorder [lreplace $displayorder $row $row]
3816 set parentlist [lreplace $parentlist $row $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003817 set commitlisted [lreplace $commitlisted $row $row]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003818 set kids $children($curview,$p)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003819 set i [lsearch -exact $kids $id]
3820 if {$i >= 0} {
3821 set kids [lreplace $kids $i $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003822 set children($curview,$p) $kids
3823 }
3824 set l [llength $displayorder]
3825 for {set r $row} {$r < $l} {incr r} {
3826 set id [lindex $displayorder $r]
3827 set commitrow($curview,$id) $r
3828 }
3829 incr commitidx($curview) -1
3830
3831 set rowidlist [lreplace $rowidlist $row $row]
3832 set rowoffsets [lreplace $rowoffsets $rp1 $rp1]
3833 if {$kids ne {}} {
3834 set offs [lindex $rowoffsets $row]
3835 set offs [lreplace $offs end end]
3836 lset rowoffsets $row $offs
3837 }
3838
3839 set rowrangelist [lreplace $rowrangelist $row $row]
3840 if {[llength $kids] > 0} {
3841 set ranges [lindex $rowrangelist $row]
3842 if {[lindex $ranges end-1] eq $id} {
3843 set ranges [lreplace $ranges end-1 end]
3844 lset rowrangelist $row $ranges
3845 }
3846 }
3847
3848 catch {unset rowchk}
3849
3850 incr rowlaidout -1
3851 incr rowoptim -1
3852 incr numcommits -1
3853
3854 if {[info exists selectedline] && $selectedline > $row} {
3855 incr selectedline -1
3856 }
3857 redisplay
3858}
3859
Paul Mackerras94a2eed2005-08-07 15:27:57 +10003860# Don't change the text pane cursor if it is currently the hand cursor,
3861# showing that we are over a sha1 ID link.
3862proc settextcursor {c} {
3863 global ctext curtextcursor
3864
3865 if {[$ctext cget -cursor] == $curtextcursor} {
3866 $ctext config -cursor $c
3867 }
3868 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003869}
3870
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003871proc nowbusy {what} {
3872 global isbusy
3873
3874 if {[array names isbusy] eq {}} {
3875 . config -cursor watch
3876 settextcursor watch
3877 }
3878 set isbusy($what) 1
3879}
3880
3881proc notbusy {what} {
3882 global isbusy maincursor textcursor
3883
3884 catch {unset isbusy($what)}
3885 if {[array names isbusy] eq {}} {
3886 . config -cursor $maincursor
3887 settextcursor $textcursor
3888 }
3889}
3890
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003891proc findmatches {f} {
3892 global findtype foundstring foundstrlen
3893 if {$findtype == "Regexp"} {
3894 set matches [regexp -indices -all -inline $foundstring $f]
3895 } else {
3896 if {$findtype == "IgnCase"} {
3897 set str [string tolower $f]
3898 } else {
3899 set str $f
3900 }
3901 set matches {}
3902 set i 0
3903 while {[set j [string first $foundstring $str $i]] >= 0} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003904 lappend matches [list $j [expr {$j+$foundstrlen-1}]]
3905 set i [expr {$j + $foundstrlen}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003906 }
3907 }
3908 return $matches
3909}
3910
Paul Mackerras98f350e2005-05-15 05:56:51 +00003911proc dofind {} {
3912 global findtype findloc findstring markedmatches commitinfo
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003913 global numcommits displayorder linehtag linentag linedtag
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003914 global mainfont canv canv2 canv3 selectedline
Paul Mackerras8ed16482006-03-02 22:56:44 +11003915 global matchinglines foundstring foundstrlen matchstring
3916 global commitdata
Paul Mackerrasb74fd572005-07-16 07:46:13 -04003917
3918 stopfindproc
Paul Mackerras98f350e2005-05-15 05:56:51 +00003919 unmarkmatches
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003920 cancel_next_highlight
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003921 focus .
Paul Mackerras98f350e2005-05-15 05:56:51 +00003922 set matchinglines {}
Paul Mackerras98f350e2005-05-15 05:56:51 +00003923 if {$findtype == "IgnCase"} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003924 set foundstring [string tolower $findstring]
Paul Mackerras98f350e2005-05-15 05:56:51 +00003925 } else {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003926 set foundstring $findstring
Paul Mackerras98f350e2005-05-15 05:56:51 +00003927 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003928 set foundstrlen [string length $findstring]
3929 if {$foundstrlen == 0} return
Paul Mackerras8ed16482006-03-02 22:56:44 +11003930 regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
3931 set matchstring "*$matchstring*"
Paul Mackerras98f350e2005-05-15 05:56:51 +00003932 if {![info exists selectedline]} {
3933 set oldsel -1
3934 } else {
3935 set oldsel $selectedline
3936 }
3937 set didsel 0
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003938 set fldtypes {Headline Author Date Committer CDate Comments}
Paul Mackerras8ed16482006-03-02 22:56:44 +11003939 set l -1
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11003940 foreach id $displayorder {
3941 set d $commitdata($id)
Paul Mackerras8ed16482006-03-02 22:56:44 +11003942 incr l
3943 if {$findtype == "Regexp"} {
3944 set doesmatch [regexp $foundstring $d]
3945 } elseif {$findtype == "IgnCase"} {
3946 set doesmatch [string match -nocase $matchstring $d]
3947 } else {
3948 set doesmatch [string match $matchstring $d]
3949 }
3950 if {!$doesmatch} continue
Paul Mackerras8ed16482006-03-02 22:56:44 +11003951 if {![info exists commitinfo($id)]} {
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11003952 getcommit $id
Paul Mackerras8ed16482006-03-02 22:56:44 +11003953 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00003954 set info $commitinfo($id)
3955 set doesmatch 0
3956 foreach f $info ty $fldtypes {
3957 if {$findloc != "All fields" && $findloc != $ty} {
3958 continue
3959 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003960 set matches [findmatches $f]
Paul Mackerras98f350e2005-05-15 05:56:51 +00003961 if {$matches == {}} continue
3962 set doesmatch 1
3963 if {$ty == "Headline"} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003964 drawcommits $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00003965 markmatches $canv $l $f $linehtag($l) $matches $mainfont
3966 } elseif {$ty == "Author"} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003967 drawcommits $l
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003968 markmatches $canv2 $l $f $linentag($l) $matches $mainfont
Paul Mackerras98f350e2005-05-15 05:56:51 +00003969 } elseif {$ty == "Date"} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003970 drawcommits $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00003971 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
3972 }
3973 }
3974 if {$doesmatch} {
3975 lappend matchinglines $l
3976 if {!$didsel && $l > $oldsel} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003977 findselectline $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00003978 set didsel 1
3979 }
3980 }
3981 }
3982 if {$matchinglines == {}} {
3983 bell
3984 } elseif {!$didsel} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003985 findselectline [lindex $matchinglines 0]
3986 }
3987}
3988
3989proc findselectline {l} {
3990 global findloc commentend ctext
Paul Mackerrasd6982062005-08-06 22:06:06 +10003991 selectline $l 1
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003992 if {$findloc == "All fields" || $findloc == "Comments"} {
3993 # highlight the matches in the comments
3994 set f [$ctext get 1.0 $commentend]
3995 set matches [findmatches $f]
3996 foreach match $matches {
3997 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003998 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003999 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
4000 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004001 }
4002}
4003
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004004proc findnext {restart} {
Paul Mackerras98f350e2005-05-15 05:56:51 +00004005 global matchinglines selectedline
4006 if {![info exists matchinglines]} {
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004007 if {$restart} {
4008 dofind
4009 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004010 return
4011 }
4012 if {![info exists selectedline]} return
4013 foreach l $matchinglines {
4014 if {$l > $selectedline} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004015 findselectline $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00004016 return
4017 }
4018 }
4019 bell
4020}
4021
4022proc findprev {} {
4023 global matchinglines selectedline
4024 if {![info exists matchinglines]} {
4025 dofind
4026 return
4027 }
4028 if {![info exists selectedline]} return
4029 set prev {}
4030 foreach l $matchinglines {
4031 if {$l >= $selectedline} break
4032 set prev $l
4033 }
4034 if {$prev != {}} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004035 findselectline $prev
Paul Mackerras98f350e2005-05-15 05:56:51 +00004036 } else {
4037 bell
4038 }
4039}
4040
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004041proc stopfindproc {{done 0}} {
4042 global findprocpid findprocfile findids
4043 global ctext findoldcursor phase maincursor textcursor
4044 global findinprogress
4045
4046 catch {unset findids}
4047 if {[info exists findprocpid]} {
4048 if {!$done} {
4049 catch {exec kill $findprocpid}
4050 }
4051 catch {close $findprocfile}
4052 unset findprocpid
4053 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004054 catch {unset findinprogress}
4055 notbusy find
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004056}
4057
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004058# mark a commit as matching by putting a yellow background
4059# behind the headline
4060proc markheadline {l id} {
Paul Mackerras8ed16482006-03-02 22:56:44 +11004061 global canv mainfont linehtag
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004062
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004063 drawcommits $l
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004064 set bbox [$canv bbox $linehtag($l)]
4065 set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
4066 $canv lower $t
4067}
4068
4069# mark the bits of a headline, author or date that match a find string
Paul Mackerras98f350e2005-05-15 05:56:51 +00004070proc markmatches {canv l str tag matches font} {
4071 set bbox [$canv bbox $tag]
4072 set x0 [lindex $bbox 0]
4073 set y0 [lindex $bbox 1]
4074 set y1 [lindex $bbox 3]
4075 foreach match $matches {
4076 set start [lindex $match 0]
4077 set end [lindex $match 1]
4078 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004079 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
4080 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
4081 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
4082 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras98f350e2005-05-15 05:56:51 +00004083 -outline {} -tags matches -fill yellow]
4084 $canv lower $t
4085 }
4086}
4087
4088proc unmarkmatches {} {
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004089 global matchinglines findids
Paul Mackerras98f350e2005-05-15 05:56:51 +00004090 allcanvs delete matches
4091 catch {unset matchinglines}
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004092 catch {unset findids}
Paul Mackerras98f350e2005-05-15 05:56:51 +00004093}
4094
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004095proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004096 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004097 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00004098 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00004099 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00004100 set yfrac [lindex [$canv yview] 0]
4101 set y [expr {$y + $yfrac * $ymax}]
4102 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
4103 if {$l < 0} {
4104 set l 0
4105 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004106 if {$w eq $canv} {
4107 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
4108 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004109 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004110 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004111}
4112
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004113proc commit_descriptor {p} {
4114 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10004115 if {![info exists commitinfo($p)]} {
4116 getcommit $p
4117 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004118 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10004119 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004120 set l [lindex $commitinfo($p) 0]
4121 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004122 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004123}
4124
Paul Mackerras106288c2005-08-19 23:11:39 +10004125# append some text to the ctext widget, and make any SHA1 ID
4126# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004127proc appendwithlinks {text tags} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004128 global ctext commitrow linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10004129
4130 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004131 $ctext insert end $text $tags
Paul Mackerras106288c2005-08-19 23:11:39 +10004132 set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
4133 foreach l $links {
4134 set s [lindex $l 0]
4135 set e [lindex $l 1]
4136 set linkid [string range $text $s $e]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004137 if {![info exists commitrow($curview,$linkid)]} continue
Paul Mackerras106288c2005-08-19 23:11:39 +10004138 incr e
4139 $ctext tag add link "$start + $s c" "$start + $e c"
4140 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004141 $ctext tag bind link$linknum <1> \
4142 [list selectline $commitrow($curview,$linkid) 1]
Paul Mackerras106288c2005-08-19 23:11:39 +10004143 incr linknum
4144 }
4145 $ctext tag conf link -foreground blue -underline 1
4146 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
4147 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
4148}
4149
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004150proc viewnextline {dir} {
4151 global canv linespc
4152
4153 $canv delete hover
4154 set ymax [lindex [$canv cget -scrollregion] 3]
4155 set wnow [$canv yview]
4156 set wtop [expr {[lindex $wnow 0] * $ymax}]
4157 set newtop [expr {$wtop + $dir * $linespc}]
4158 if {$newtop < 0} {
4159 set newtop 0
4160 } elseif {$newtop > $ymax} {
4161 set newtop $ymax
4162 }
4163 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
4164}
4165
Paul Mackerrasef030b82006-06-04 11:50:38 +10004166# add a list of tag or branch names at position pos
4167# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10004168proc appendrefs {pos ids var} {
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004169 global ctext commitrow linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004170
Paul Mackerrasef030b82006-06-04 11:50:38 +10004171 if {[catch {$ctext index $pos}]} {
4172 return 0
4173 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004174 $ctext conf -state normal
4175 $ctext delete $pos "$pos lineend"
4176 set tags {}
4177 foreach id $ids {
4178 foreach tag [set $var\($id\)] {
4179 lappend tags [list $tag $id]
4180 }
4181 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004182 if {[llength $tags] > $maxrefs} {
4183 $ctext insert $pos "many ([llength $tags])"
4184 } else {
4185 set tags [lsort -index 0 -decreasing $tags]
4186 set sep {}
4187 foreach ti $tags {
4188 set id [lindex $ti 1]
4189 set lk link$linknum
4190 incr linknum
4191 $ctext tag delete $lk
4192 $ctext insert $pos $sep
4193 $ctext insert $pos [lindex $ti 0] $lk
4194 if {[info exists commitrow($curview,$id)]} {
4195 $ctext tag conf $lk -foreground blue
4196 $ctext tag bind $lk <1> \
4197 [list selectline $commitrow($curview,$id) 1]
4198 $ctext tag conf $lk -underline 1
4199 $ctext tag bind $lk <Enter> { %W configure -cursor hand2 }
4200 $ctext tag bind $lk <Leave> \
4201 { %W configure -cursor $curtextcursor }
4202 }
4203 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004204 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004205 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004206 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10004207 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004208}
4209
4210# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10004211proc dispneartags {delay} {
4212 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004213
4214 if {![info exists selectedline] || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10004215 after cancel dispnexttag
4216 if {$delay} {
4217 after 200 dispnexttag
4218 set tagphase -1
4219 } else {
4220 after idle dispnexttag
4221 set tagphase 0
4222 }
4223}
4224
4225proc dispnexttag {} {
4226 global selectedline currentid showneartags tagphase ctext
4227
4228 if {![info exists selectedline] || !$showneartags} return
4229 switch -- $tagphase {
4230 0 {
4231 set dtags [desctags $currentid]
4232 if {$dtags ne {}} {
4233 appendrefs precedes $dtags idtags
4234 }
4235 }
4236 1 {
4237 set atags [anctags $currentid]
4238 if {$atags ne {}} {
4239 appendrefs follows $atags idtags
4240 }
4241 }
4242 2 {
4243 set dheads [descheads $currentid]
4244 if {$dheads ne {}} {
4245 if {[appendrefs branch $dheads idheads] > 1
4246 && [$ctext get "branch -3c"] eq "h"} {
4247 # turn "Branch" into "Branches"
4248 $ctext conf -state normal
4249 $ctext insert "branch -2c" "es"
4250 $ctext conf -state disabled
4251 }
4252 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004253 }
4254 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004255 if {[incr tagphase] <= 2} {
4256 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004257 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004258}
4259
Paul Mackerrasd6982062005-08-06 22:06:06 +10004260proc selectline {l isnew} {
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004261 global canv canv2 canv3 ctext commitinfo selectedline
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004262 global displayorder linehtag linentag linedtag
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004263 global canvy0 linespc parentlist children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004264 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004265 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004266 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10004267 global cmitmode showneartags allcommits
Paul Mackerrasd6982062005-08-06 22:06:06 +10004268
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004269 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00004270 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10004271 normalline
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004272 cancel_next_highlight
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004273 if {$l < 0 || $l >= $numcommits} return
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004274 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00004275 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00004276 set ytop [expr {$y - $linespc - 1}]
4277 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004278 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004279 set wtop [expr {[lindex $wnow 0] * $ymax}]
4280 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00004281 set wh [expr {$wbot - $wtop}]
4282 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00004283 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00004284 if {$ybot < $wtop} {
4285 set newtop [expr {$y - $wh / 2.0}]
4286 } else {
4287 set newtop $ytop
4288 if {$newtop > $wtop - $linespc} {
4289 set newtop [expr {$wtop - $linespc}]
4290 }
Paul Mackerras17386062005-05-18 22:51:00 +00004291 }
Paul Mackerras58422152005-05-19 10:56:42 +00004292 } elseif {$ybot > $wbot} {
4293 if {$ytop > $wbot} {
4294 set newtop [expr {$y - $wh / 2.0}]
4295 } else {
4296 set newtop [expr {$ybot - $wh}]
4297 if {$newtop < $wtop + $linespc} {
4298 set newtop [expr {$wtop + $linespc}]
4299 }
Paul Mackerras17386062005-05-18 22:51:00 +00004300 }
Paul Mackerras58422152005-05-19 10:56:42 +00004301 }
4302 if {$newtop != $wtop} {
4303 if {$newtop < 0} {
4304 set newtop 0
4305 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004306 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004307 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004308 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004309
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004310 if {![info exists linehtag($l)]} return
4311 $canv delete secsel
4312 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
4313 -tags secsel -fill [$canv cget -selectbackground]]
4314 $canv lower $t
4315 $canv2 delete secsel
4316 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
4317 -tags secsel -fill [$canv2 cget -selectbackground]]
4318 $canv2 lower $t
4319 $canv3 delete secsel
4320 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
4321 -tags secsel -fill [$canv3 cget -selectbackground]]
4322 $canv3 lower $t
4323
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004324 if {$isnew} {
4325 addtohistory [list selectline $l 0]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004326 }
4327
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004328 set selectedline $l
4329
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004330 set id [lindex $displayorder $l]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004331 set currentid $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004332 $sha1entry delete 0 end
4333 $sha1entry insert 0 $id
4334 $sha1entry selection from 0
4335 $sha1entry selection to end
Paul Mackerras164ff272006-05-29 19:50:02 +10004336 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004337
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004338 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004339 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10004340 set linknum 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00004341 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11004342 set date [formatdate [lindex $info 2]]
4343 $ctext insert end "Author: [lindex $info 1] $date\n"
4344 set date [formatdate [lindex $info 4]]
4345 $ctext insert end "Committer: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004346 if {[info exists idtags($id)]} {
4347 $ctext insert end "Tags:"
4348 foreach tag $idtags($id) {
4349 $ctext insert end " $tag"
4350 }
4351 $ctext insert end "\n"
4352 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004353
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004354 set headers {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004355 set olds [lindex $parentlist $l]
4356 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004357 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10004358 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004359 if {$np >= $mergemax} {
4360 set tag mmax
4361 } else {
4362 set tag m$np
4363 }
4364 $ctext insert end "Parent: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004365 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004366 incr np
4367 }
4368 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004369 foreach p $olds {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004370 append headers "Parent: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004371 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004372 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004373
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004374 foreach c $children($curview,$id) {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004375 append headers "Child: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004376 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004377
4378 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004379 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004380 if {$showneartags} {
4381 if {![info exists allcommits]} {
4382 getallcommits
4383 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004384 $ctext insert end "Branch: "
4385 $ctext mark set branch "end -1c"
4386 $ctext mark gravity branch left
Paul Mackerrasef030b82006-06-04 11:50:38 +10004387 $ctext insert end "\nFollows: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004388 $ctext mark set follows "end -1c"
4389 $ctext mark gravity follows left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004390 $ctext insert end "\nPrecedes: "
4391 $ctext mark set precedes "end -1c"
4392 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004393 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10004394 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004395 }
4396 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10004397 set comment [lindex $info 5]
4398 if {[string first "\r" $comment] >= 0} {
4399 set comment [string map {"\r" "\n "} $comment]
4400 }
4401 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10004402
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004403 $ctext tag delete Comments
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004404 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004405 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004406 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004407
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004408 init_flist "Comments"
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004409 if {$cmitmode eq "tree"} {
4410 gettree $id
4411 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11004412 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11004413 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004414 mergediff $id $l
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004415 }
4416}
4417
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004418proc selfirstline {} {
4419 unmarkmatches
4420 selectline 0 1
4421}
4422
4423proc sellastline {} {
4424 global numcommits
4425 unmarkmatches
4426 set l [expr {$numcommits - 1}]
4427 selectline $l 1
4428}
4429
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004430proc selnextline {dir} {
4431 global selectedline
4432 if {![info exists selectedline]} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004433 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004434 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004435 selectline $l 1
4436}
4437
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004438proc selnextpage {dir} {
4439 global canv linespc selectedline numcommits
4440
4441 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
4442 if {$lpp < 1} {
4443 set lpp 1
4444 }
4445 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10004446 drawvisible
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004447 if {![info exists selectedline]} return
4448 set l [expr {$selectedline + $dir * $lpp}]
4449 if {$l < 0} {
4450 set l 0
4451 } elseif {$l >= $numcommits} {
4452 set l [expr $numcommits - 1]
4453 }
4454 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004455 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004456}
4457
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004458proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004459 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004460
4461 catch {unset selectedline}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004462 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004463 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10004464 rhighlight_none
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004465 cancel_next_highlight
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004466}
4467
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004468proc reselectline {} {
4469 global selectedline
4470
4471 if {[info exists selectedline]} {
4472 selectline $selectedline 0
4473 }
4474}
4475
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004476proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004477 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004478
Paul Mackerras2516dae2006-04-21 10:35:31 +10004479 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004480 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10004481 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004482 return
4483 }
4484
4485 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004486 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004487 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004488 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004489 }
4490 incr historyindex
4491 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004492 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004493 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004494 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004495 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004496 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004497}
4498
Paul Mackerras2516dae2006-04-21 10:35:31 +10004499proc godo {elt} {
4500 global curview
4501
4502 set view [lindex $elt 0]
4503 set cmd [lindex $elt 1]
4504 if {$curview != $view} {
4505 showview $view
4506 }
4507 eval $cmd
4508}
4509
Paul Mackerrasd6982062005-08-06 22:06:06 +10004510proc goback {} {
4511 global history historyindex
4512
4513 if {$historyindex > 1} {
4514 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10004515 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004516 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004517 }
4518 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004519 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004520 }
4521}
4522
4523proc goforw {} {
4524 global history historyindex
4525
4526 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004527 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004528 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10004529 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004530 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004531 }
4532 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004533 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004534 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004535}
4536
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004537proc gettree {id} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004538 global treefilelist treeidlist diffids diffmergeid treepending nullid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004539
4540 set diffids $id
4541 catch {unset diffmergeid}
4542 if {![info exists treefilelist($id)]} {
4543 if {![info exists treepending]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004544 if {$id ne $nullid} {
4545 set cmd [concat | git ls-tree -r $id]
4546 } else {
4547 set cmd [concat | git ls-files]
4548 }
4549 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004550 return
4551 }
4552 set treepending $id
4553 set treefilelist($id) {}
4554 set treeidlist($id) {}
4555 fconfigure $gtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004556 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004557 }
4558 } else {
4559 setfilelist $id
4560 }
4561}
4562
4563proc gettreeline {gtf id} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004564 global treefilelist treeidlist treepending cmitmode diffids nullid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004565
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004566 set nl 0
4567 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004568 if {$diffids ne $nullid} {
4569 set tl [split $line "\t"]
4570 if {[lindex $tl 0 1] ne "blob"} continue
4571 set sha1 [lindex $tl 0 2]
4572 set fname [lindex $tl 1]
4573 if {[string index $fname 0] eq "\""} {
4574 set fname [lindex $fname 0]
4575 }
4576 lappend treeidlist($id) $sha1
4577 } else {
4578 set fname $line
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004579 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004580 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004581 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004582 if {![eof $gtf]} {
4583 return [expr {$nl >= 1000? 2: 1}]
4584 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004585 close $gtf
4586 unset treepending
4587 if {$cmitmode ne "tree"} {
4588 if {![info exists diffmergeid]} {
4589 gettreediffs $diffids
4590 }
4591 } elseif {$id ne $diffids} {
4592 gettree $diffids
4593 } else {
4594 setfilelist $id
4595 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004596 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004597}
4598
4599proc showfile {f} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004600 global treefilelist treeidlist diffids nullid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004601 global ctext commentend
4602
4603 set i [lsearch -exact $treefilelist($diffids) $f]
4604 if {$i < 0} {
4605 puts "oops, $f not in list for id $diffids"
4606 return
4607 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004608 if {$diffids ne $nullid} {
4609 set blob [lindex $treeidlist($diffids) $i]
4610 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
4611 puts "oops, error reading blob $blob: $err"
4612 return
4613 }
4614 } else {
4615 if {[catch {set bf [open $f r]} err]} {
4616 puts "oops, can't read $f: $err"
4617 return
4618 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004619 }
4620 fconfigure $bf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004621 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004622 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004623 clear_ctext $commentend
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004624 $ctext insert end "\n"
4625 $ctext insert end "$f\n" filesep
4626 $ctext config -state disabled
4627 $ctext yview $commentend
4628}
4629
4630proc getblobline {bf id} {
4631 global diffids cmitmode ctext
4632
4633 if {$id ne $diffids || $cmitmode ne "tree"} {
4634 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004635 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004636 }
4637 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004638 set nl 0
4639 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004640 $ctext insert end "$line\n"
4641 }
4642 if {[eof $bf]} {
4643 # delete last newline
4644 $ctext delete "end - 2c" "end - 1c"
4645 close $bf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004646 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004647 }
4648 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004649 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004650}
4651
Paul Mackerras79b2c752006-04-02 20:47:40 +10004652proc mergediff {id l} {
4653 global diffmergeid diffopts mdifffd
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004654 global diffids
Paul Mackerras79b2c752006-04-02 20:47:40 +10004655 global parentlist
Paul Mackerrase2ed4322005-07-17 03:39:44 -04004656
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004657 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004658 set diffids $id
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004659 # this doesn't seem to actually affect anything...
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004660 set env(GIT_DIFF_OPTS) $diffopts
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03004661 set cmd [concat | git diff-tree --no-commit-id --cc $id]
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004662 if {[catch {set mdf [open $cmd r]} err]} {
4663 error_popup "Error getting merge diffs: $err"
4664 return
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004665 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004666 fconfigure $mdf -blocking 0
4667 set mdifffd($id) $mdf
Paul Mackerras79b2c752006-04-02 20:47:40 +10004668 set np [llength [lindex $parentlist $l]]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004669 filerun $mdf [list getmergediffline $mdf $id $np]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004670}
4671
Paul Mackerras79b2c752006-04-02 20:47:40 +10004672proc getmergediffline {mdf id np} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004673 global diffmergeid ctext cflist mergemax
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004674 global difffilestart mdifffd
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004675
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004676 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004677 set nr 0
4678 while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
4679 if {![info exists diffmergeid] || $id != $diffmergeid
4680 || $mdf != $mdifffd($id)} {
4681 close $mdf
4682 return 0
4683 }
4684 if {[regexp {^diff --cc (.*)} $line match fname]} {
4685 # start of a new file
4686 $ctext insert end "\n"
4687 set here [$ctext index "end - 1c"]
4688 lappend difffilestart $here
4689 add_flist [list $fname]
4690 set l [expr {(78 - [string length $fname]) / 2}]
4691 set pad [string range "----------------------------------------" 1 $l]
4692 $ctext insert end "$pad $fname $pad\n" filesep
4693 } elseif {[regexp {^@@} $line]} {
4694 $ctext insert end "$line\n" hunksep
4695 } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
4696 # do nothing
4697 } else {
4698 # parse the prefix - one ' ', '-' or '+' for each parent
4699 set spaces {}
4700 set minuses {}
4701 set pluses {}
4702 set isbad 0
4703 for {set j 0} {$j < $np} {incr j} {
4704 set c [string range $line $j $j]
4705 if {$c == " "} {
4706 lappend spaces $j
4707 } elseif {$c == "-"} {
4708 lappend minuses $j
4709 } elseif {$c == "+"} {
4710 lappend pluses $j
4711 } else {
4712 set isbad 1
4713 break
4714 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004715 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004716 set tags {}
4717 set num {}
4718 if {!$isbad && $minuses ne {} && $pluses eq {}} {
4719 # line doesn't appear in result, parents in $minuses have the line
4720 set num [lindex $minuses 0]
4721 } elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
4722 # line appears in result, parents in $pluses don't have the line
4723 lappend tags mresult
4724 set num [lindex $spaces 0]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004725 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004726 if {$num ne {}} {
4727 if {$num >= $mergemax} {
4728 set num "max"
4729 }
4730 lappend tags m$num
4731 }
4732 $ctext insert end "$line\n" $tags
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004733 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004734 }
4735 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004736 if {[eof $mdf]} {
4737 close $mdf
4738 return 0
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05004739 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004740 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05004741}
4742
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004743proc startdiff {ids} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004744 global treediffs diffids treepending diffmergeid nullid
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004745
4746 set diffids $ids
4747 catch {unset diffmergeid}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004748 if {![info exists treediffs($ids)] || [lsearch -exact $ids $nullid] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004749 if {![info exists treepending]} {
4750 gettreediffs $ids
4751 }
4752 } else {
4753 addtocflist $ids
4754 }
4755}
4756
4757proc addtocflist {ids} {
4758 global treediffs cflist
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004759 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004760 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004761}
4762
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004763proc diffcmd {ids flags} {
4764 global nullid
4765
4766 set i [lsearch -exact $ids $nullid]
4767 if {$i >= 0} {
4768 set cmd [concat | git diff-index $flags]
4769 if {[llength $ids] > 1} {
4770 if {$i == 0} {
4771 lappend cmd -R [lindex $ids 1]
4772 } else {
4773 lappend cmd [lindex $ids 0]
4774 }
4775 } else {
4776 lappend cmd HEAD
4777 }
4778 } else {
4779 set cmd [concat | git diff-tree --no-commit-id -r $flags $ids]
4780 }
4781 return $cmd
4782}
4783
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004784proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004785 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004786
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004787 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004788 set treediff {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004789 if {[catch {set gdtf [open [diffcmd $ids {}] r]}]} return
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004790 fconfigure $gdtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004791 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004792}
4793
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004794proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004795 global treediff treediffs treepending diffids diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004796 global cmitmode
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004797
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004798 set nr 0
4799 while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
4800 set file [lindex $line 5]
4801 lappend treediff $file
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004802 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004803 if {![eof $gdtf]} {
4804 return [expr {$nr >= 1000? 2: 1}]
4805 }
4806 close $gdtf
4807 set treediffs($ids) $treediff
4808 unset treepending
4809 if {$cmitmode eq "tree"} {
4810 gettree $diffids
4811 } elseif {$ids != $diffids} {
4812 if {![info exists diffmergeid]} {
4813 gettreediffs $diffids
4814 }
4815 } else {
4816 addtocflist $ids
4817 }
4818 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004819}
4820
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004821proc getblobdiffs {ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004822 global diffopts blobdifffd diffids env curdifftag curtagstart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004823 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004824
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004825 set env(GIT_DIFF_OPTS) $diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004826 if {[catch {set bdf [open [diffcmd $ids {-p -C}] r]} err]} {
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004827 puts "error getting diffs: $err"
4828 return
4829 }
Paul Mackerras4f2c2642005-07-17 11:11:44 -04004830 set diffinhdr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004831 fconfigure $bdf -blocking 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004832 set blobdifffd($ids) $bdf
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004833 set curdifftag Comments
4834 set curtagstart 0.0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004835 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004836}
4837
Paul Mackerras89b11d32006-05-02 19:55:31 +10004838proc setinlist {var i val} {
4839 global $var
4840
4841 while {[llength [set $var]] < $i} {
4842 lappend $var {}
4843 }
4844 if {[llength [set $var]] == $i} {
4845 lappend $var $val
4846 } else {
4847 lset $var $i $val
4848 }
4849}
4850
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004851proc getblobdiffline {bdf ids} {
Paul Mackerras4f2c2642005-07-17 11:11:44 -04004852 global diffids blobdifffd ctext curdifftag curtagstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04004853 global diffnexthead diffnextnote difffilestart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004854 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004855
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004856 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004857 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004858 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
4859 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
4860 close $bdf
4861 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10004862 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004863 if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} {
4864 # start of a new file
4865 $ctext insert end "\n"
4866 $ctext tag add $curdifftag $curtagstart end
4867 set here [$ctext index "end - 1c"]
4868 set curtagstart $here
4869 set header $newname
4870 set i [lsearch -exact $treediffs($ids) $fname]
Paul Mackerras89b11d32006-05-02 19:55:31 +10004871 if {$i >= 0} {
4872 setinlist difffilestart $i $here
4873 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004874 if {$newname ne $fname} {
4875 set i [lsearch -exact $treediffs($ids) $newname]
4876 if {$i >= 0} {
4877 setinlist difffilestart $i $here
4878 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004879 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004880 set curdifftag "f:$fname"
4881 $ctext tag delete $curdifftag
4882 set l [expr {(78 - [string length $header]) / 2}]
4883 set pad [string range "----------------------------------------" \
4884 1 $l]
4885 $ctext insert end "$pad $header $pad\n" filesep
4886 set diffinhdr 1
4887 } elseif {$diffinhdr && [string compare -length 3 $line "---"] == 0} {
4888 # do nothing
4889 } elseif {$diffinhdr && [string compare -length 3 $line "+++"] == 0} {
4890 set diffinhdr 0
4891 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
4892 $line match f1l f1c f2l f2c rest]} {
4893 $ctext insert end "$line\n" hunksep
4894 set diffinhdr 0
4895 } else {
4896 set x [string range $line 0 0]
4897 if {$x == "-" || $x == "+"} {
4898 set tag [expr {$x == "+"}]
4899 $ctext insert end "$line\n" d$tag
4900 } elseif {$x == " "} {
4901 $ctext insert end "$line\n"
4902 } elseif {$diffinhdr || $x == "\\"} {
4903 # e.g. "\ No newline at end of file"
4904 $ctext insert end "$line\n" filesep
4905 } else {
4906 # Something else we don't recognize
4907 if {$curdifftag != "Comments"} {
4908 $ctext insert end "\n"
4909 $ctext tag add $curdifftag $curtagstart end
4910 set curtagstart [$ctext index "end - 1c"]
4911 set curdifftag Comments
4912 }
4913 $ctext insert end "$line\n" filesep
4914 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004915 }
4916 }
4917 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004918 if {[eof $bdf]} {
4919 close $bdf
4920 if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
4921 $ctext tag add $curdifftag $curtagstart end
4922 }
4923 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004924 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004925 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004926}
4927
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10004928proc changediffdisp {} {
4929 global ctext diffelide
4930
4931 $ctext tag conf d0 -elide [lindex $diffelide 0]
4932 $ctext tag conf d1 -elide [lindex $diffelide 1]
4933}
4934
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09004935proc prevfile {} {
4936 global difffilestart ctext
4937 set prev [lindex $difffilestart 0]
4938 set here [$ctext index @0,0]
4939 foreach loc $difffilestart {
4940 if {[$ctext compare $loc >= $here]} {
4941 $ctext yview $prev
4942 return
4943 }
4944 set prev $loc
4945 }
4946 $ctext yview $prev
4947}
4948
Paul Mackerras39ad8572005-05-19 12:35:53 +00004949proc nextfile {} {
4950 global difffilestart ctext
4951 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004952 foreach loc $difffilestart {
4953 if {[$ctext compare $loc > $here]} {
4954 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09004955 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00004956 }
4957 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00004958}
4959
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004960proc clear_ctext {{first 1.0}} {
4961 global ctext smarktop smarkbot
4962
Paul Mackerras1902c272006-05-25 21:25:13 +10004963 set l [lindex [split $first .] 0]
4964 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
4965 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004966 }
Paul Mackerras1902c272006-05-25 21:25:13 +10004967 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
4968 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004969 }
4970 $ctext delete $first end
4971}
4972
4973proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10004974 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004975
4976 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10004977 if {[catch {$ctext index anchor}]} {
4978 # no anchor set, use start of selection, or of visible area
4979 set sel [$ctext tag ranges sel]
4980 if {$sel ne {}} {
4981 $ctext mark set anchor [lindex $sel 0]
4982 } elseif {$searchdirn eq "-forwards"} {
4983 $ctext mark set anchor @0,0
4984 } else {
4985 $ctext mark set anchor @0,[winfo height $ctext]
4986 }
4987 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004988 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10004989 set here [$ctext search $searchdirn -- $searchstring anchor]
4990 if {$here ne {}} {
4991 $ctext see $here
4992 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004993 searchmarkvisible 1
4994 }
4995}
4996
4997proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10004998 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004999
5000 focus $sstring
5001 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10005002 set searchdirn -forwards
5003 if {$searchstring ne {}} {
5004 set sel [$ctext tag ranges sel]
5005 if {$sel ne {}} {
5006 set start "[lindex $sel 0] + 1c"
5007 } elseif {[catch {set start [$ctext index anchor]}]} {
5008 set start "@0,0"
5009 }
5010 set match [$ctext search -count mlen -- $searchstring $start]
5011 $ctext tag remove sel 1.0 end
5012 if {$match eq {}} {
5013 bell
5014 return
5015 }
5016 $ctext see $match
5017 set mend "$match + $mlen c"
5018 $ctext tag add sel $match $mend
5019 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005020 }
Paul Mackerras1902c272006-05-25 21:25:13 +10005021}
5022
5023proc dosearchback {} {
5024 global sstring ctext searchstring searchdirn
5025
5026 focus $sstring
5027 $sstring icursor end
5028 set searchdirn -backwards
5029 if {$searchstring ne {}} {
5030 set sel [$ctext tag ranges sel]
5031 if {$sel ne {}} {
5032 set start [lindex $sel 0]
5033 } elseif {[catch {set start [$ctext index anchor]}]} {
5034 set start @0,[winfo height $ctext]
5035 }
5036 set match [$ctext search -backwards -count ml -- $searchstring $start]
5037 $ctext tag remove sel 1.0 end
5038 if {$match eq {}} {
5039 bell
5040 return
5041 }
5042 $ctext see $match
5043 set mend "$match + $ml c"
5044 $ctext tag add sel $match $mend
5045 $ctext mark unset anchor
5046 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005047}
5048
5049proc searchmark {first last} {
5050 global ctext searchstring
5051
5052 set mend $first.0
5053 while {1} {
5054 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
5055 if {$match eq {}} break
5056 set mend "$match + $mlen c"
5057 $ctext tag add found $match $mend
5058 }
5059}
5060
5061proc searchmarkvisible {doall} {
5062 global ctext smarktop smarkbot
5063
5064 set topline [lindex [split [$ctext index @0,0] .] 0]
5065 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
5066 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
5067 # no overlap with previous
5068 searchmark $topline $botline
5069 set smarktop $topline
5070 set smarkbot $botline
5071 } else {
5072 if {$topline < $smarktop} {
5073 searchmark $topline [expr {$smarktop-1}]
5074 set smarktop $topline
5075 }
5076 if {$botline > $smarkbot} {
5077 searchmark [expr {$smarkbot+1}] $botline
5078 set smarkbot $botline
5079 }
5080 }
5081}
5082
5083proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005084 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005085
Junio C Hamanoe9937d22007-02-01 08:46:38 -05005086 .bleft.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005087 if {$searchstring ne {}} {
5088 searchmarkvisible 0
5089 }
5090}
5091
Paul Mackerras1d10f362005-05-15 12:55:47 +00005092proc setcoords {} {
5093 global linespc charspc canvx0 canvy0 mainfont
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005094 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10005095
Paul Mackerras1d10f362005-05-15 12:55:47 +00005096 set linespc [font metrics $mainfont -linespace]
5097 set charspc [font measure $mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005098 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
5099 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005100 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10005101 set xspc1(0) $linespc
5102 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00005103}
Paul Mackerras1db95b02005-05-09 04:08:39 +00005104
Paul Mackerras1d10f362005-05-15 12:55:47 +00005105proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005106 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005107 global selectedline
5108
5109 set ymax [lindex [$canv cget -scrollregion] 3]
5110 if {$ymax eq {} || $ymax == 0} return
5111 set span [$canv yview]
5112 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005113 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005114 allcanvs yview moveto [lindex $span 0]
5115 drawvisible
5116 if {[info exists selectedline]} {
5117 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005118 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00005119 }
5120}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005121
5122proc incrfont {inc} {
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005123 global mainfont textfont ctext canv phase cflist
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005124 global charspc tabstop
Paul Mackerrascfb45632005-05-31 12:14:42 +00005125 global stopped entries
Paul Mackerras1d10f362005-05-15 12:55:47 +00005126 unmarkmatches
5127 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
Paul Mackerras1d10f362005-05-15 12:55:47 +00005128 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
5129 setcoords
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005130 $ctext conf -font $textfont -tabs "[expr {$tabstop * $charspc}]"
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005131 $cflist conf -font $textfont
Paul Mackerras1d10f362005-05-15 12:55:47 +00005132 $ctext tag conf filesep -font [concat $textfont bold]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005133 foreach e $entries {
5134 $e conf -font $mainfont
5135 }
Paul Mackerras22626ef2006-04-17 09:56:02 +10005136 if {$phase eq "getcommits"} {
Paul Mackerras1d10f362005-05-15 12:55:47 +00005137 $canv itemconf textitems -font $mainfont
5138 }
5139 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00005140}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005141
Paul Mackerrasee3dc722005-06-25 16:37:13 +10005142proc clearsha1 {} {
5143 global sha1entry sha1string
5144 if {[string length $sha1string] == 40} {
5145 $sha1entry delete 0 end
5146 }
5147}
5148
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005149proc sha1change {n1 n2 op} {
5150 global sha1string currentid sha1but
5151 if {$sha1string == {}
5152 || ([info exists currentid] && $sha1string == $currentid)} {
5153 set state disabled
5154 } else {
5155 set state normal
5156 }
5157 if {[$sha1but cget -state] == $state} return
5158 if {$state == "normal"} {
5159 $sha1but conf -state normal -relief raised -text "Goto: "
5160 } else {
5161 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
5162 }
5163}
5164
5165proc gotocommit {} {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005166 global sha1string currentid commitrow tagids headids
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005167 global displayorder numcommits curview
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005168
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005169 if {$sha1string == {}
5170 || ([info exists currentid] && $sha1string == $currentid)} return
5171 if {[info exists tagids($sha1string)]} {
5172 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11005173 } elseif {[info exists headids($sha1string)]} {
5174 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005175 } else {
5176 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005177 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
5178 set matches {}
Paul Mackerras8ed16482006-03-02 22:56:44 +11005179 foreach i $displayorder {
5180 if {[string match $id* $i]} {
5181 lappend matches $i
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005182 }
5183 }
5184 if {$matches ne {}} {
5185 if {[llength $matches] > 1} {
5186 error_popup "Short SHA1 id $id is ambiguous"
5187 return
5188 }
5189 set id [lindex $matches 0]
5190 }
5191 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005192 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005193 if {[info exists commitrow($curview,$id)]} {
5194 selectline $commitrow($curview,$id) 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005195 return
5196 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005197 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005198 set type "SHA1 id"
5199 } else {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005200 set type "Tag/Head"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005201 }
5202 error_popup "$type $sha1string is not known"
5203}
5204
Paul Mackerras84ba7342005-06-17 00:12:26 +00005205proc lineenter {x y id} {
5206 global hoverx hovery hoverid hovertimer
5207 global commitinfo canv
5208
Paul Mackerras8ed16482006-03-02 22:56:44 +11005209 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00005210 set hoverx $x
5211 set hovery $y
5212 set hoverid $id
5213 if {[info exists hovertimer]} {
5214 after cancel $hovertimer
5215 }
5216 set hovertimer [after 500 linehover]
5217 $canv delete hover
5218}
5219
5220proc linemotion {x y id} {
5221 global hoverx hovery hoverid hovertimer
5222
5223 if {[info exists hoverid] && $id == $hoverid} {
5224 set hoverx $x
5225 set hovery $y
5226 if {[info exists hovertimer]} {
5227 after cancel $hovertimer
5228 }
5229 set hovertimer [after 500 linehover]
5230 }
5231}
5232
5233proc lineleave {id} {
5234 global hoverid hovertimer canv
5235
5236 if {[info exists hoverid] && $id == $hoverid} {
5237 $canv delete hover
5238 if {[info exists hovertimer]} {
5239 after cancel $hovertimer
5240 unset hovertimer
5241 }
5242 unset hoverid
5243 }
5244}
5245
5246proc linehover {} {
5247 global hoverx hovery hoverid hovertimer
5248 global canv linespc lthickness
5249 global commitinfo mainfont
5250
5251 set text [lindex $commitinfo($hoverid) 0]
5252 set ymax [lindex [$canv cget -scrollregion] 3]
5253 if {$ymax == {}} return
5254 set yfrac [lindex [$canv yview] 0]
5255 set x [expr {$hoverx + 2 * $linespc}]
5256 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
5257 set x0 [expr {$x - 2 * $lthickness}]
5258 set y0 [expr {$y - 2 * $lthickness}]
5259 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
5260 set y1 [expr {$y + $linespc + 2 * $lthickness}]
5261 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
5262 -fill \#ffff80 -outline black -width 1 -tags hover]
5263 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10005264 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
5265 -font $mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00005266 $canv raise $t
5267}
5268
Paul Mackerras9843c302005-08-30 10:57:11 +10005269proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005270 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10005271
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005272 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10005273 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005274 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005275 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005276 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005277 if {abs([yc $row] - $y) < $thresh} {
5278 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10005279 }
5280 }
5281 return {}
5282}
5283
Paul Mackerrasf6342482006-02-28 10:02:03 +11005284proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005285 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10005286
Paul Mackerrasf6342482006-02-28 10:02:03 +11005287 # 1 <-> 2, 3 <-> 4, etc...
5288 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005289 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005290 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10005291 set ymax [lindex [$canv cget -scrollregion] 3]
5292 if {$ymax eq {} || $ymax <= 0} return
5293 set view [$canv yview]
5294 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
5295 set yfrac [expr {$yt / $ymax - $yspan / 2}]
5296 if {$yfrac < 0} {
5297 set yfrac 0
5298 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11005299 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10005300}
5301
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005302proc lineclick {x y id isnew} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005303 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005304
Paul Mackerras8ed16482006-03-02 22:56:44 +11005305 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005306 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005307 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10005308 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005309 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10005310 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10005311 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005312 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005313 if {$isnew} {
5314 set ymax [lindex [$canv cget -scrollregion] 3]
5315 if {$ymax eq {}} return
5316 set yfrac [lindex [$canv yview] 0]
5317 set y [expr {$y + $yfrac * $ymax}]
5318 }
5319 set dirn [clickisonarrow $id $y]
5320 if {$dirn ne {}} {
5321 arrowjump $id $dirn $y
5322 return
5323 }
5324
5325 if {$isnew} {
5326 addtohistory [list lineclick $x $y $id 0]
5327 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005328 # fill the details pane with info about this line
5329 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005330 clear_ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005331 $ctext tag conf link -foreground blue -underline 1
5332 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
5333 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
5334 $ctext insert end "Parent:\t"
5335 $ctext insert end $id [list link link0]
5336 $ctext tag bind link0 <1> [list selbyid $id]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005337 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005338 $ctext insert end "\n\t[lindex $info 0]\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005339 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11005340 set date [formatdate [lindex $info 2]]
5341 $ctext insert end "\tDate:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005342 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005343 if {$kids ne {}} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005344 $ctext insert end "\nChildren:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005345 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10005346 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005347 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11005348 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005349 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005350 $ctext insert end "\n\t"
5351 $ctext insert end $child [list link link$i]
5352 $ctext tag bind link$i <1> [list selbyid $child]
5353 $ctext insert end "\n\t[lindex $info 0]"
5354 $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11005355 set date [formatdate [lindex $info 2]]
5356 $ctext insert end "\n\tDate:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005357 }
5358 }
5359 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005360 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005361}
5362
Paul Mackerras9843c302005-08-30 10:57:11 +10005363proc normalline {} {
5364 global thickerline
5365 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005366 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10005367 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005368 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005369 }
5370}
5371
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005372proc selbyid {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005373 global commitrow curview
5374 if {[info exists commitrow($curview,$id)]} {
5375 selectline $commitrow($curview,$id) 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005376 }
5377}
5378
5379proc mstime {} {
5380 global startmstime
5381 if {![info exists startmstime]} {
5382 set startmstime [clock clicks -milliseconds]
5383 }
5384 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
5385}
5386
5387proc rowmenu {x y id} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005388 global rowctxmenu commitrow selectedline rowmenuid curview
5389 global nullid fakerowmenu mainhead
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005390
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005391 set rowmenuid $id
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005392 if {![info exists selectedline]
5393 || $commitrow($curview,$id) eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005394 set state disabled
5395 } else {
5396 set state normal
5397 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005398 if {$id ne $nullid} {
5399 set menu $rowctxmenu
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005400 $menu entryconfigure 7 -label "Reset $mainhead branch to here"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005401 } else {
5402 set menu $fakerowmenu
5403 }
5404 $menu entryconfigure "Diff this*" -state $state
5405 $menu entryconfigure "Diff selected*" -state $state
5406 $menu entryconfigure "Make patch" -state $state
5407 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005408}
5409
5410proc diffvssel {dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005411 global rowmenuid selectedline displayorder
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005412
5413 if {![info exists selectedline]} return
5414 if {$dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005415 set oldid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005416 set newid $rowmenuid
5417 } else {
5418 set oldid $rowmenuid
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005419 set newid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005420 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005421 addtohistory [list doseldiff $oldid $newid]
5422 doseldiff $oldid $newid
5423}
5424
5425proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005426 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005427 global commitinfo
5428
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005429 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005430 clear_ctext
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005431 init_flist "Top"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005432 $ctext insert end "From "
5433 $ctext tag conf link -foreground blue -underline 1
5434 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
5435 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
5436 $ctext tag bind link0 <1> [list selbyid $oldid]
5437 $ctext insert end $oldid [list link link0]
5438 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005439 $ctext insert end [lindex $commitinfo($oldid) 0]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005440 $ctext insert end "\n\nTo "
5441 $ctext tag bind link1 <1> [list selbyid $newid]
5442 $ctext insert end $newid [list link link1]
5443 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005444 $ctext insert end [lindex $commitinfo($newid) 0]
5445 $ctext insert end "\n"
5446 $ctext conf -state disabled
5447 $ctext tag delete Comments
5448 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11005449 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005450}
5451
Paul Mackerras74daedb2005-06-27 19:27:32 +10005452proc mkpatch {} {
5453 global rowmenuid currentid commitinfo patchtop patchnum
5454
5455 if {![info exists currentid]} return
5456 set oldid $currentid
5457 set oldhead [lindex $commitinfo($oldid) 0]
5458 set newid $rowmenuid
5459 set newhead [lindex $commitinfo($newid) 0]
5460 set top .patch
5461 set patchtop $top
5462 catch {destroy $top}
5463 toplevel $top
5464 label $top.title -text "Generate patch"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005465 grid $top.title - -pady 10
Paul Mackerras74daedb2005-06-27 19:27:32 +10005466 label $top.from -text "From:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005467 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005468 $top.fromsha1 insert 0 $oldid
5469 $top.fromsha1 conf -state readonly
5470 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005471 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005472 $top.fromhead insert 0 $oldhead
5473 $top.fromhead conf -state readonly
5474 grid x $top.fromhead -sticky w
5475 label $top.to -text "To:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005476 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005477 $top.tosha1 insert 0 $newid
5478 $top.tosha1 conf -state readonly
5479 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005480 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005481 $top.tohead insert 0 $newhead
5482 $top.tohead conf -state readonly
5483 grid x $top.tohead -sticky w
5484 button $top.rev -text "Reverse" -command mkpatchrev -padx 5
5485 grid $top.rev x -pady 10
5486 label $top.flab -text "Output file:"
5487 entry $top.fname -width 60
5488 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
5489 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005490 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10005491 frame $top.buts
5492 button $top.buts.gen -text "Generate" -command mkpatchgo
5493 button $top.buts.can -text "Cancel" -command mkpatchcan
5494 grid $top.buts.gen $top.buts.can
5495 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5496 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5497 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005498 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10005499}
5500
5501proc mkpatchrev {} {
5502 global patchtop
5503
5504 set oldid [$patchtop.fromsha1 get]
5505 set oldhead [$patchtop.fromhead get]
5506 set newid [$patchtop.tosha1 get]
5507 set newhead [$patchtop.tohead get]
5508 foreach e [list fromsha1 fromhead tosha1 tohead] \
5509 v [list $newid $newhead $oldid $oldhead] {
5510 $patchtop.$e conf -state normal
5511 $patchtop.$e delete 0 end
5512 $patchtop.$e insert 0 $v
5513 $patchtop.$e conf -state readonly
5514 }
5515}
5516
5517proc mkpatchgo {} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005518 global patchtop nullid
Paul Mackerras74daedb2005-06-27 19:27:32 +10005519
5520 set oldid [$patchtop.fromsha1 get]
5521 set newid [$patchtop.tosha1 get]
5522 set fname [$patchtop.fname get]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005523 if {$newid eq $nullid} {
5524 set cmd [list git diff-index -p $oldid]
5525 } elseif {$oldid eq $nullid} {
5526 set cmd [list git diff-index -p -R $newid]
5527 } else {
5528 set cmd [list git diff-tree -p $oldid $newid]
5529 }
5530 lappend cmd >$fname &
5531 if {[catch {eval exec $cmd} err]} {
Paul Mackerras74daedb2005-06-27 19:27:32 +10005532 error_popup "Error creating patch: $err"
5533 }
5534 catch {destroy $patchtop}
5535 unset patchtop
5536}
5537
5538proc mkpatchcan {} {
5539 global patchtop
5540
5541 catch {destroy $patchtop}
5542 unset patchtop
5543}
5544
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005545proc mktag {} {
5546 global rowmenuid mktagtop commitinfo
5547
5548 set top .maketag
5549 set mktagtop $top
5550 catch {destroy $top}
5551 toplevel $top
5552 label $top.title -text "Create tag"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005553 grid $top.title - -pady 10
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005554 label $top.id -text "ID:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005555 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005556 $top.sha1 insert 0 $rowmenuid
5557 $top.sha1 conf -state readonly
5558 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005559 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005560 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5561 $top.head conf -state readonly
5562 grid x $top.head -sticky w
5563 label $top.tlab -text "Tag name:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005564 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005565 grid $top.tlab $top.tag -sticky w
5566 frame $top.buts
5567 button $top.buts.gen -text "Create" -command mktaggo
5568 button $top.buts.can -text "Cancel" -command mktagcan
5569 grid $top.buts.gen $top.buts.can
5570 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5571 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5572 grid $top.buts - -pady 10 -sticky ew
5573 focus $top.tag
5574}
5575
5576proc domktag {} {
5577 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005578
5579 set id [$mktagtop.sha1 get]
5580 set tag [$mktagtop.tag get]
5581 if {$tag == {}} {
5582 error_popup "No tag name specified"
5583 return
5584 }
5585 if {[info exists tagids($tag)]} {
5586 error_popup "Tag \"$tag\" already exists"
5587 return
5588 }
5589 if {[catch {
Junio C Hamano73b6a6c2005-07-28 00:28:44 -07005590 set dir [gitdir]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005591 set fname [file join $dir "refs/tags" $tag]
5592 set f [open $fname w]
5593 puts $f $id
5594 close $f
5595 } err]} {
5596 error_popup "Error creating tag: $err"
5597 return
5598 }
5599
5600 set tagids($tag) $id
5601 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005602 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10005603 addedtag $id
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005604}
5605
5606proc redrawtags {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005607 global canv linehtag commitrow idpos selectedline curview
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005608 global mainfont canvxmax iddrawn
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005609
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005610 if {![info exists commitrow($curview,$id)]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005611 if {![info exists iddrawn($id)]} return
5612 drawcommits $commitrow($curview,$id)
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005613 $canv delete tag.$id
5614 set xt [eval drawtags $id $idpos($id)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005615 $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005616 set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text]
5617 set xr [expr {$xt + [font measure $mainfont $text]}]
5618 if {$xr > $canvxmax} {
5619 set canvxmax $xr
5620 setcanvscroll
5621 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005622 if {[info exists selectedline]
5623 && $selectedline == $commitrow($curview,$id)} {
Paul Mackerrasd6982062005-08-06 22:06:06 +10005624 selectline $selectedline 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005625 }
5626}
5627
5628proc mktagcan {} {
5629 global mktagtop
5630
5631 catch {destroy $mktagtop}
5632 unset mktagtop
5633}
5634
5635proc mktaggo {} {
5636 domktag
5637 mktagcan
5638}
5639
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005640proc writecommit {} {
5641 global rowmenuid wrcomtop commitinfo wrcomcmd
5642
5643 set top .writecommit
5644 set wrcomtop $top
5645 catch {destroy $top}
5646 toplevel $top
5647 label $top.title -text "Write commit to file"
5648 grid $top.title - -pady 10
5649 label $top.id -text "ID:"
5650 entry $top.sha1 -width 40 -relief flat
5651 $top.sha1 insert 0 $rowmenuid
5652 $top.sha1 conf -state readonly
5653 grid $top.id $top.sha1 -sticky w
5654 entry $top.head -width 60 -relief flat
5655 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5656 $top.head conf -state readonly
5657 grid x $top.head -sticky w
5658 label $top.clab -text "Command:"
5659 entry $top.cmd -width 60 -textvariable wrcomcmd
5660 grid $top.clab $top.cmd -sticky w -pady 10
5661 label $top.flab -text "Output file:"
5662 entry $top.fname -width 60
5663 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
5664 grid $top.flab $top.fname -sticky w
5665 frame $top.buts
5666 button $top.buts.gen -text "Write" -command wrcomgo
5667 button $top.buts.can -text "Cancel" -command wrcomcan
5668 grid $top.buts.gen $top.buts.can
5669 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5670 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5671 grid $top.buts - -pady 10 -sticky ew
5672 focus $top.fname
5673}
5674
5675proc wrcomgo {} {
5676 global wrcomtop
5677
5678 set id [$wrcomtop.sha1 get]
5679 set cmd "echo $id | [$wrcomtop.cmd get]"
5680 set fname [$wrcomtop.fname get]
5681 if {[catch {exec sh -c $cmd >$fname &} err]} {
5682 error_popup "Error writing commit: $err"
5683 }
5684 catch {destroy $wrcomtop}
5685 unset wrcomtop
5686}
5687
5688proc wrcomcan {} {
5689 global wrcomtop
5690
5691 catch {destroy $wrcomtop}
5692 unset wrcomtop
5693}
5694
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005695proc mkbranch {} {
5696 global rowmenuid mkbrtop
5697
5698 set top .makebranch
5699 catch {destroy $top}
5700 toplevel $top
5701 label $top.title -text "Create new branch"
5702 grid $top.title - -pady 10
5703 label $top.id -text "ID:"
5704 entry $top.sha1 -width 40 -relief flat
5705 $top.sha1 insert 0 $rowmenuid
5706 $top.sha1 conf -state readonly
5707 grid $top.id $top.sha1 -sticky w
5708 label $top.nlab -text "Name:"
5709 entry $top.name -width 40
5710 grid $top.nlab $top.name -sticky w
5711 frame $top.buts
5712 button $top.buts.go -text "Create" -command [list mkbrgo $top]
5713 button $top.buts.can -text "Cancel" -command "catch {destroy $top}"
5714 grid $top.buts.go $top.buts.can
5715 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5716 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5717 grid $top.buts - -pady 10 -sticky ew
5718 focus $top.name
5719}
5720
5721proc mkbrgo {top} {
5722 global headids idheads
5723
5724 set name [$top.name get]
5725 set id [$top.sha1 get]
5726 if {$name eq {}} {
5727 error_popup "Please specify a name for the new branch"
5728 return
5729 }
5730 catch {destroy $top}
5731 nowbusy newbranch
5732 update
5733 if {[catch {
5734 exec git branch $name $id
5735 } err]} {
5736 notbusy newbranch
5737 error_popup $err
5738 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005739 set headids($name) $id
5740 lappend idheads($id) $name
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005741 addedhead $id $name
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005742 notbusy newbranch
5743 redrawtags $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10005744 dispneartags 0
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005745 }
5746}
5747
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005748proc cherrypick {} {
5749 global rowmenuid curview commitrow
Paul Mackerrase11f1232007-06-16 20:29:25 +10005750 global mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005751
Paul Mackerrase11f1232007-06-16 20:29:25 +10005752 set oldhead [exec git rev-parse HEAD]
5753 set dheads [descheads $rowmenuid]
5754 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005755 set ok [confirm_popup "Commit [string range $rowmenuid 0 7] is already\
5756 included in branch $mainhead -- really re-apply it?"]
5757 if {!$ok} return
5758 }
5759 nowbusy cherrypick
5760 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005761 # Unfortunately git-cherry-pick writes stuff to stderr even when
5762 # no error occurs, and exec takes that as an indication of error...
5763 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
5764 notbusy cherrypick
5765 error_popup $err
5766 return
5767 }
5768 set newhead [exec git rev-parse HEAD]
5769 if {$newhead eq $oldhead} {
5770 notbusy cherrypick
5771 error_popup "No changes committed"
5772 return
5773 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005774 addnewchild $newhead $oldhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005775 if {[info exists commitrow($curview,$oldhead)]} {
5776 insertrow $commitrow($curview,$oldhead) $newhead
5777 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005778 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005779 movedhead $newhead $mainhead
5780 }
5781 redrawtags $oldhead
5782 redrawtags $newhead
5783 }
5784 notbusy cherrypick
5785}
5786
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005787proc resethead {} {
5788 global mainheadid mainhead rowmenuid confirm_ok resettype
5789 global showlocalchanges
5790
5791 set confirm_ok 0
5792 set w ".confirmreset"
5793 toplevel $w
5794 wm transient $w .
5795 wm title $w "Confirm reset"
5796 message $w.m -text \
5797 "Reset branch $mainhead to [string range $rowmenuid 0 7]?" \
5798 -justify center -aspect 1000
5799 pack $w.m -side top -fill x -padx 20 -pady 20
5800 frame $w.f -relief sunken -border 2
5801 message $w.f.rt -text "Reset type:" -aspect 1000
5802 grid $w.f.rt -sticky w
5803 set resettype mixed
5804 radiobutton $w.f.soft -value soft -variable resettype -justify left \
5805 -text "Soft: Leave working tree and index untouched"
5806 grid $w.f.soft -sticky w
5807 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
5808 -text "Mixed: Leave working tree untouched, reset index"
5809 grid $w.f.mixed -sticky w
5810 radiobutton $w.f.hard -value hard -variable resettype -justify left \
5811 -text "Hard: Reset working tree and index\n(discard ALL local changes)"
5812 grid $w.f.hard -sticky w
5813 pack $w.f -side top -fill x
5814 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
5815 pack $w.ok -side left -fill x -padx 20 -pady 20
5816 button $w.cancel -text Cancel -command "destroy $w"
5817 pack $w.cancel -side right -fill x -padx 20 -pady 20
5818 bind $w <Visibility> "grab $w; focus $w"
5819 tkwait window $w
5820 if {!$confirm_ok} return
5821 dohidelocalchanges
5822 if {[catch {exec git reset --$resettype $rowmenuid} err]} {
5823 error_popup $err
5824 } else {
5825 set oldhead $mainheadid
5826 movedhead $rowmenuid $mainhead
5827 set mainheadid $rowmenuid
5828 redrawtags $oldhead
5829 redrawtags $rowmenuid
5830 }
5831 if {$showlocalchanges} {
5832 doshowlocalchanges
5833 }
5834}
5835
Paul Mackerras10299152006-08-02 09:52:01 +10005836# context menu for a head
5837proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10005838 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10005839
5840 set headmenuid $id
5841 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10005842 set state normal
5843 if {$head eq $mainhead} {
5844 set state disabled
5845 }
5846 $headctxmenu entryconfigure 0 -state $state
5847 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10005848 tk_popup $headctxmenu $x $y
5849}
5850
5851proc cobranch {} {
5852 global headmenuid headmenuhead mainhead headids
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005853 global showlocalchanges mainheadid
Paul Mackerras10299152006-08-02 09:52:01 +10005854
5855 # check the tree is clean first??
5856 set oldmainhead $mainhead
5857 nowbusy checkout
5858 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005859 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10005860 if {[catch {
Paul Mackerras696cf492007-05-22 09:52:00 +10005861 exec git checkout -q $headmenuhead
Paul Mackerras10299152006-08-02 09:52:01 +10005862 } err]} {
5863 notbusy checkout
5864 error_popup $err
5865 } else {
5866 notbusy checkout
Paul Mackerras53cda8d2006-08-02 19:43:34 +10005867 set mainhead $headmenuhead
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005868 set mainheadid $headmenuid
Paul Mackerras10299152006-08-02 09:52:01 +10005869 if {[info exists headids($oldmainhead)]} {
5870 redrawtags $headids($oldmainhead)
5871 }
5872 redrawtags $headmenuid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005873 }
5874 if {$showlocalchanges} {
5875 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10005876 }
5877}
5878
5879proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005880 global headmenuid headmenuhead mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10005881 global headids idheads
5882
5883 set head $headmenuhead
5884 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10005885 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10005886 if {$head eq $mainhead} {
5887 error_popup "Cannot delete the currently checked-out branch"
5888 return
5889 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005890 set dheads [descheads $id]
5891 if {$dheads eq $headids($head)} {
Paul Mackerras10299152006-08-02 09:52:01 +10005892 # the stuff on this branch isn't on any other branch
5893 if {![confirm_popup "The commits on branch $head aren't on any other\
5894 branch.\nReally delete branch $head?"]} return
5895 }
5896 nowbusy rmbranch
5897 update
5898 if {[catch {exec git branch -D $head} err]} {
5899 notbusy rmbranch
5900 error_popup $err
5901 return
5902 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005903 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005904 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10005905 redrawtags $id
5906 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10005907 dispneartags 0
Paul Mackerras10299152006-08-02 09:52:01 +10005908}
5909
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005910# Stuff for finding nearby tags
5911proc getallcommits {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005912 global allcommits allids nbmp nextarc seeds
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005913
Paul Mackerrascec7bec2006-08-02 09:38:10 +10005914 set allids {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10005915 set nbmp 0
5916 set nextarc 0
5917 set allcommits 0
5918 set seeds {}
5919 regetallcommits
5920}
5921
5922# Called when the graph might have changed
5923proc regetallcommits {} {
5924 global allcommits seeds
5925
5926 set cmd [concat | git rev-list --all --parents]
5927 foreach id $seeds {
5928 lappend cmd "^$id"
5929 }
5930 set fd [open $cmd r]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005931 fconfigure $fd -blocking 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10005932 incr allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005933 nowbusy allcommits
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005934 filerun $fd [list getallclines $fd]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005935}
5936
Paul Mackerrase11f1232007-06-16 20:29:25 +10005937# Since most commits have 1 parent and 1 child, we group strings of
5938# such commits into "arcs" joining branch/merge points (BMPs), which
5939# are commits that either don't have 1 parent or don't have 1 child.
5940#
5941# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
5942# arcout(id) - outgoing arcs for BMP
5943# arcids(a) - list of IDs on arc including end but not start
5944# arcstart(a) - BMP ID at start of arc
5945# arcend(a) - BMP ID at end of arc
5946# growing(a) - arc a is still growing
5947# arctags(a) - IDs out of arcids (excluding end) that have tags
5948# archeads(a) - IDs out of arcids (excluding end) that have heads
5949# The start of an arc is at the descendent end, so "incoming" means
5950# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10005951
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005952proc getallclines {fd} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005953 global allids allparents allchildren idtags nextarc nbmp
5954 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005955 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005956
Paul Mackerrase11f1232007-06-16 20:29:25 +10005957 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005958 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005959 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10005960 if {[info exists allparents($id)]} {
5961 # seen it already
5962 continue
5963 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005964 lappend allids $id
5965 set olds [lrange $line 1 end]
5966 set allparents($id) $olds
5967 if {![info exists allchildren($id)]} {
5968 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10005969 set arcnos($id) {}
5970 lappend seeds $id
5971 } else {
5972 set a $arcnos($id)
5973 if {[llength $olds] == 1 && [llength $a] == 1} {
5974 lappend arcids($a) $id
5975 if {[info exists idtags($id)]} {
5976 lappend arctags($a) $id
5977 }
5978 if {[info exists idheads($id)]} {
5979 lappend archeads($a) $id
5980 }
5981 if {[info exists allparents($olds)]} {
5982 # seen parent already
5983 if {![info exists arcout($olds)]} {
5984 splitarc $olds
5985 }
5986 lappend arcids($a) $olds
5987 set arcend($a) $olds
5988 unset growing($a)
5989 }
5990 lappend allchildren($olds) $id
5991 lappend arcnos($olds) $a
5992 continue
5993 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005994 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005995 incr nbmp
5996 foreach a $arcnos($id) {
5997 lappend arcids($a) $id
5998 set arcend($a) $id
5999 unset growing($a)
6000 }
6001
6002 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006003 foreach p $olds {
6004 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10006005 set a [incr nextarc]
6006 set arcstart($a) $id
6007 set archeads($a) {}
6008 set arctags($a) {}
6009 set archeads($a) {}
6010 set arcids($a) {}
6011 lappend ao $a
6012 set growing($a) 1
6013 if {[info exists allparents($p)]} {
6014 # seen it already, may need to make a new branch
6015 if {![info exists arcout($p)]} {
6016 splitarc $p
6017 }
6018 lappend arcids($a) $p
6019 set arcend($a) $p
6020 unset growing($a)
6021 }
6022 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006023 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006024 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006025 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006026 if {![eof $fd]} {
6027 return [expr {$nid >= 1000? 2: 1}]
6028 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006029 close $fd
6030 if {[incr allcommits -1] == 0} {
6031 notbusy allcommits
6032 }
6033 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006034 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006035}
6036
6037proc recalcarc {a} {
6038 global arctags archeads arcids idtags idheads
6039
6040 set at {}
6041 set ah {}
6042 foreach id [lrange $arcids($a) 0 end-1] {
6043 if {[info exists idtags($id)]} {
6044 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006045 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006046 if {[info exists idheads($id)]} {
6047 lappend ah $id
6048 }
6049 }
6050 set arctags($a) $at
6051 set archeads($a) $ah
6052}
6053
6054proc splitarc {p} {
6055 global arcnos arcids nextarc nbmp arctags archeads idtags idheads
6056 global arcstart arcend arcout allparents growing
6057
6058 set a $arcnos($p)
6059 if {[llength $a] != 1} {
6060 puts "oops splitarc called but [llength $a] arcs already"
6061 return
6062 }
6063 set a [lindex $a 0]
6064 set i [lsearch -exact $arcids($a) $p]
6065 if {$i < 0} {
6066 puts "oops splitarc $p not in arc $a"
6067 return
6068 }
6069 set na [incr nextarc]
6070 if {[info exists arcend($a)]} {
6071 set arcend($na) $arcend($a)
6072 } else {
6073 set l [lindex $allparents([lindex $arcids($a) end]) 0]
6074 set j [lsearch -exact $arcnos($l) $a]
6075 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
6076 }
6077 set tail [lrange $arcids($a) [expr {$i+1}] end]
6078 set arcids($a) [lrange $arcids($a) 0 $i]
6079 set arcend($a) $p
6080 set arcstart($na) $p
6081 set arcout($p) $na
6082 set arcids($na) $tail
6083 if {[info exists growing($a)]} {
6084 set growing($na) 1
6085 unset growing($a)
6086 }
6087 incr nbmp
6088
6089 foreach id $tail {
6090 if {[llength $arcnos($id)] == 1} {
6091 set arcnos($id) $na
6092 } else {
6093 set j [lsearch -exact $arcnos($id) $a]
6094 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
6095 }
6096 }
6097
6098 # reconstruct tags and heads lists
6099 if {$arctags($a) ne {} || $archeads($a) ne {}} {
6100 recalcarc $a
6101 recalcarc $na
6102 } else {
6103 set arctags($na) {}
6104 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006105 }
6106}
6107
Paul Mackerrase11f1232007-06-16 20:29:25 +10006108# Update things for a new commit added that is a child of one
6109# existing commit. Used when cherry-picking.
6110proc addnewchild {id p} {
6111 global allids allparents allchildren idtags nextarc nbmp
6112 global arcnos arcids arctags arcout arcend arcstart archeads growing
6113 global seeds
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006114
Paul Mackerrase11f1232007-06-16 20:29:25 +10006115 lappend allids $id
6116 set allparents($id) [list $p]
6117 set allchildren($id) {}
6118 set arcnos($id) {}
6119 lappend seeds $id
6120 incr nbmp
6121 lappend allchildren($p) $id
6122 set a [incr nextarc]
6123 set arcstart($a) $id
6124 set archeads($a) {}
6125 set arctags($a) {}
6126 set arcids($a) [list $p]
6127 set arcend($a) $p
6128 if {![info exists arcout($p)]} {
6129 splitarc $p
6130 }
6131 lappend arcnos($p) $a
6132 set arcout($id) [list $a]
6133}
6134
6135# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
6136# or 0 if neither is true.
6137proc anc_or_desc {a b} {
6138 global arcout arcstart arcend arcnos cached_isanc
6139
6140 if {$arcnos($a) eq $arcnos($b)} {
6141 # Both are on the same arc(s); either both are the same BMP,
6142 # or if one is not a BMP, the other is also not a BMP or is
6143 # the BMP at end of the arc (and it only has 1 incoming arc).
6144 if {$a eq $b} {
6145 return 0
6146 }
6147 # assert {[llength $arcnos($a)] == 1}
6148 set arc [lindex $arcnos($a) 0]
6149 set i [lsearch -exact $arcids($arc) $a]
6150 set j [lsearch -exact $arcids($arc) $b]
6151 if {$i < 0 || $i > $j} {
6152 return 1
6153 } else {
6154 return -1
6155 }
6156 }
6157
6158 if {![info exists arcout($a)]} {
6159 set arc [lindex $arcnos($a) 0]
6160 if {[info exists arcend($arc)]} {
6161 set aend $arcend($arc)
6162 } else {
6163 set aend {}
6164 }
6165 set a $arcstart($arc)
6166 } else {
6167 set aend $a
6168 }
6169 if {![info exists arcout($b)]} {
6170 set arc [lindex $arcnos($b) 0]
6171 if {[info exists arcend($arc)]} {
6172 set bend $arcend($arc)
6173 } else {
6174 set bend {}
6175 }
6176 set b $arcstart($arc)
6177 } else {
6178 set bend $b
6179 }
6180 if {$a eq $bend} {
6181 return 1
6182 }
6183 if {$b eq $aend} {
6184 return -1
6185 }
6186 if {[info exists cached_isanc($a,$bend)]} {
6187 if {$cached_isanc($a,$bend)} {
6188 return 1
6189 }
6190 }
6191 if {[info exists cached_isanc($b,$aend)]} {
6192 if {$cached_isanc($b,$aend)} {
6193 return -1
6194 }
6195 if {[info exists cached_isanc($a,$bend)]} {
6196 return 0
6197 }
6198 }
6199
6200 set todo [list $a $b]
6201 set anc($a) a
6202 set anc($b) b
6203 for {set i 0} {$i < [llength $todo]} {incr i} {
6204 set x [lindex $todo $i]
6205 if {$anc($x) eq {}} {
6206 continue
6207 }
6208 foreach arc $arcnos($x) {
6209 set xd $arcstart($arc)
6210 if {$xd eq $bend} {
6211 set cached_isanc($a,$bend) 1
6212 set cached_isanc($b,$aend) 0
6213 return 1
6214 } elseif {$xd eq $aend} {
6215 set cached_isanc($b,$aend) 1
6216 set cached_isanc($a,$bend) 0
6217 return -1
6218 }
6219 if {![info exists anc($xd)]} {
6220 set anc($xd) $anc($x)
6221 lappend todo $xd
6222 } elseif {$anc($xd) ne $anc($x)} {
6223 set anc($xd) {}
6224 }
6225 }
6226 }
6227 set cached_isanc($a,$bend) 0
6228 set cached_isanc($b,$aend) 0
6229 return 0
6230}
6231
6232# This identifies whether $desc has an ancestor that is
6233# a growing tip of the graph and which is not an ancestor of $anc
6234# and returns 0 if so and 1 if not.
6235# If we subsequently discover a tag on such a growing tip, and that
6236# turns out to be a descendent of $anc (which it could, since we
6237# don't necessarily see children before parents), then $desc
6238# isn't a good choice to display as a descendent tag of
6239# $anc (since it is the descendent of another tag which is
6240# a descendent of $anc). Similarly, $anc isn't a good choice to
6241# display as a ancestor tag of $desc.
6242#
6243proc is_certain {desc anc} {
6244 global arcnos arcout arcstart arcend growing problems
6245
6246 set certain {}
6247 if {[llength $arcnos($anc)] == 1} {
6248 # tags on the same arc are certain
6249 if {$arcnos($desc) eq $arcnos($anc)} {
6250 return 1
6251 }
6252 if {![info exists arcout($anc)]} {
6253 # if $anc is partway along an arc, use the start of the arc instead
6254 set a [lindex $arcnos($anc) 0]
6255 set anc $arcstart($a)
6256 }
6257 }
6258 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
6259 set x $desc
6260 } else {
6261 set a [lindex $arcnos($desc) 0]
6262 set x $arcend($a)
6263 }
6264 if {$x == $anc} {
6265 return 1
6266 }
6267 set anclist [list $x]
6268 set dl($x) 1
6269 set nnh 1
6270 set ngrowanc 0
6271 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
6272 set x [lindex $anclist $i]
6273 if {$dl($x)} {
6274 incr nnh -1
6275 }
6276 set done($x) 1
6277 foreach a $arcout($x) {
6278 if {[info exists growing($a)]} {
6279 if {![info exists growanc($x)] && $dl($x)} {
6280 set growanc($x) 1
6281 incr ngrowanc
6282 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006283 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006284 set y $arcend($a)
6285 if {[info exists dl($y)]} {
6286 if {$dl($y)} {
6287 if {!$dl($x)} {
6288 set dl($y) 0
6289 if {![info exists done($y)]} {
6290 incr nnh -1
6291 }
6292 if {[info exists growanc($x)]} {
6293 incr ngrowanc -1
6294 }
6295 set xl [list $y]
6296 for {set k 0} {$k < [llength $xl]} {incr k} {
6297 set z [lindex $xl $k]
6298 foreach c $arcout($z) {
6299 if {[info exists arcend($c)]} {
6300 set v $arcend($c)
6301 if {[info exists dl($v)] && $dl($v)} {
6302 set dl($v) 0
6303 if {![info exists done($v)]} {
6304 incr nnh -1
6305 }
6306 if {[info exists growanc($v)]} {
6307 incr ngrowanc -1
6308 }
6309 lappend xl $v
6310 }
6311 }
6312 }
6313 }
6314 }
6315 }
6316 } elseif {$y eq $anc || !$dl($x)} {
6317 set dl($y) 0
6318 lappend anclist $y
6319 } else {
6320 set dl($y) 1
6321 lappend anclist $y
6322 incr nnh
6323 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006324 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006325 }
6326 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006327 foreach x [array names growanc] {
6328 if {$dl($x)} {
6329 return 0
6330 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006331 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006332 }
6333 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006334}
6335
Paul Mackerrase11f1232007-06-16 20:29:25 +10006336proc validate_arctags {a} {
6337 global arctags idtags
6338
6339 set i -1
6340 set na $arctags($a)
6341 foreach id $arctags($a) {
6342 incr i
6343 if {![info exists idtags($id)]} {
6344 set na [lreplace $na $i $i]
6345 incr i -1
6346 }
6347 }
6348 set arctags($a) $na
6349}
6350
6351proc validate_archeads {a} {
6352 global archeads idheads
6353
6354 set i -1
6355 set na $archeads($a)
6356 foreach id $archeads($a) {
6357 incr i
6358 if {![info exists idheads($id)]} {
6359 set na [lreplace $na $i $i]
6360 incr i -1
6361 }
6362 }
6363 set archeads($a) $na
6364}
6365
6366# Return the list of IDs that have tags that are descendents of id,
6367# ignoring IDs that are descendents of IDs already reported.
6368proc desctags {id} {
6369 global arcnos arcstart arcids arctags idtags allparents
6370 global growing cached_dtags
6371
6372 if {![info exists allparents($id)]} {
6373 return {}
6374 }
6375 set t1 [clock clicks -milliseconds]
6376 set argid $id
6377 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6378 # part-way along an arc; check that arc first
6379 set a [lindex $arcnos($id) 0]
6380 if {$arctags($a) ne {}} {
6381 validate_arctags $a
6382 set i [lsearch -exact $arcids($a) $id]
6383 set tid {}
6384 foreach t $arctags($a) {
6385 set j [lsearch -exact $arcids($a) $t]
6386 if {$j >= $i} break
6387 set tid $t
6388 }
6389 if {$tid ne {}} {
6390 return $tid
6391 }
6392 }
6393 set id $arcstart($a)
6394 if {[info exists idtags($id)]} {
6395 return $id
6396 }
6397 }
6398 if {[info exists cached_dtags($id)]} {
6399 return $cached_dtags($id)
6400 }
6401
6402 set origid $id
6403 set todo [list $id]
6404 set queued($id) 1
6405 set nc 1
6406 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
6407 set id [lindex $todo $i]
6408 set done($id) 1
6409 set ta [info exists hastaggedancestor($id)]
6410 if {!$ta} {
6411 incr nc -1
6412 }
6413 # ignore tags on starting node
6414 if {!$ta && $i > 0} {
6415 if {[info exists idtags($id)]} {
6416 set tagloc($id) $id
6417 set ta 1
6418 } elseif {[info exists cached_dtags($id)]} {
6419 set tagloc($id) $cached_dtags($id)
6420 set ta 1
6421 }
6422 }
6423 foreach a $arcnos($id) {
6424 set d $arcstart($a)
6425 if {!$ta && $arctags($a) ne {}} {
6426 validate_arctags $a
6427 if {$arctags($a) ne {}} {
6428 lappend tagloc($id) [lindex $arctags($a) end]
6429 }
6430 }
6431 if {$ta || $arctags($a) ne {}} {
6432 set tomark [list $d]
6433 for {set j 0} {$j < [llength $tomark]} {incr j} {
6434 set dd [lindex $tomark $j]
6435 if {![info exists hastaggedancestor($dd)]} {
6436 if {[info exists done($dd)]} {
6437 foreach b $arcnos($dd) {
6438 lappend tomark $arcstart($b)
6439 }
6440 if {[info exists tagloc($dd)]} {
6441 unset tagloc($dd)
6442 }
6443 } elseif {[info exists queued($dd)]} {
6444 incr nc -1
6445 }
6446 set hastaggedancestor($dd) 1
6447 }
6448 }
6449 }
6450 if {![info exists queued($d)]} {
6451 lappend todo $d
6452 set queued($d) 1
6453 if {![info exists hastaggedancestor($d)]} {
6454 incr nc
6455 }
6456 }
6457 }
6458 }
6459 set tags {}
6460 foreach id [array names tagloc] {
6461 if {![info exists hastaggedancestor($id)]} {
6462 foreach t $tagloc($id) {
6463 if {[lsearch -exact $tags $t] < 0} {
6464 lappend tags $t
6465 }
6466 }
6467 }
6468 }
6469 set t2 [clock clicks -milliseconds]
6470 set loopix $i
6471
6472 # remove tags that are descendents of other tags
6473 for {set i 0} {$i < [llength $tags]} {incr i} {
6474 set a [lindex $tags $i]
6475 for {set j 0} {$j < $i} {incr j} {
6476 set b [lindex $tags $j]
6477 set r [anc_or_desc $a $b]
6478 if {$r == 1} {
6479 set tags [lreplace $tags $j $j]
6480 incr j -1
6481 incr i -1
6482 } elseif {$r == -1} {
6483 set tags [lreplace $tags $i $i]
6484 incr i -1
6485 break
6486 }
6487 }
6488 }
6489
6490 if {[array names growing] ne {}} {
6491 # graph isn't finished, need to check if any tag could get
6492 # eclipsed by another tag coming later. Simply ignore any
6493 # tags that could later get eclipsed.
6494 set ctags {}
6495 foreach t $tags {
6496 if {[is_certain $t $origid]} {
6497 lappend ctags $t
6498 }
6499 }
6500 if {$tags eq $ctags} {
6501 set cached_dtags($origid) $tags
6502 } else {
6503 set tags $ctags
6504 }
6505 } else {
6506 set cached_dtags($origid) $tags
6507 }
6508 set t3 [clock clicks -milliseconds]
6509 if {0 && $t3 - $t1 >= 100} {
6510 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
6511 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
6512 }
6513 return $tags
6514}
6515
6516proc anctags {id} {
6517 global arcnos arcids arcout arcend arctags idtags allparents
6518 global growing cached_atags
6519
6520 if {![info exists allparents($id)]} {
6521 return {}
6522 }
6523 set t1 [clock clicks -milliseconds]
6524 set argid $id
6525 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6526 # part-way along an arc; check that arc first
6527 set a [lindex $arcnos($id) 0]
6528 if {$arctags($a) ne {}} {
6529 validate_arctags $a
6530 set i [lsearch -exact $arcids($a) $id]
6531 foreach t $arctags($a) {
6532 set j [lsearch -exact $arcids($a) $t]
6533 if {$j > $i} {
6534 return $t
6535 }
6536 }
6537 }
6538 if {![info exists arcend($a)]} {
6539 return {}
6540 }
6541 set id $arcend($a)
6542 if {[info exists idtags($id)]} {
6543 return $id
6544 }
6545 }
6546 if {[info exists cached_atags($id)]} {
6547 return $cached_atags($id)
6548 }
6549
6550 set origid $id
6551 set todo [list $id]
6552 set queued($id) 1
6553 set taglist {}
6554 set nc 1
6555 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
6556 set id [lindex $todo $i]
6557 set done($id) 1
6558 set td [info exists hastaggeddescendent($id)]
6559 if {!$td} {
6560 incr nc -1
6561 }
6562 # ignore tags on starting node
6563 if {!$td && $i > 0} {
6564 if {[info exists idtags($id)]} {
6565 set tagloc($id) $id
6566 set td 1
6567 } elseif {[info exists cached_atags($id)]} {
6568 set tagloc($id) $cached_atags($id)
6569 set td 1
6570 }
6571 }
6572 foreach a $arcout($id) {
6573 if {!$td && $arctags($a) ne {}} {
6574 validate_arctags $a
6575 if {$arctags($a) ne {}} {
6576 lappend tagloc($id) [lindex $arctags($a) 0]
6577 }
6578 }
6579 if {![info exists arcend($a)]} continue
6580 set d $arcend($a)
6581 if {$td || $arctags($a) ne {}} {
6582 set tomark [list $d]
6583 for {set j 0} {$j < [llength $tomark]} {incr j} {
6584 set dd [lindex $tomark $j]
6585 if {![info exists hastaggeddescendent($dd)]} {
6586 if {[info exists done($dd)]} {
6587 foreach b $arcout($dd) {
6588 if {[info exists arcend($b)]} {
6589 lappend tomark $arcend($b)
6590 }
6591 }
6592 if {[info exists tagloc($dd)]} {
6593 unset tagloc($dd)
6594 }
6595 } elseif {[info exists queued($dd)]} {
6596 incr nc -1
6597 }
6598 set hastaggeddescendent($dd) 1
6599 }
6600 }
6601 }
6602 if {![info exists queued($d)]} {
6603 lappend todo $d
6604 set queued($d) 1
6605 if {![info exists hastaggeddescendent($d)]} {
6606 incr nc
6607 }
6608 }
6609 }
6610 }
6611 set t2 [clock clicks -milliseconds]
6612 set loopix $i
6613 set tags {}
6614 foreach id [array names tagloc] {
6615 if {![info exists hastaggeddescendent($id)]} {
6616 foreach t $tagloc($id) {
6617 if {[lsearch -exact $tags $t] < 0} {
6618 lappend tags $t
6619 }
6620 }
6621 }
6622 }
6623
6624 # remove tags that are ancestors of other tags
6625 for {set i 0} {$i < [llength $tags]} {incr i} {
6626 set a [lindex $tags $i]
6627 for {set j 0} {$j < $i} {incr j} {
6628 set b [lindex $tags $j]
6629 set r [anc_or_desc $a $b]
6630 if {$r == -1} {
6631 set tags [lreplace $tags $j $j]
6632 incr j -1
6633 incr i -1
6634 } elseif {$r == 1} {
6635 set tags [lreplace $tags $i $i]
6636 incr i -1
6637 break
6638 }
6639 }
6640 }
6641
6642 if {[array names growing] ne {}} {
6643 # graph isn't finished, need to check if any tag could get
6644 # eclipsed by another tag coming later. Simply ignore any
6645 # tags that could later get eclipsed.
6646 set ctags {}
6647 foreach t $tags {
6648 if {[is_certain $origid $t]} {
6649 lappend ctags $t
6650 }
6651 }
6652 if {$tags eq $ctags} {
6653 set cached_atags($origid) $tags
6654 } else {
6655 set tags $ctags
6656 }
6657 } else {
6658 set cached_atags($origid) $tags
6659 }
6660 set t3 [clock clicks -milliseconds]
6661 if {0 && $t3 - $t1 >= 100} {
6662 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
6663 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
6664 }
6665 return $tags
6666}
6667
6668# Return the list of IDs that have heads that are descendents of id,
6669# including id itself if it has a head.
6670proc descheads {id} {
6671 global arcnos arcstart arcids archeads idheads cached_dheads
6672 global allparents
6673
6674 if {![info exists allparents($id)]} {
6675 return {}
6676 }
6677 set ret {}
6678 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6679 # part-way along an arc; check it first
6680 set a [lindex $arcnos($id) 0]
6681 if {$archeads($a) ne {}} {
6682 validate_archeads $a
6683 set i [lsearch -exact $arcids($a) $id]
6684 foreach t $archeads($a) {
6685 set j [lsearch -exact $arcids($a) $t]
6686 if {$j > $i} break
6687 lappend $ret $t
6688 }
6689 }
6690 set id $arcstart($a)
6691 }
6692 set origid $id
6693 set todo [list $id]
6694 set seen($id) 1
6695 for {set i 0} {$i < [llength $todo]} {incr i} {
6696 set id [lindex $todo $i]
6697 if {[info exists cached_dheads($id)]} {
6698 set ret [concat $ret $cached_dheads($id)]
6699 } else {
6700 if {[info exists idheads($id)]} {
6701 lappend ret $id
6702 }
6703 foreach a $arcnos($id) {
6704 if {$archeads($a) ne {}} {
6705 set ret [concat $ret $archeads($a)]
6706 }
6707 set d $arcstart($a)
6708 if {![info exists seen($d)]} {
6709 lappend todo $d
6710 set seen($d) 1
6711 }
6712 }
6713 }
6714 }
6715 set ret [lsort -unique $ret]
6716 set cached_dheads($origid) $ret
6717}
6718
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006719proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006720 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006721
Paul Mackerrase11f1232007-06-16 20:29:25 +10006722 if {![info exists arcnos($id)]} return
6723 if {![info exists arcout($id)]} {
6724 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006725 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006726 catch {unset cached_dtags}
6727 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006728}
6729
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006730proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006731 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006732
Paul Mackerrase11f1232007-06-16 20:29:25 +10006733 if {![info exists arcnos($hid)]} return
6734 if {![info exists arcout($hid)]} {
6735 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006736 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006737 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006738}
6739
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006740proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006741 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006742
Paul Mackerrase11f1232007-06-16 20:29:25 +10006743 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +10006744}
6745
Paul Mackerrase11f1232007-06-16 20:29:25 +10006746proc movedhead {hid head} {
6747 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006748
Paul Mackerrase11f1232007-06-16 20:29:25 +10006749 if {![info exists arcnos($hid)]} return
6750 if {![info exists arcout($hid)]} {
6751 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006752 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006753 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006754}
6755
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006756proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006757 global cached_dheads cached_dtags cached_atags
6758 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006759
Paul Mackerrase11f1232007-06-16 20:29:25 +10006760 foreach id [concat [array names idheads] [array names idtags]] {
6761 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
6762 set a [lindex $arcnos($id) 0]
6763 if {![info exists donearc($a)]} {
6764 recalcarc $a
6765 set donearc($a) 1
6766 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006767 }
6768 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006769 catch {unset cached_dtags}
6770 catch {unset cached_atags}
6771 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006772}
6773
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006774proc rereadrefs {} {
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006775 global idtags idheads idotherrefs mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006776
6777 set refids [concat [array names idtags] \
6778 [array names idheads] [array names idotherrefs]]
6779 foreach id $refids {
6780 if {![info exists ref($id)]} {
6781 set ref($id) [listrefs $id]
6782 }
6783 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006784 set oldmainhead $mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006785 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006786 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006787 set refids [lsort -unique [concat $refids [array names idtags] \
6788 [array names idheads] [array names idotherrefs]]]
6789 foreach id $refids {
6790 set v [listrefs $id]
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006791 if {![info exists ref($id)] || $ref($id) != $v ||
6792 ($id eq $oldmainhead && $id ne $mainhead) ||
6793 ($id eq $mainhead && $id ne $oldmainhead)} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006794 redrawtags $id
6795 }
6796 }
6797}
6798
Junio C Hamano2e1ded42006-06-11 09:50:47 -07006799proc listrefs {id} {
6800 global idtags idheads idotherrefs
6801
6802 set x {}
6803 if {[info exists idtags($id)]} {
6804 set x $idtags($id)
6805 }
6806 set y {}
6807 if {[info exists idheads($id)]} {
6808 set y $idheads($id)
6809 }
6810 set z {}
6811 if {[info exists idotherrefs($id)]} {
6812 set z $idotherrefs($id)
6813 }
6814 return [list $x $y $z]
6815}
6816
Paul Mackerras106288c2005-08-19 23:11:39 +10006817proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10006818 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +10006819
6820 if {$isnew} {
6821 addtohistory [list showtag $tag 0]
6822 }
6823 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006824 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10006825 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +10006826 if {![info exists tagcontents($tag)]} {
6827 catch {
6828 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
6829 }
6830 }
Paul Mackerras106288c2005-08-19 23:11:39 +10006831 if {[info exists tagcontents($tag)]} {
6832 set text $tagcontents($tag)
6833 } else {
6834 set text "Tag: $tag\nId: $tagids($tag)"
6835 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006836 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +10006837 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006838 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +10006839}
6840
Paul Mackerras1d10f362005-05-15 12:55:47 +00006841proc doquit {} {
6842 global stopped
6843 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -05006844 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +00006845 destroy .
6846}
6847
Paul Mackerras712fcc02005-11-30 09:28:16 +11006848proc doprefs {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006849 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006850 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl60378c02007-05-20 12:12:48 -04006851 global bgcolor fgcolor ctext diffcolors selectbgcolor
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006852 global uifont tabstop
Paul Mackerras232475d2005-11-15 10:34:03 +11006853
Paul Mackerras712fcc02005-11-30 09:28:16 +11006854 set top .gitkprefs
6855 set prefstop $top
6856 if {[winfo exists $top]} {
6857 raise $top
6858 return
Paul Mackerras757f17b2005-11-21 09:56:07 +11006859 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006860 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11006861 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +11006862 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11006863 toplevel $top
6864 wm title $top "Gitk preferences"
6865 label $top.ldisp -text "Commit list display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006866 $top.ldisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11006867 grid $top.ldisp - -sticky w -pady 10
6868 label $top.spacer -text " "
6869 label $top.maxwidthl -text "Maximum graph width (lines)" \
6870 -font optionfont
6871 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
6872 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
6873 label $top.maxpctl -text "Maximum graph width (% of pane)" \
6874 -font optionfont
6875 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
6876 grid x $top.maxpctl $top.maxpct -sticky w
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006877 frame $top.showlocal
6878 label $top.showlocal.l -text "Show local changes" -font optionfont
6879 checkbutton $top.showlocal.b -variable showlocalchanges
6880 pack $top.showlocal.b $top.showlocal.l -side left
6881 grid x $top.showlocal -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006882
Paul Mackerras712fcc02005-11-30 09:28:16 +11006883 label $top.ddisp -text "Diff display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006884 $top.ddisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11006885 grid $top.ddisp - -sticky w -pady 10
6886 label $top.diffoptl -text "Options for diff program" \
6887 -font optionfont
6888 entry $top.diffopt -width 20 -textvariable diffopts
6889 grid x $top.diffoptl $top.diffopt -sticky w
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006890 frame $top.ntag
6891 label $top.ntag.l -text "Display nearby tags" -font optionfont
6892 checkbutton $top.ntag.b -variable showneartags
6893 pack $top.ntag.b $top.ntag.l -side left
6894 grid x $top.ntag -sticky w
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006895 label $top.tabstopl -text "tabstop" -font optionfont
6896 entry $top.tabstop -width 10 -textvariable tabstop
6897 grid x $top.tabstopl $top.tabstop -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006898
6899 label $top.cdisp -text "Colors: press to choose"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006900 $top.cdisp configure -font $uifont
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006901 grid $top.cdisp - -sticky w -pady 10
6902 label $top.bg -padx 40 -relief sunk -background $bgcolor
6903 button $top.bgbut -text "Background" -font optionfont \
6904 -command [list choosecolor bgcolor 0 $top.bg background setbg]
6905 grid x $top.bgbut $top.bg -sticky w
6906 label $top.fg -padx 40 -relief sunk -background $fgcolor
6907 button $top.fgbut -text "Foreground" -font optionfont \
6908 -command [list choosecolor fgcolor 0 $top.fg foreground setfg]
6909 grid x $top.fgbut $top.fg -sticky w
6910 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
6911 button $top.diffoldbut -text "Diff: old lines" -font optionfont \
6912 -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
6913 [list $ctext tag conf d0 -foreground]]
6914 grid x $top.diffoldbut $top.diffold -sticky w
6915 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
6916 button $top.diffnewbut -text "Diff: new lines" -font optionfont \
6917 -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
6918 [list $ctext tag conf d1 -foreground]]
6919 grid x $top.diffnewbut $top.diffnew -sticky w
6920 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
6921 button $top.hunksepbut -text "Diff: hunk header" -font optionfont \
6922 -command [list choosecolor diffcolors 2 $top.hunksep \
6923 "diff hunk header" \
6924 [list $ctext tag conf hunksep -foreground]]
6925 grid x $top.hunksepbut $top.hunksep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -04006926 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
6927 button $top.selbgbut -text "Select bg" -font optionfont \
6928 -command [list choosecolor selectbgcolor 0 $top.bg background setselbg]
6929 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006930
Paul Mackerras712fcc02005-11-30 09:28:16 +11006931 frame $top.buts
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04006932 button $top.buts.ok -text "OK" -command prefsok -default active
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006933 $top.buts.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04006934 button $top.buts.can -text "Cancel" -command prefscan -default normal
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006935 $top.buts.can configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11006936 grid $top.buts.ok $top.buts.can
6937 grid columnconfigure $top.buts 0 -weight 1 -uniform a
6938 grid columnconfigure $top.buts 1 -weight 1 -uniform a
6939 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04006940 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +11006941}
6942
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006943proc choosecolor {v vi w x cmd} {
6944 global $v
6945
6946 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
6947 -title "Gitk: choose color for $x"]
6948 if {$c eq {}} return
6949 $w conf -background $c
6950 lset $v $vi $c
6951 eval $cmd $c
6952}
6953
Mark Levedahl60378c02007-05-20 12:12:48 -04006954proc setselbg {c} {
6955 global bglist cflist
6956 foreach w $bglist {
6957 $w configure -selectbackground $c
6958 }
6959 $cflist tag configure highlight \
6960 -background [$cflist cget -selectbackground]
6961 allcanvs itemconf secsel -fill $c
6962}
6963
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006964proc setbg {c} {
6965 global bglist
6966
6967 foreach w $bglist {
6968 $w conf -background $c
6969 }
6970}
6971
6972proc setfg {c} {
6973 global fglist canv
6974
6975 foreach w $fglist {
6976 $w conf -foreground $c
6977 }
6978 allcanvs itemconf text -fill $c
6979 $canv itemconf circle -outline $c
6980}
6981
Paul Mackerras712fcc02005-11-30 09:28:16 +11006982proc prefscan {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006983 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006984 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras712fcc02005-11-30 09:28:16 +11006985
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006986 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11006987 set $v $oldprefs($v)
6988 }
6989 catch {destroy $prefstop}
6990 unset prefstop
6991}
6992
6993proc prefsok {} {
6994 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006995 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006996 global charspc ctext tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11006997
6998 catch {destroy $prefstop}
6999 unset prefstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007000 $ctext configure -tabs "[expr {$tabstop * $charspc}]"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007001 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
7002 if {$showlocalchanges} {
7003 doshowlocalchanges
7004 } else {
7005 dohidelocalchanges
7006 }
7007 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11007008 if {$maxwidth != $oldprefs(maxwidth)
7009 || $maxgraphpct != $oldprefs(maxgraphpct)} {
7010 redisplay
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007011 } elseif {$showneartags != $oldprefs(showneartags)} {
7012 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +11007013 }
7014}
7015
7016proc formatdate {d} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007017 if {$d ne {}} {
7018 set d [clock format $d -format "%Y-%m-%d %H:%M:%S"]
7019 }
7020 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +11007021}
7022
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007023# This list of encoding names and aliases is distilled from
7024# http://www.iana.org/assignments/character-sets.
7025# Not all of them are supported by Tcl.
7026set encoding_aliases {
7027 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
7028 ISO646-US US-ASCII us IBM367 cp367 csASCII }
7029 { ISO-10646-UTF-1 csISO10646UTF1 }
7030 { ISO_646.basic:1983 ref csISO646basic1983 }
7031 { INVARIANT csINVARIANT }
7032 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
7033 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
7034 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
7035 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
7036 { NATS-DANO iso-ir-9-1 csNATSDANO }
7037 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
7038 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
7039 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
7040 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
7041 { ISO-2022-KR csISO2022KR }
7042 { EUC-KR csEUCKR }
7043 { ISO-2022-JP csISO2022JP }
7044 { ISO-2022-JP-2 csISO2022JP2 }
7045 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
7046 csISO13JISC6220jp }
7047 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
7048 { IT iso-ir-15 ISO646-IT csISO15Italian }
7049 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
7050 { ES iso-ir-17 ISO646-ES csISO17Spanish }
7051 { greek7-old iso-ir-18 csISO18Greek7Old }
7052 { latin-greek iso-ir-19 csISO19LatinGreek }
7053 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
7054 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
7055 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
7056 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
7057 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
7058 { BS_viewdata iso-ir-47 csISO47BSViewdata }
7059 { INIS iso-ir-49 csISO49INIS }
7060 { INIS-8 iso-ir-50 csISO50INIS8 }
7061 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
7062 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
7063 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
7064 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
7065 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
7066 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
7067 csISO60Norwegian1 }
7068 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
7069 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
7070 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
7071 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
7072 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
7073 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
7074 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
7075 { greek7 iso-ir-88 csISO88Greek7 }
7076 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
7077 { iso-ir-90 csISO90 }
7078 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
7079 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
7080 csISO92JISC62991984b }
7081 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
7082 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
7083 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
7084 csISO95JIS62291984handadd }
7085 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
7086 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
7087 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
7088 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
7089 CP819 csISOLatin1 }
7090 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
7091 { T.61-7bit iso-ir-102 csISO102T617bit }
7092 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
7093 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
7094 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
7095 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
7096 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
7097 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
7098 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
7099 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
7100 arabic csISOLatinArabic }
7101 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
7102 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
7103 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
7104 greek greek8 csISOLatinGreek }
7105 { T.101-G2 iso-ir-128 csISO128T101G2 }
7106 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
7107 csISOLatinHebrew }
7108 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
7109 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
7110 { CSN_369103 iso-ir-139 csISO139CSN369103 }
7111 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
7112 { ISO_6937-2-add iso-ir-142 csISOTextComm }
7113 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
7114 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
7115 csISOLatinCyrillic }
7116 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
7117 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
7118 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
7119 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
7120 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
7121 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
7122 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
7123 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
7124 { ISO_10367-box iso-ir-155 csISO10367Box }
7125 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
7126 { latin-lap lap iso-ir-158 csISO158Lap }
7127 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
7128 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
7129 { us-dk csUSDK }
7130 { dk-us csDKUS }
7131 { JIS_X0201 X0201 csHalfWidthKatakana }
7132 { KSC5636 ISO646-KR csKSC5636 }
7133 { ISO-10646-UCS-2 csUnicode }
7134 { ISO-10646-UCS-4 csUCS4 }
7135 { DEC-MCS dec csDECMCS }
7136 { hp-roman8 roman8 r8 csHPRoman8 }
7137 { macintosh mac csMacintosh }
7138 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
7139 csIBM037 }
7140 { IBM038 EBCDIC-INT cp038 csIBM038 }
7141 { IBM273 CP273 csIBM273 }
7142 { IBM274 EBCDIC-BE CP274 csIBM274 }
7143 { IBM275 EBCDIC-BR cp275 csIBM275 }
7144 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
7145 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
7146 { IBM280 CP280 ebcdic-cp-it csIBM280 }
7147 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
7148 { IBM284 CP284 ebcdic-cp-es csIBM284 }
7149 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
7150 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
7151 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
7152 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
7153 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
7154 { IBM424 cp424 ebcdic-cp-he csIBM424 }
7155 { IBM437 cp437 437 csPC8CodePage437 }
7156 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
7157 { IBM775 cp775 csPC775Baltic }
7158 { IBM850 cp850 850 csPC850Multilingual }
7159 { IBM851 cp851 851 csIBM851 }
7160 { IBM852 cp852 852 csPCp852 }
7161 { IBM855 cp855 855 csIBM855 }
7162 { IBM857 cp857 857 csIBM857 }
7163 { IBM860 cp860 860 csIBM860 }
7164 { IBM861 cp861 861 cp-is csIBM861 }
7165 { IBM862 cp862 862 csPC862LatinHebrew }
7166 { IBM863 cp863 863 csIBM863 }
7167 { IBM864 cp864 csIBM864 }
7168 { IBM865 cp865 865 csIBM865 }
7169 { IBM866 cp866 866 csIBM866 }
7170 { IBM868 CP868 cp-ar csIBM868 }
7171 { IBM869 cp869 869 cp-gr csIBM869 }
7172 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
7173 { IBM871 CP871 ebcdic-cp-is csIBM871 }
7174 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
7175 { IBM891 cp891 csIBM891 }
7176 { IBM903 cp903 csIBM903 }
7177 { IBM904 cp904 904 csIBBM904 }
7178 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
7179 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
7180 { IBM1026 CP1026 csIBM1026 }
7181 { EBCDIC-AT-DE csIBMEBCDICATDE }
7182 { EBCDIC-AT-DE-A csEBCDICATDEA }
7183 { EBCDIC-CA-FR csEBCDICCAFR }
7184 { EBCDIC-DK-NO csEBCDICDKNO }
7185 { EBCDIC-DK-NO-A csEBCDICDKNOA }
7186 { EBCDIC-FI-SE csEBCDICFISE }
7187 { EBCDIC-FI-SE-A csEBCDICFISEA }
7188 { EBCDIC-FR csEBCDICFR }
7189 { EBCDIC-IT csEBCDICIT }
7190 { EBCDIC-PT csEBCDICPT }
7191 { EBCDIC-ES csEBCDICES }
7192 { EBCDIC-ES-A csEBCDICESA }
7193 { EBCDIC-ES-S csEBCDICESS }
7194 { EBCDIC-UK csEBCDICUK }
7195 { EBCDIC-US csEBCDICUS }
7196 { UNKNOWN-8BIT csUnknown8BiT }
7197 { MNEMONIC csMnemonic }
7198 { MNEM csMnem }
7199 { VISCII csVISCII }
7200 { VIQR csVIQR }
7201 { KOI8-R csKOI8R }
7202 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
7203 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
7204 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
7205 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
7206 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
7207 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
7208 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
7209 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
7210 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
7211 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
7212 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
7213 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
7214 { IBM1047 IBM-1047 }
7215 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
7216 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
7217 { UNICODE-1-1 csUnicode11 }
7218 { CESU-8 csCESU-8 }
7219 { BOCU-1 csBOCU-1 }
7220 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
7221 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
7222 l8 }
7223 { ISO-8859-15 ISO_8859-15 Latin-9 }
7224 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
7225 { GBK CP936 MS936 windows-936 }
7226 { JIS_Encoding csJISEncoding }
7227 { Shift_JIS MS_Kanji csShiftJIS }
7228 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
7229 EUC-JP }
7230 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
7231 { ISO-10646-UCS-Basic csUnicodeASCII }
7232 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
7233 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
7234 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
7235 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
7236 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
7237 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
7238 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
7239 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
7240 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
7241 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
7242 { Adobe-Standard-Encoding csAdobeStandardEncoding }
7243 { Ventura-US csVenturaUS }
7244 { Ventura-International csVenturaInternational }
7245 { PC8-Danish-Norwegian csPC8DanishNorwegian }
7246 { PC8-Turkish csPC8Turkish }
7247 { IBM-Symbols csIBMSymbols }
7248 { IBM-Thai csIBMThai }
7249 { HP-Legal csHPLegal }
7250 { HP-Pi-font csHPPiFont }
7251 { HP-Math8 csHPMath8 }
7252 { Adobe-Symbol-Encoding csHPPSMath }
7253 { HP-DeskTop csHPDesktop }
7254 { Ventura-Math csVenturaMath }
7255 { Microsoft-Publishing csMicrosoftPublishing }
7256 { Windows-31J csWindows31J }
7257 { GB2312 csGB2312 }
7258 { Big5 csBig5 }
7259}
7260
7261proc tcl_encoding {enc} {
7262 global encoding_aliases
7263 set names [encoding names]
7264 set lcnames [string tolower $names]
7265 set enc [string tolower $enc]
7266 set i [lsearch -exact $lcnames $enc]
7267 if {$i < 0} {
7268 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
7269 if {[regsub {^iso[-_]} $enc iso encx]} {
7270 set i [lsearch -exact $lcnames $encx]
7271 }
7272 }
7273 if {$i < 0} {
7274 foreach l $encoding_aliases {
7275 set ll [string tolower $l]
7276 if {[lsearch -exact $ll $enc] < 0} continue
7277 # look through the aliases for one that tcl knows about
7278 foreach e $ll {
7279 set i [lsearch -exact $lcnames $e]
7280 if {$i < 0} {
7281 if {[regsub {^iso[-_]} $e iso ex]} {
7282 set i [lsearch -exact $lcnames $ex]
7283 }
7284 }
7285 if {$i >= 0} break
7286 }
7287 break
7288 }
7289 }
7290 if {$i >= 0} {
7291 return [lindex $names $i]
7292 }
7293 return {}
7294}
7295
Paul Mackerras1d10f362005-05-15 12:55:47 +00007296# defaults...
7297set datemode 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007298set diffopts "-U 5 -p"
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03007299set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -08007300
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007301set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -08007302catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +11007303 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -08007304}
7305if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007306 set gitencoding "utf-8"
7307}
7308set tclencoding [tcl_encoding $gitencoding]
7309if {$tclencoding == {}} {
7310 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -08007311}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007312
7313set mainfont {Helvetica 9}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007314set textfont {Courier 9}
Keith Packard4840be62006-04-04 00:19:45 -07007315set uifont {Helvetica 9 bold}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007316set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -04007317set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +10007318set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007319set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +11007320set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +11007321set fastdate 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007322set uparrowlen 7
7323set downarrowlen 7
7324set mingaplen 30
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007325set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007326set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007327set showneartags 1
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007328set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +10007329set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007330set showlocalchanges 1
Paul Mackerras1d10f362005-05-15 12:55:47 +00007331
7332set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007333set bgcolor white
7334set fgcolor black
7335set diffcolors {red "#00a000" blue}
Mark Levedahl60378c02007-05-20 12:12:48 -04007336set selectbgcolor gray85
Paul Mackerras1d10f362005-05-15 12:55:47 +00007337
7338catch {source ~/.gitk}
7339
Paul Mackerras712fcc02005-11-30 09:28:16 +11007340font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +00007341
Paul Mackerras1d10f362005-05-15 12:55:47 +00007342set revtreeargs {}
7343foreach arg $argv {
7344 switch -regexp -- $arg {
7345 "^$" { }
Paul Mackerras1d10f362005-05-15 12:55:47 +00007346 "^-d" { set datemode 1 }
Paul Mackerras1d10f362005-05-15 12:55:47 +00007347 default {
7348 lappend revtreeargs $arg
7349 }
7350 }
7351}
7352
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007353# check that we can find a .git directory somewhere...
7354set gitdir [gitdir]
7355if {![file isdirectory $gitdir]} {
Paul Mackerrase54be9e2006-05-26 22:34:30 +10007356 show_error {} . "Cannot find the git directory \"$gitdir\"."
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007357 exit 1
7358}
7359
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007360set cmdline_files {}
7361set i [lsearch -exact $revtreeargs "--"]
7362if {$i >= 0} {
7363 set cmdline_files [lrange $revtreeargs [expr {$i + 1}] end]
7364 set revtreeargs [lrange $revtreeargs 0 [expr {$i - 1}]]
7365} elseif {$revtreeargs ne {}} {
7366 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03007367 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007368 set cmdline_files [split $f "\n"]
7369 set n [llength $cmdline_files]
7370 set revtreeargs [lrange $revtreeargs 0 end-$n]
7371 } err]} {
7372 # unfortunately we get both stdout and stderr in $err,
7373 # so look for "fatal:".
7374 set i [string first "fatal:" $err]
7375 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -07007376 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007377 }
Paul Mackerrase54be9e2006-05-26 22:34:30 +10007378 show_error {} . "Bad arguments to gitk:\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007379 exit 1
7380 }
7381}
7382
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007383set nullid "0000000000000000000000000000000000000000"
7384
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007385set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007386set history {}
7387set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007388set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007389set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +10007390set highlight_paths {}
Paul Mackerras1902c272006-05-25 21:25:13 +10007391set searchdirn -forwards
Paul Mackerras4e7d6772006-05-30 21:33:07 +10007392set boldrows {}
7393set boldnamerows {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007394set diffelide {0 0}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007395
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007396set optim_delay 16
7397
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007398set nextviewnum 1
7399set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007400set selectedview 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007401set selectedhlview None
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007402set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007403set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007404set viewargs(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007405
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007406set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007407set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +00007408set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +10007409set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007410set lookingforhead 0
7411set localrow -1
7412set lserial 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007413setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007414makewindow
Doug Maxey6c283322006-12-10 14:31:46 -06007415wm title . "[file tail $argv0]: [file tail [pwd]]"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007416readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10007417
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007418if {$cmdline_files ne {} || $revtreeargs ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007419 # create a view for the files/dirs specified on the command line
7420 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007421 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007422 set nextviewnum 2
7423 set viewname(1) "Command line"
7424 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007425 set viewargs(1) $revtreeargs
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007426 set viewperm(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007427 addviewmenu 1
Paul Mackerras3cd204e2006-11-23 21:06:16 +11007428 .bar.view entryconf Edit* -state normal
7429 .bar.view entryconf Delete* -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007430}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007431
7432if {[info exists permviews]} {
7433 foreach v $permviews {
7434 set n $nextviewnum
7435 incr nextviewnum
7436 set viewname($n) [lindex $v 0]
7437 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007438 set viewargs($n) [lindex $v 2]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007439 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007440 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007441 }
7442}
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10007443getcommits