blob: 73324cfb7169a0c53d76c5ef6878097e7e29e33d [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 Mackerras10299152006-08-02 09:52:01 +1000876
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000877 set fakerowmenu .fakerowmenu
878 menu $fakerowmenu -tearoff 0
879 $fakerowmenu add command -label "Diff this -> selected" \
880 -command {diffvssel 0}
881 $fakerowmenu add command -label "Diff selected -> this" \
882 -command {diffvssel 1}
883 $fakerowmenu add command -label "Make patch" -command mkpatch
884# $fakerowmenu add command -label "Commit" -command {mkcommit 0}
885# $fakerowmenu add command -label "Commit all" -command {mkcommit 1}
886# $fakerowmenu add command -label "Revert local changes" -command revertlocal
887
Paul Mackerras10299152006-08-02 09:52:01 +1000888 set headctxmenu .headctxmenu
889 menu $headctxmenu -tearoff 0
890 $headctxmenu add command -label "Check out this branch" \
891 -command cobranch
892 $headctxmenu add command -label "Remove this branch" \
893 -command rmbranch
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000894}
895
Paul Mackerrasbe0cd092006-03-31 09:55:11 +1100896# mouse-2 makes all windows scan vertically, but only the one
897# the cursor is in scans horizontally
898proc canvscan {op w x y} {
899 global canv canv2 canv3
900 foreach c [list $canv $canv2 $canv3] {
901 if {$c == $w} {
902 $c scan $op $x $y
903 } else {
904 $c scan $op 0 $y
905 }
906 }
907}
908
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100909proc scrollcanv {cscroll f0 f1} {
910 $cscroll set $f0 $f1
911 drawfrac $f0 $f1
Paul Mackerras908c3582006-05-20 09:38:11 +1000912 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100913}
914
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000915# when we make a key binding for the toplevel, make sure
916# it doesn't get triggered when that key is pressed in the
917# find string entry widget.
918proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000919 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000920 bind . $ev $script
921 set escript [bind Entry $ev]
922 if {$escript == {}} {
923 set escript [bind Entry <Key>]
924 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000925 foreach e $entries {
926 bind $e $ev "$escript; break"
927 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000928}
929
930# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000931# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000932proc click {w} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000933 global entries
934 foreach e $entries {
935 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000936 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000937 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000938}
939
940proc savestuff {w} {
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400941 global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +1100942 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000943 global maxwidth showneartags showlocalchanges
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000944 global viewname viewfiles viewargs viewperm nextviewnum
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400945 global cmitmode wrapcomment
Mark Levedahl60378c02007-05-20 12:12:48 -0400946 global colors bgcolor fgcolor diffcolors selectbgcolor
Paul Mackerras4ef17532005-07-27 22:16:51 -0500947
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000948 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000949 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000950 catch {
951 set f [open "~/.gitk-new" w]
Paul Mackerrasf0654862005-07-18 14:29:03 -0400952 puts $f [list set mainfont $mainfont]
953 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -0700954 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400955 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -0400956 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +1000957 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +1000958 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000959 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400960 puts $f [list set wrapcomment $wrapcomment]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +1000961 puts $f [list set showneartags $showneartags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000962 puts $f [list set showlocalchanges $showlocalchanges]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000963 puts $f [list set bgcolor $bgcolor]
964 puts $f [list set fgcolor $fgcolor]
965 puts $f [list set colors $colors]
966 puts $f [list set diffcolors $diffcolors]
Mark Levedahl60378c02007-05-20 12:12:48 -0400967 puts $f [list set selectbgcolor $selectbgcolor]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500968
Mark Levedahlb6047c52007-02-08 22:22:24 -0500969 puts $f "set geometry(main) [wm geometry .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500970 puts $f "set geometry(topwidth) [winfo width .tf]"
971 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500972 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
973 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500974 puts $f "set geometry(botwidth) [winfo width .bleft]"
975 puts $f "set geometry(botheight) [winfo height .bleft]"
976
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000977 puts -nonewline $f "set permviews {"
978 for {set v 0} {$v < $nextviewnum} {incr v} {
979 if {$viewperm($v)} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000980 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000981 }
982 }
983 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000984 close $f
985 file rename -force "~/.gitk-new" "~/.gitk"
986 }
987 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +0000988}
989
Paul Mackerras43bddeb2005-05-15 23:19:18 +0000990proc resizeclistpanes {win w} {
991 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +1100992 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +0000993 set s0 [$win sash coord 0]
994 set s1 [$win sash coord 1]
995 if {$w < 60} {
996 set sash0 [expr {int($w/2 - 2)}]
997 set sash1 [expr {int($w*5/6 - 2)}]
998 } else {
999 set factor [expr {1.0 * $w / $oldwidth($win)}]
1000 set sash0 [expr {int($factor * [lindex $s0 0])}]
1001 set sash1 [expr {int($factor * [lindex $s1 0])}]
1002 if {$sash0 < 30} {
1003 set sash0 30
1004 }
1005 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001006 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001007 }
1008 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001009 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001010 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001011 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001012 }
1013 }
1014 }
1015 $win sash place 0 $sash0 [lindex $s0 1]
1016 $win sash place 1 $sash1 [lindex $s1 1]
1017 }
1018 set oldwidth($win) $w
1019}
1020
1021proc resizecdetpanes {win w} {
1022 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11001023 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001024 set s0 [$win sash coord 0]
1025 if {$w < 60} {
1026 set sash0 [expr {int($w*3/4 - 2)}]
1027 } else {
1028 set factor [expr {1.0 * $w / $oldwidth($win)}]
1029 set sash0 [expr {int($factor * [lindex $s0 0])}]
1030 if {$sash0 < 45} {
1031 set sash0 45
1032 }
1033 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001034 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001035 }
1036 }
1037 $win sash place 0 $sash0 [lindex $s0 1]
1038 }
1039 set oldwidth($win) $w
1040}
1041
Paul Mackerrasb5721c72005-05-10 12:08:22 +00001042proc allcanvs args {
1043 global canv canv2 canv3
1044 eval $canv $args
1045 eval $canv2 $args
1046 eval $canv3 $args
1047}
1048
1049proc bindall {event action} {
1050 global canv canv2 canv3
1051 bind $canv $event $action
1052 bind $canv2 $event $action
1053 bind $canv3 $event $action
1054}
1055
Paul Mackerras9a40c502005-05-12 23:46:16 +00001056proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001057 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00001058 set w .about
1059 if {[winfo exists $w]} {
1060 raise $w
1061 return
1062 }
1063 toplevel $w
1064 wm title $w "About gitk"
1065 message $w.m -text {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001066Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00001067
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001068Copyright © 2005-2006 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00001069
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10001070Use and redistribute under the terms of the GNU General Public License} \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001071 -justify center -aspect 400 -border 2 -bg white -relief groove
1072 pack $w.m -side top -fill x -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001073 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001074 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00001075 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001076 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001077 bind $w <Visibility> "focus $w.ok"
1078 bind $w <Key-Escape> "destroy $w"
1079 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00001080}
1081
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001082proc keys {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001083 global uifont
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001084 set w .keys
1085 if {[winfo exists $w]} {
1086 raise $w
1087 return
1088 }
1089 toplevel $w
1090 wm title $w "Gitk key bindings"
1091 message $w.m -text {
1092Gitk key bindings:
1093
1094<Ctrl-Q> Quit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001095<Home> Move to first commit
1096<End> Move to last commit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001097<Up>, p, i Move up one commit
1098<Down>, n, k Move down one commit
1099<Left>, z, j Go back in history list
1100<Right>, x, l Go forward in history list
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001101<PageUp> Move up one page in commit list
1102<PageDown> Move down one page in commit list
1103<Ctrl-Home> Scroll to top of commit list
1104<Ctrl-End> Scroll to bottom of commit list
1105<Ctrl-Up> Scroll commit list up one line
1106<Ctrl-Down> Scroll commit list down one line
1107<Ctrl-PageUp> Scroll commit list up one page
1108<Ctrl-PageDown> Scroll commit list down one page
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001109<Shift-Up> Move to previous highlighted line
1110<Shift-Down> Move to next highlighted line
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001111<Delete>, b Scroll diff view up one page
1112<Backspace> Scroll diff view up one page
1113<Space> Scroll diff view down one page
1114u Scroll diff view up 18 lines
1115d Scroll diff view down 18 lines
1116<Ctrl-F> Find
1117<Ctrl-G> Move to next find hit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001118<Return> Move to next find hit
1119/ Move to next find hit, or redo find
1120? Move to previous find hit
1121f Scroll diff view to next file
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001122<Ctrl-S> Search for next hit in diff view
1123<Ctrl-R> Search for previous hit in diff view
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001124<Ctrl-KP+> Increase font size
1125<Ctrl-plus> Increase font size
1126<Ctrl-KP-> Decrease font size
1127<Ctrl-minus> Decrease font size
Eric Wonge7a09192007-02-23 12:36:34 -08001128<F5> Update
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001129} \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001130 -justify left -bg white -border 2 -relief groove
1131 pack $w.m -side top -fill both -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001132 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001133 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001134 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001135 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001136 bind $w <Visibility> "focus $w.ok"
1137 bind $w <Key-Escape> "destroy $w"
1138 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001139}
1140
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001141# Procedures for manipulating the file list window at the
1142# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001143
1144proc treeview {w l openlevs} {
1145 global treecontents treediropen treeheight treeparent treeindex
1146
1147 set ix 0
1148 set treeindex() 0
1149 set lev 0
1150 set prefix {}
1151 set prefixend -1
1152 set prefendstack {}
1153 set htstack {}
1154 set ht 0
1155 set treecontents() {}
1156 $w conf -state normal
1157 foreach f $l {
1158 while {[string range $f 0 $prefixend] ne $prefix} {
1159 if {$lev <= $openlevs} {
1160 $w mark set e:$treeindex($prefix) "end -1c"
1161 $w mark gravity e:$treeindex($prefix) left
1162 }
1163 set treeheight($prefix) $ht
1164 incr ht [lindex $htstack end]
1165 set htstack [lreplace $htstack end end]
1166 set prefixend [lindex $prefendstack end]
1167 set prefendstack [lreplace $prefendstack end end]
1168 set prefix [string range $prefix 0 $prefixend]
1169 incr lev -1
1170 }
1171 set tail [string range $f [expr {$prefixend+1}] end]
1172 while {[set slash [string first "/" $tail]] >= 0} {
1173 lappend htstack $ht
1174 set ht 0
1175 lappend prefendstack $prefixend
1176 incr prefixend [expr {$slash + 1}]
1177 set d [string range $tail 0 $slash]
1178 lappend treecontents($prefix) $d
1179 set oldprefix $prefix
1180 append prefix $d
1181 set treecontents($prefix) {}
1182 set treeindex($prefix) [incr ix]
1183 set treeparent($prefix) $oldprefix
1184 set tail [string range $tail [expr {$slash+1}] end]
1185 if {$lev <= $openlevs} {
1186 set ht 1
1187 set treediropen($prefix) [expr {$lev < $openlevs}]
1188 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
1189 $w mark set d:$ix "end -1c"
1190 $w mark gravity d:$ix left
1191 set str "\n"
1192 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1193 $w insert end $str
1194 $w image create end -align center -image $bm -padx 1 \
1195 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10001196 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001197 $w mark set s:$ix "end -1c"
1198 $w mark gravity s:$ix left
1199 }
1200 incr lev
1201 }
1202 if {$tail ne {}} {
1203 if {$lev <= $openlevs} {
1204 incr ht
1205 set str "\n"
1206 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1207 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001208 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001209 }
1210 lappend treecontents($prefix) $tail
1211 }
1212 }
1213 while {$htstack ne {}} {
1214 set treeheight($prefix) $ht
1215 incr ht [lindex $htstack end]
1216 set htstack [lreplace $htstack end end]
1217 }
1218 $w conf -state disabled
1219}
1220
1221proc linetoelt {l} {
1222 global treeheight treecontents
1223
1224 set y 2
1225 set prefix {}
1226 while {1} {
1227 foreach e $treecontents($prefix) {
1228 if {$y == $l} {
1229 return "$prefix$e"
1230 }
1231 set n 1
1232 if {[string index $e end] eq "/"} {
1233 set n $treeheight($prefix$e)
1234 if {$y + $n > $l} {
1235 append prefix $e
1236 incr y
1237 break
1238 }
1239 }
1240 incr y $n
1241 }
1242 }
1243}
1244
Paul Mackerras45a9d502006-05-20 22:56:27 +10001245proc highlight_tree {y prefix} {
1246 global treeheight treecontents cflist
1247
1248 foreach e $treecontents($prefix) {
1249 set path $prefix$e
1250 if {[highlight_tag $path] ne {}} {
1251 $cflist tag add bold $y.0 "$y.0 lineend"
1252 }
1253 incr y
1254 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
1255 set y [highlight_tree $y $path]
1256 }
1257 }
1258 return $y
1259}
1260
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001261proc treeclosedir {w dir} {
1262 global treediropen treeheight treeparent treeindex
1263
1264 set ix $treeindex($dir)
1265 $w conf -state normal
1266 $w delete s:$ix e:$ix
1267 set treediropen($dir) 0
1268 $w image configure a:$ix -image tri-rt
1269 $w conf -state disabled
1270 set n [expr {1 - $treeheight($dir)}]
1271 while {$dir ne {}} {
1272 incr treeheight($dir) $n
1273 set dir $treeparent($dir)
1274 }
1275}
1276
1277proc treeopendir {w dir} {
1278 global treediropen treeheight treeparent treecontents treeindex
1279
1280 set ix $treeindex($dir)
1281 $w conf -state normal
1282 $w image configure a:$ix -image tri-dn
1283 $w mark set e:$ix s:$ix
1284 $w mark gravity e:$ix right
1285 set lev 0
1286 set str "\n"
1287 set n [llength $treecontents($dir)]
1288 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
1289 incr lev
1290 append str "\t"
1291 incr treeheight($x) $n
1292 }
1293 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001294 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001295 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001296 set iy $treeindex($de)
1297 $w mark set d:$iy e:$ix
1298 $w mark gravity d:$iy left
1299 $w insert e:$ix $str
1300 set treediropen($de) 0
1301 $w image create e:$ix -align center -image tri-rt -padx 1 \
1302 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10001303 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001304 $w mark set s:$iy e:$ix
1305 $w mark gravity s:$iy left
1306 set treeheight($de) 1
1307 } else {
1308 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001309 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001310 }
1311 }
1312 $w mark gravity e:$ix left
1313 $w conf -state disabled
1314 set treediropen($dir) 1
1315 set top [lindex [split [$w index @0,0] .] 0]
1316 set ht [$w cget -height]
1317 set l [lindex [split [$w index s:$ix] .] 0]
1318 if {$l < $top} {
1319 $w yview $l.0
1320 } elseif {$l + $n + 1 > $top + $ht} {
1321 set top [expr {$l + $n + 2 - $ht}]
1322 if {$l < $top} {
1323 set top $l
1324 }
1325 $w yview $top.0
1326 }
1327}
1328
1329proc treeclick {w x y} {
1330 global treediropen cmitmode ctext cflist cflist_top
1331
1332 if {$cmitmode ne "tree"} return
1333 if {![info exists cflist_top]} return
1334 set l [lindex [split [$w index "@$x,$y"] "."] 0]
1335 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1336 $cflist tag add highlight $l.0 "$l.0 lineend"
1337 set cflist_top $l
1338 if {$l == 1} {
1339 $ctext yview 1.0
1340 return
1341 }
1342 set e [linetoelt $l]
1343 if {[string index $e end] ne "/"} {
1344 showfile $e
1345 } elseif {$treediropen($e)} {
1346 treeclosedir $w $e
1347 } else {
1348 treeopendir $w $e
1349 }
1350}
1351
1352proc setfilelist {id} {
1353 global treefilelist cflist
1354
1355 treeview $cflist $treefilelist($id) 0
1356}
1357
1358image create bitmap tri-rt -background black -foreground blue -data {
1359 #define tri-rt_width 13
1360 #define tri-rt_height 13
1361 static unsigned char tri-rt_bits[] = {
1362 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
1363 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
1364 0x00, 0x00};
1365} -maskdata {
1366 #define tri-rt-mask_width 13
1367 #define tri-rt-mask_height 13
1368 static unsigned char tri-rt-mask_bits[] = {
1369 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
1370 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
1371 0x08, 0x00};
1372}
1373image create bitmap tri-dn -background black -foreground blue -data {
1374 #define tri-dn_width 13
1375 #define tri-dn_height 13
1376 static unsigned char tri-dn_bits[] = {
1377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
1378 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00};
1380} -maskdata {
1381 #define tri-dn-mask_width 13
1382 #define tri-dn-mask_height 13
1383 static unsigned char tri-dn-mask_bits[] = {
1384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
1385 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
1386 0x00, 0x00};
1387}
1388
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001389proc init_flist {first} {
Paul Mackerras89b11d32006-05-02 19:55:31 +10001390 global cflist cflist_top selectedline difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001391
1392 $cflist conf -state normal
1393 $cflist delete 0.0 end
1394 if {$first ne {}} {
1395 $cflist insert end $first
1396 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001397 $cflist tag add highlight 1.0 "1.0 lineend"
1398 } else {
1399 catch {unset cflist_top}
1400 }
1401 $cflist conf -state disabled
1402 set difffilestart {}
1403}
1404
Paul Mackerras63b79192006-05-20 21:31:52 +10001405proc highlight_tag {f} {
1406 global highlight_paths
1407
1408 foreach p $highlight_paths {
1409 if {[string match $p $f]} {
1410 return "bold"
1411 }
1412 }
1413 return {}
1414}
1415
1416proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001417 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001418
Paul Mackerras45a9d502006-05-20 22:56:27 +10001419 $cflist conf -state normal
1420 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10001421 set end [lindex [split [$cflist index end] .] 0]
1422 for {set l 2} {$l < $end} {incr l} {
1423 set line [$cflist get $l.0 "$l.0 lineend"]
1424 if {[highlight_tag $line] ne {}} {
1425 $cflist tag add bold $l.0 "$l.0 lineend"
1426 }
1427 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001428 } else {
1429 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10001430 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001431 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001432}
1433
1434proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001435 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001436
Paul Mackerras45a9d502006-05-20 22:56:27 +10001437 $cflist conf -state normal
1438 $cflist tag remove bold 1.0 end
1439 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001440}
1441
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001442proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001443 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001444
Paul Mackerras45a9d502006-05-20 22:56:27 +10001445 $cflist conf -state normal
1446 foreach f $fl {
1447 $cflist insert end "\n"
1448 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001449 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001450 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001451}
1452
1453proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001454 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001455
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001456 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001457 if {![info exists cflist_top]} return
1458 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10001459 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1460 $cflist tag add highlight $l.0 "$l.0 lineend"
1461 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001462 if {$l == 1} {
1463 $ctext yview 1.0
1464 } else {
1465 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001466 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001467}
1468
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001469# Functions for adding and removing shell-type quoting
1470
1471proc shellquote {str} {
1472 if {![string match "*\['\"\\ \t]*" $str]} {
1473 return $str
1474 }
1475 if {![string match "*\['\"\\]*" $str]} {
1476 return "\"$str\""
1477 }
1478 if {![string match "*'*" $str]} {
1479 return "'$str'"
1480 }
1481 return "\"[string map {\" \\\" \\ \\\\} $str]\""
1482}
1483
1484proc shellarglist {l} {
1485 set str {}
1486 foreach a $l {
1487 if {$str ne {}} {
1488 append str " "
1489 }
1490 append str [shellquote $a]
1491 }
1492 return $str
1493}
1494
1495proc shelldequote {str} {
1496 set ret {}
1497 set used -1
1498 while {1} {
1499 incr used
1500 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
1501 append ret [string range $str $used end]
1502 set used [string length $str]
1503 break
1504 }
1505 set first [lindex $first 0]
1506 set ch [string index $str $first]
1507 if {$first > $used} {
1508 append ret [string range $str $used [expr {$first - 1}]]
1509 set used $first
1510 }
1511 if {$ch eq " " || $ch eq "\t"} break
1512 incr used
1513 if {$ch eq "'"} {
1514 set first [string first "'" $str $used]
1515 if {$first < 0} {
1516 error "unmatched single-quote"
1517 }
1518 append ret [string range $str $used [expr {$first - 1}]]
1519 set used $first
1520 continue
1521 }
1522 if {$ch eq "\\"} {
1523 if {$used >= [string length $str]} {
1524 error "trailing backslash"
1525 }
1526 append ret [string index $str $used]
1527 continue
1528 }
1529 # here ch == "\""
1530 while {1} {
1531 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
1532 error "unmatched double-quote"
1533 }
1534 set first [lindex $first 0]
1535 set ch [string index $str $first]
1536 if {$first > $used} {
1537 append ret [string range $str $used [expr {$first - 1}]]
1538 set used $first
1539 }
1540 if {$ch eq "\""} break
1541 incr used
1542 append ret [string index $str $used]
1543 incr used
1544 }
1545 }
1546 return [list $used $ret]
1547}
1548
1549proc shellsplit {str} {
1550 set l {}
1551 while {1} {
1552 set str [string trimleft $str]
1553 if {$str eq {}} break
1554 set dq [shelldequote $str]
1555 set n [lindex $dq 0]
1556 set word [lindex $dq 1]
1557 set str [string range $str $n end]
1558 lappend l $word
1559 }
1560 return $l
1561}
1562
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001563# Code to implement multiple views
1564
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001565proc newview {ishighlight} {
1566 global nextviewnum newviewname newviewperm uifont newishighlight
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001567 global newviewargs revtreeargs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001568
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001569 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001570 set top .gitkview
1571 if {[winfo exists $top]} {
1572 raise $top
1573 return
1574 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001575 set newviewname($nextviewnum) "View $nextviewnum"
1576 set newviewperm($nextviewnum) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001577 set newviewargs($nextviewnum) [shellarglist $revtreeargs]
Mark Levedahl40b87ff2007-02-01 08:44:46 -05001578 vieweditor $top $nextviewnum "Gitk view definition"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001579}
1580
1581proc editview {} {
1582 global curview
1583 global viewname viewperm newviewname newviewperm
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001584 global viewargs newviewargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001585
1586 set top .gitkvedit-$curview
1587 if {[winfo exists $top]} {
1588 raise $top
1589 return
1590 }
1591 set newviewname($curview) $viewname($curview)
1592 set newviewperm($curview) $viewperm($curview)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001593 set newviewargs($curview) [shellarglist $viewargs($curview)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001594 vieweditor $top $curview "Gitk: edit view $viewname($curview)"
1595}
1596
1597proc vieweditor {top n title} {
1598 global newviewname newviewperm viewfiles
1599 global uifont
1600
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001601 toplevel $top
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001602 wm title $top $title
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001603 label $top.nl -text "Name" -font $uifont
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001604 entry $top.name -width 20 -textvariable newviewname($n) -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001605 grid $top.nl $top.name -sticky w -pady 5
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001606 checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) \
1607 -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001608 grid $top.perm - -pady 5 -sticky w
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001609 message $top.al -aspect 1000 -font $uifont \
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001610 -text "Commits to include (arguments to git rev-list):"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001611 grid $top.al - -sticky w -pady 5
1612 entry $top.args -width 50 -textvariable newviewargs($n) \
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001613 -background white -font $uifont
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001614 grid $top.args - -sticky ew -padx 5
1615 message $top.l -aspect 1000 -font $uifont \
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001616 -text "Enter files and directories to include, one per line:"
1617 grid $top.l - -sticky w
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001618 text $top.t -width 40 -height 10 -background white -font $uifont
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001619 if {[info exists viewfiles($n)]} {
1620 foreach f $viewfiles($n) {
1621 $top.t insert end $f
1622 $top.t insert end "\n"
1623 }
1624 $top.t delete {end - 1c} end
1625 $top.t mark set insert 0.0
1626 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001627 grid $top.t - -sticky ew -padx 5
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001628 frame $top.buts
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001629 button $top.buts.ok -text "OK" -command [list newviewok $top $n] \
1630 -font $uifont
1631 button $top.buts.can -text "Cancel" -command [list destroy $top] \
1632 -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001633 grid $top.buts.ok $top.buts.can
1634 grid columnconfigure $top.buts 0 -weight 1 -uniform a
1635 grid columnconfigure $top.buts 1 -weight 1 -uniform a
1636 grid $top.buts - -pady 10 -sticky ew
1637 focus $top.t
1638}
1639
Paul Mackerras908c3582006-05-20 09:38:11 +10001640proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001641 set nmenu [$m index end]
1642 for {set i $first} {$i <= $nmenu} {incr i} {
1643 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001644 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001645 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001646 }
1647 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001648}
1649
1650proc allviewmenus {n op args} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001651 global viewhlmenu
1652
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001653 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras908c3582006-05-20 09:38:11 +10001654 doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001655}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001656
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001657proc newviewok {top n} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001658 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001659 global viewname viewfiles viewperm selectedview curview
Paul Mackerras908c3582006-05-20 09:38:11 +10001660 global viewargs newviewargs viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001661
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001662 if {[catch {
1663 set newargs [shellsplit $newviewargs($n)]
1664 } err]} {
1665 error_popup "Error in commit selection arguments: $err"
1666 wm raise $top
1667 focus $top
1668 return
1669 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001670 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001671 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001672 set ft [string trim $f]
1673 if {$ft ne {}} {
1674 lappend files $ft
1675 }
1676 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001677 if {![info exists viewfiles($n)]} {
1678 # creating a new view
1679 incr nextviewnum
1680 set viewname($n) $newviewname($n)
1681 set viewperm($n) $newviewperm($n)
1682 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001683 set viewargs($n) $newargs
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001684 addviewmenu $n
1685 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001686 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001687 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001688 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001689 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001690 } else {
1691 # editing an existing view
1692 set viewperm($n) $newviewperm($n)
1693 if {$newviewname($n) ne $viewname($n)} {
1694 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001695 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10001696 entryconf [list -label $viewname($n)]
1697 doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
1698 entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001699 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001700 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001701 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001702 set viewargs($n) $newargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001703 if {$curview == $n} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001704 run updatecommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001705 }
1706 }
1707 }
1708 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001709}
1710
1711proc delview {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001712 global curview viewdata viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001713
1714 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10001715 if {[info exists hlview] && $hlview == $curview} {
1716 set selectedhlview None
1717 unset hlview
1718 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001719 allviewmenus $curview delete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001720 set viewdata($curview) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001721 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001722 showview 0
1723}
1724
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001725proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001726 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001727
1728 .bar.view add radiobutton -label $viewname($n) \
1729 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras908c3582006-05-20 09:38:11 +10001730 $viewhlmenu add radiobutton -label $viewname($n) \
1731 -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001732}
1733
Paul Mackerras22626ef2006-04-17 09:56:02 +10001734proc flatten {var} {
1735 global $var
1736
1737 set ret {}
1738 foreach i [array names $var] {
1739 lappend ret $i [set $var\($i\)]
1740 }
1741 return $ret
1742}
1743
1744proc unflatten {var l} {
1745 global $var
1746
1747 catch {unset $var}
1748 foreach {i v} $l {
1749 set $var\($i\) $v
1750 }
1751}
1752
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001753proc showview {n} {
1754 global curview viewdata viewfiles
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001755 global displayorder parentlist rowidlist rowoffsets
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001756 global colormap rowtextx commitrow nextcolor canvxmax
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001757 global numcommits rowrangelist commitlisted idrowranges rowchk
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001758 global selectedline currentid canv canvy0
1759 global matchinglines treediffs
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001760 global pending_select phase
Paul Mackerras322a8cc2006-10-15 18:03:46 +10001761 global commitidx rowlaidout rowoptim
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001762 global commfd
Paul Mackerrase507fd42007-06-16 21:51:08 +10001763 global selectedview selectfirst
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001764 global vparentlist vdisporder vcmitlisted
Paul Mackerras908c3582006-05-20 09:38:11 +10001765 global hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001766
1767 if {$n == $curview} return
1768 set selid {}
1769 if {[info exists selectedline]} {
1770 set selid $currentid
1771 set y [yc $selectedline]
1772 set ymax [lindex [$canv cget -scrollregion] 3]
1773 set span [$canv yview]
1774 set ytop [expr {[lindex $span 0] * $ymax}]
1775 set ybot [expr {[lindex $span 1] * $ymax}]
1776 if {$ytop < $y && $y < $ybot} {
1777 set yscreen [expr {$y - $ytop}]
1778 } else {
1779 set yscreen [expr {($ybot - $ytop) / 2}]
1780 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10001781 } elseif {[info exists pending_select]} {
1782 set selid $pending_select
1783 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001784 }
1785 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10001786 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001787 stopfindproc
Paul Mackerras22626ef2006-04-17 09:56:02 +10001788 if {$curview >= 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001789 set vparentlist($curview) $parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001790 set vdisporder($curview) $displayorder
1791 set vcmitlisted($curview) $commitlisted
Paul Mackerras22626ef2006-04-17 09:56:02 +10001792 if {$phase ne {}} {
1793 set viewdata($curview) \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001794 [list $phase $rowidlist $rowoffsets $rowrangelist \
1795 [flatten idrowranges] [flatten idinlist] \
Paul Mackerras322a8cc2006-10-15 18:03:46 +10001796 $rowlaidout $rowoptim $numcommits]
Paul Mackerras2516dae2006-04-21 10:35:31 +10001797 } elseif {![info exists viewdata($curview)]
1798 || [lindex $viewdata($curview) 0] ne {}} {
Paul Mackerras22626ef2006-04-17 09:56:02 +10001799 set viewdata($curview) \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001800 [list {} $rowidlist $rowoffsets $rowrangelist]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001801 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001802 }
1803 catch {unset matchinglines}
1804 catch {unset treediffs}
1805 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10001806 if {[info exists hlview] && $hlview == $n} {
1807 unset hlview
1808 set selectedhlview None
1809 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001810
1811 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001812 set selectedview $n
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001813 .bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}]
1814 .bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001815
1816 if {![info exists viewdata($n)]} {
Paul Mackerrase507fd42007-06-16 21:51:08 +10001817 if {$selid ne {}} {
1818 set pending_select $selid
1819 }
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10001820 getcommits
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001821 return
1822 }
1823
Paul Mackerras22626ef2006-04-17 09:56:02 +10001824 set v $viewdata($n)
1825 set phase [lindex $v 0]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001826 set displayorder $vdisporder($n)
1827 set parentlist $vparentlist($n)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001828 set commitlisted $vcmitlisted($n)
1829 set rowidlist [lindex $v 1]
1830 set rowoffsets [lindex $v 2]
1831 set rowrangelist [lindex $v 3]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001832 if {$phase eq {}} {
1833 set numcommits [llength $displayorder]
1834 catch {unset idrowranges}
Paul Mackerras22626ef2006-04-17 09:56:02 +10001835 } else {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001836 unflatten idrowranges [lindex $v 4]
1837 unflatten idinlist [lindex $v 5]
1838 set rowlaidout [lindex $v 6]
1839 set rowoptim [lindex $v 7]
1840 set numcommits [lindex $v 8]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001841 catch {unset rowchk}
Paul Mackerras22626ef2006-04-17 09:56:02 +10001842 }
1843
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001844 catch {unset colormap}
1845 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001846 set nextcolor 0
1847 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001848 set curview $n
1849 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001850 setcanvscroll
1851 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10001852 set row {}
1853 set selectfirst 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001854 if {$selid ne {} && [info exists commitrow($n,$selid)]} {
1855 set row $commitrow($n,$selid)
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001856 # try to get the selected row in the same position on the screen
1857 set ymax [lindex [$canv cget -scrollregion] 3]
1858 set ytop [expr {[yc $row] - $yscreen}]
1859 if {$ytop < 0} {
1860 set ytop 0
1861 }
1862 set yf [expr {$ytop * 1.0 / $ymax}]
1863 }
1864 allcanvs yview moveto $yf
1865 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10001866 if {$row ne {}} {
1867 selectline $row 0
1868 } elseif {$selid ne {}} {
1869 set pending_select $selid
1870 } else {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001871 set row [expr {[lindex $displayorder 0] eq $nullid}]
1872 if {$row < $numcommits} {
1873 selectline $row 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10001874 } else {
1875 set selectfirst 1
1876 }
1877 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001878 if {$phase ne {}} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001879 if {$phase eq "getcommits"} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001880 show_status "Reading commits..."
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001881 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001882 run chewcommits $n
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001883 } elseif {$numcommits == 0} {
1884 show_status "No commits selected"
Paul Mackerras2516dae2006-04-21 10:35:31 +10001885 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001886}
1887
Paul Mackerras908c3582006-05-20 09:38:11 +10001888# Stuff relating to the highlighting facility
1889
1890proc ishighlighted {row} {
Paul Mackerras164ff272006-05-29 19:50:02 +10001891 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10001892
1893 if {[info exists nhighlights($row)] && $nhighlights($row) > 0} {
1894 return $nhighlights($row)
1895 }
1896 if {[info exists vhighlights($row)] && $vhighlights($row) > 0} {
1897 return $vhighlights($row)
1898 }
1899 if {[info exists fhighlights($row)] && $fhighlights($row) > 0} {
1900 return $fhighlights($row)
1901 }
Paul Mackerras164ff272006-05-29 19:50:02 +10001902 if {[info exists rhighlights($row)] && $rhighlights($row) > 0} {
1903 return $rhighlights($row)
1904 }
Paul Mackerras908c3582006-05-20 09:38:11 +10001905 return 0
1906}
1907
1908proc bolden {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001909 global canv linehtag selectedline boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10001910
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001911 lappend boldrows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10001912 $canv itemconf $linehtag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10001913 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001914 $canv delete secsel
1915 set t [eval $canv create rect [$canv bbox $linehtag($row)] \
1916 -outline {{}} -tags secsel \
1917 -fill [$canv cget -selectbackground]]
1918 $canv lower $t
1919 }
1920}
1921
1922proc bolden_name {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001923 global canv2 linentag selectedline boldnamerows
Paul Mackerras908c3582006-05-20 09:38:11 +10001924
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001925 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10001926 $canv2 itemconf $linentag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10001927 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001928 $canv2 delete secsel
1929 set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
1930 -outline {{}} -tags secsel \
1931 -fill [$canv2 cget -selectbackground]]
1932 $canv2 lower $t
1933 }
1934}
1935
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001936proc unbolden {} {
1937 global mainfont boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10001938
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001939 set stillbold {}
1940 foreach row $boldrows {
Paul Mackerras908c3582006-05-20 09:38:11 +10001941 if {![ishighlighted $row]} {
1942 bolden $row $mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001943 } else {
1944 lappend stillbold $row
Paul Mackerras908c3582006-05-20 09:38:11 +10001945 }
1946 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001947 set boldrows $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10001948}
1949
1950proc addvhighlight {n} {
1951 global hlview curview viewdata vhl_done vhighlights commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001952
1953 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001954 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001955 }
1956 set hlview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001957 if {$n != $curview && ![info exists viewdata($n)]} {
1958 set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}]
1959 set vparentlist($n) {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001960 set vdisporder($n) {}
1961 set vcmitlisted($n) {}
1962 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10001963 }
1964 set vhl_done $commitidx($hlview)
1965 if {$vhl_done > 0} {
1966 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001967 }
1968}
1969
Paul Mackerras908c3582006-05-20 09:38:11 +10001970proc delvhighlight {} {
1971 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001972
1973 if {![info exists hlview]} return
1974 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001975 catch {unset vhighlights}
1976 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001977}
1978
Paul Mackerras908c3582006-05-20 09:38:11 +10001979proc vhighlightmore {} {
1980 global hlview vhl_done commitidx vhighlights
1981 global displayorder vdisporder curview mainfont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001982
1983 set font [concat $mainfont bold]
1984 set max $commitidx($hlview)
1985 if {$hlview == $curview} {
1986 set disp $displayorder
1987 } else {
1988 set disp $vdisporder($hlview)
1989 }
Paul Mackerras908c3582006-05-20 09:38:11 +10001990 set vr [visiblerows]
1991 set r0 [lindex $vr 0]
1992 set r1 [lindex $vr 1]
1993 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001994 set id [lindex $disp $i]
1995 if {[info exists commitrow($curview,$id)]} {
1996 set row $commitrow($curview,$id)
Paul Mackerras908c3582006-05-20 09:38:11 +10001997 if {$r0 <= $row && $row <= $r1} {
1998 if {![highlighted $row]} {
1999 bolden $row $font
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002000 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002001 set vhighlights($row) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002002 }
2003 }
2004 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002005 set vhl_done $max
2006}
2007
2008proc askvhighlight {row id} {
2009 global hlview vhighlights commitrow iddrawn mainfont
2010
2011 if {[info exists commitrow($hlview,$id)]} {
2012 if {[info exists iddrawn($id)] && ![ishighlighted $row]} {
2013 bolden $row [concat $mainfont bold]
2014 }
2015 set vhighlights($row) 1
2016 } else {
2017 set vhighlights($row) 0
2018 }
2019}
2020
2021proc hfiles_change {name ix op} {
2022 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras63b79192006-05-20 21:31:52 +10002023 global mainfont highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10002024
2025 if {[info exists filehighlight]} {
2026 # delete previous highlights
2027 catch {close $filehighlight}
2028 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002029 catch {unset fhighlights}
2030 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10002031 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10002032 }
Paul Mackerras63b79192006-05-20 21:31:52 +10002033 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002034 after cancel do_file_hl $fh_serial
2035 incr fh_serial
2036 if {$highlight_files ne {}} {
2037 after 300 do_file_hl $fh_serial
2038 }
2039}
2040
Paul Mackerras63b79192006-05-20 21:31:52 +10002041proc makepatterns {l} {
2042 set ret {}
2043 foreach e $l {
2044 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
2045 if {[string index $ee end] eq "/"} {
2046 lappend ret "$ee*"
2047 } else {
2048 lappend ret $ee
2049 lappend ret "$ee/*"
2050 }
2051 }
2052 return $ret
2053}
2054
Paul Mackerras908c3582006-05-20 09:38:11 +10002055proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002056 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002057
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002058 if {$gdttype eq "touching paths:"} {
2059 if {[catch {set paths [shellsplit $highlight_files]}]} return
2060 set highlight_paths [makepatterns $paths]
2061 highlight_filelist
2062 set gdtargs [concat -- $paths]
2063 } else {
2064 set gdtargs [list "-S$highlight_files"]
2065 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002066 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10002067 set filehighlight [open $cmd r+]
2068 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002069 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002070 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002071 drawvisible
2072 flushhighlights
2073}
2074
2075proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002076 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002077
2078 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002079 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002080 puts $filehighlight ""
2081 flush $filehighlight
2082 }
2083}
2084
2085proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002086 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002087
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002088 lappend fhl_list $id
2089 set fhighlights($row) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10002090 puts $filehighlight $id
2091}
2092
2093proc readfhighlight {} {
2094 global filehighlight fhighlights commitrow curview mainfont iddrawn
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002095 global fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002096
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002097 if {![info exists filehighlight]} {
2098 return 0
2099 }
2100 set nr 0
2101 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002102 set line [string trim $line]
2103 set i [lsearch -exact $fhl_list $line]
2104 if {$i < 0} continue
2105 for {set j 0} {$j < $i} {incr j} {
2106 set id [lindex $fhl_list $j]
2107 if {[info exists commitrow($curview,$id)]} {
2108 set fhighlights($commitrow($curview,$id)) 0
2109 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002110 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002111 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
2112 if {$line eq {}} continue
2113 if {![info exists commitrow($curview,$line)]} continue
2114 set row $commitrow($curview,$line)
2115 if {[info exists iddrawn($line)] && ![ishighlighted $row]} {
2116 bolden $row [concat $mainfont bold]
2117 }
2118 set fhighlights($row) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002119 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002120 if {[eof $filehighlight]} {
2121 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002122 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002123 catch {close $filehighlight}
2124 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002125 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10002126 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002127 next_hlcont
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002128 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002129}
2130
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002131proc find_change {name ix op} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002132 global nhighlights mainfont boldnamerows
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002133 global findstring findpattern findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10002134
2135 # delete previous highlights, if any
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002136 foreach row $boldnamerows {
2137 bolden_name $row $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10002138 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002139 set boldnamerows {}
2140 catch {unset nhighlights}
2141 unbolden
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002142 if {$findtype ne "Regexp"} {
2143 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
2144 $findstring]
2145 set findpattern "*$e*"
Paul Mackerras908c3582006-05-20 09:38:11 +10002146 }
2147 drawvisible
2148}
2149
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002150proc askfindhighlight {row id} {
2151 global nhighlights commitinfo iddrawn mainfont
2152 global findstring findtype findloc findpattern
Paul Mackerras908c3582006-05-20 09:38:11 +10002153
2154 if {![info exists commitinfo($id)]} {
2155 getcommit $id
2156 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002157 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10002158 set isbold 0
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002159 set fldtypes {Headline Author Date Committer CDate Comments}
2160 foreach f $info ty $fldtypes {
2161 if {$findloc ne "All fields" && $findloc ne $ty} {
2162 continue
Paul Mackerras908c3582006-05-20 09:38:11 +10002163 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002164 if {$findtype eq "Regexp"} {
2165 set doesmatch [regexp $findstring $f]
2166 } elseif {$findtype eq "IgnCase"} {
2167 set doesmatch [string match -nocase $findpattern $f]
2168 } else {
2169 set doesmatch [string match $findpattern $f]
2170 }
2171 if {$doesmatch} {
2172 if {$ty eq "Author"} {
2173 set isbold 2
2174 } else {
2175 set isbold 1
2176 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002177 }
2178 }
2179 if {[info exists iddrawn($id)]} {
2180 if {$isbold && ![ishighlighted $row]} {
2181 bolden $row [concat $mainfont bold]
2182 }
2183 if {$isbold >= 2} {
2184 bolden_name $row [concat $mainfont bold]
2185 }
2186 }
2187 set nhighlights($row) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002188}
2189
Paul Mackerras164ff272006-05-29 19:50:02 +10002190proc vrel_change {name ix op} {
2191 global highlight_related
2192
2193 rhighlight_none
2194 if {$highlight_related ne "None"} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002195 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002196 }
2197}
2198
2199# prepare for testing whether commits are descendents or ancestors of a
2200proc rhighlight_sel {a} {
2201 global descendent desc_todo ancestor anc_todo
2202 global highlight_related rhighlights
2203
2204 catch {unset descendent}
2205 set desc_todo [list $a]
2206 catch {unset ancestor}
2207 set anc_todo [list $a]
2208 if {$highlight_related ne "None"} {
2209 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002210 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002211 }
2212}
2213
2214proc rhighlight_none {} {
2215 global rhighlights
2216
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002217 catch {unset rhighlights}
2218 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10002219}
2220
2221proc is_descendent {a} {
2222 global curview children commitrow descendent desc_todo
2223
2224 set v $curview
2225 set la $commitrow($v,$a)
2226 set todo $desc_todo
2227 set leftover {}
2228 set done 0
2229 for {set i 0} {$i < [llength $todo]} {incr i} {
2230 set do [lindex $todo $i]
2231 if {$commitrow($v,$do) < $la} {
2232 lappend leftover $do
2233 continue
2234 }
2235 foreach nk $children($v,$do) {
2236 if {![info exists descendent($nk)]} {
2237 set descendent($nk) 1
2238 lappend todo $nk
2239 if {$nk eq $a} {
2240 set done 1
2241 }
2242 }
2243 }
2244 if {$done} {
2245 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2246 return
2247 }
2248 }
2249 set descendent($a) 0
2250 set desc_todo $leftover
2251}
2252
2253proc is_ancestor {a} {
2254 global curview parentlist commitrow ancestor anc_todo
2255
2256 set v $curview
2257 set la $commitrow($v,$a)
2258 set todo $anc_todo
2259 set leftover {}
2260 set done 0
2261 for {set i 0} {$i < [llength $todo]} {incr i} {
2262 set do [lindex $todo $i]
2263 if {![info exists commitrow($v,$do)] || $commitrow($v,$do) > $la} {
2264 lappend leftover $do
2265 continue
2266 }
2267 foreach np [lindex $parentlist $commitrow($v,$do)] {
2268 if {![info exists ancestor($np)]} {
2269 set ancestor($np) 1
2270 lappend todo $np
2271 if {$np eq $a} {
2272 set done 1
2273 }
2274 }
2275 }
2276 if {$done} {
2277 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2278 return
2279 }
2280 }
2281 set ancestor($a) 0
2282 set anc_todo $leftover
2283}
2284
2285proc askrelhighlight {row id} {
2286 global descendent highlight_related iddrawn mainfont rhighlights
2287 global selectedline ancestor
2288
2289 if {![info exists selectedline]} return
2290 set isbold 0
2291 if {$highlight_related eq "Descendent" ||
2292 $highlight_related eq "Not descendent"} {
2293 if {![info exists descendent($id)]} {
2294 is_descendent $id
2295 }
2296 if {$descendent($id) == ($highlight_related eq "Descendent")} {
2297 set isbold 1
2298 }
2299 } elseif {$highlight_related eq "Ancestor" ||
2300 $highlight_related eq "Not ancestor"} {
2301 if {![info exists ancestor($id)]} {
2302 is_ancestor $id
2303 }
2304 if {$ancestor($id) == ($highlight_related eq "Ancestor")} {
2305 set isbold 1
2306 }
2307 }
2308 if {[info exists iddrawn($id)]} {
2309 if {$isbold && ![ishighlighted $row]} {
2310 bolden $row [concat $mainfont bold]
2311 }
2312 }
2313 set rhighlights($row) $isbold
2314}
2315
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002316proc next_hlcont {} {
2317 global fhl_row fhl_dirn displayorder numcommits
2318 global vhighlights fhighlights nhighlights rhighlights
2319 global hlview filehighlight findstring highlight_related
2320
2321 if {![info exists fhl_dirn] || $fhl_dirn == 0} return
2322 set row $fhl_row
2323 while {1} {
2324 if {$row < 0 || $row >= $numcommits} {
2325 bell
2326 set fhl_dirn 0
2327 return
2328 }
2329 set id [lindex $displayorder $row]
2330 if {[info exists hlview]} {
2331 if {![info exists vhighlights($row)]} {
2332 askvhighlight $row $id
2333 }
2334 if {$vhighlights($row) > 0} break
2335 }
2336 if {$findstring ne {}} {
2337 if {![info exists nhighlights($row)]} {
2338 askfindhighlight $row $id
2339 }
2340 if {$nhighlights($row) > 0} break
2341 }
2342 if {$highlight_related ne "None"} {
2343 if {![info exists rhighlights($row)]} {
2344 askrelhighlight $row $id
2345 }
2346 if {$rhighlights($row) > 0} break
2347 }
2348 if {[info exists filehighlight]} {
2349 if {![info exists fhighlights($row)]} {
2350 # ask for a few more while we're at it...
2351 set r $row
2352 for {set n 0} {$n < 100} {incr n} {
2353 if {![info exists fhighlights($r)]} {
2354 askfilehighlight $r [lindex $displayorder $r]
2355 }
2356 incr r $fhl_dirn
2357 if {$r < 0 || $r >= $numcommits} break
2358 }
2359 flushhighlights
2360 }
2361 if {$fhighlights($row) < 0} {
2362 set fhl_row $row
2363 return
2364 }
2365 if {$fhighlights($row) > 0} break
2366 }
2367 incr row $fhl_dirn
2368 }
2369 set fhl_dirn 0
2370 selectline $row 1
2371}
2372
2373proc next_highlight {dirn} {
2374 global selectedline fhl_row fhl_dirn
2375 global hlview filehighlight findstring highlight_related
2376
2377 if {![info exists selectedline]} return
2378 if {!([info exists hlview] || $findstring ne {} ||
2379 $highlight_related ne "None" || [info exists filehighlight])} return
2380 set fhl_row [expr {$selectedline + $dirn}]
2381 set fhl_dirn $dirn
2382 next_hlcont
2383}
2384
2385proc cancel_next_highlight {} {
2386 global fhl_dirn
2387
2388 set fhl_dirn 0
2389}
2390
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002391# Graph layout functions
2392
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002393proc shortids {ids} {
2394 set res {}
2395 foreach id $ids {
2396 if {[llength $id] > 1} {
2397 lappend res [shortids $id]
2398 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
2399 lappend res [string range $id 0 7]
2400 } else {
2401 lappend res $id
2402 }
2403 }
2404 return $res
2405}
2406
2407proc incrange {l x o} {
2408 set n [llength $l]
2409 while {$x < $n} {
2410 set e [lindex $l $x]
2411 if {$e ne {}} {
2412 lset l $x [expr {$e + $o}]
2413 }
2414 incr x
2415 }
2416 return $l
2417}
2418
2419proc ntimes {n o} {
2420 set ret {}
2421 for {} {$n > 0} {incr n -1} {
2422 lappend ret $o
2423 }
2424 return $ret
2425}
2426
2427proc usedinrange {id l1 l2} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002428 global children commitrow curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002429
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002430 if {[info exists commitrow($curview,$id)]} {
2431 set r $commitrow($curview,$id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002432 if {$l1 <= $r && $r <= $l2} {
2433 return [expr {$r - $l1 + 1}]
2434 }
2435 }
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002436 set kids $children($curview,$id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002437 foreach c $kids {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002438 set r $commitrow($curview,$c)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002439 if {$l1 <= $r && $r <= $l2} {
2440 return [expr {$r - $l1 + 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002441 }
2442 }
2443 return 0
2444}
2445
2446proc sanity {row {full 0}} {
2447 global rowidlist rowoffsets
2448
2449 set col -1
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002450 set ids [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002451 foreach id $ids {
2452 incr col
2453 if {$id eq {}} continue
2454 if {$col < [llength $ids] - 1 &&
2455 [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002456 puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}"
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002457 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002458 set o [lindex $rowoffsets $row $col]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002459 set y $row
2460 set x $col
2461 while {$o ne {}} {
2462 incr y -1
2463 incr x $o
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002464 if {[lindex $rowidlist $y $x] != $id} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002465 puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]"
2466 puts " id=[shortids $id] check started at row $row"
2467 for {set i $row} {$i >= $y} {incr i -1} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002468 puts " row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}"
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002469 }
2470 break
2471 }
2472 if {!$full} break
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002473 set o [lindex $rowoffsets $y $x]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002474 }
2475 }
2476}
2477
2478proc makeuparrow {oid x y z} {
Paul Mackerras66e46f32006-10-14 19:21:02 +10002479 global rowidlist rowoffsets uparrowlen idrowranges displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002480
2481 for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
2482 incr y -1
2483 incr x $z
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002484 set off0 [lindex $rowoffsets $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002485 for {set x0 $x} {1} {incr x0} {
2486 if {$x0 >= [llength $off0]} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002487 set x0 [llength [lindex $rowoffsets [expr {$y-1}]]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002488 break
2489 }
2490 set z [lindex $off0 $x0]
2491 if {$z ne {}} {
2492 incr x0 $z
2493 break
2494 }
2495 }
2496 set z [expr {$x0 - $x}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002497 lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid]
2498 lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002499 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002500 set tmp [lreplace [lindex $rowoffsets $y] $x $x {}]
2501 lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1]
Paul Mackerras66e46f32006-10-14 19:21:02 +10002502 lappend idrowranges($oid) [lindex $displayorder $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002503}
2504
2505proc initlayout {} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10002506 global rowidlist rowoffsets displayorder commitlisted
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002507 global rowlaidout rowoptim
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002508 global idinlist rowchk rowrangelist idrowranges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002509 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002510 global nextcolor
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002511 global parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002512 global colormap rowtextx
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002513 global selectfirst
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002514
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002515 set numcommits 0
2516 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002517 set commitlisted {}
2518 set parentlist {}
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002519 set rowrangelist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002520 set nextcolor 0
2521 set rowidlist {{}}
2522 set rowoffsets {{}}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002523 catch {unset idinlist}
2524 catch {unset rowchk}
2525 set rowlaidout 0
2526 set rowoptim 0
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002527 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002528 catch {unset colormap}
2529 catch {unset rowtextx}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002530 catch {unset idrowranges}
Paul Mackerrase507fd42007-06-16 21:51:08 +10002531 set selectfirst 1
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002532}
2533
2534proc setcanvscroll {} {
2535 global canv canv2 canv3 numcommits linespc canvxmax canvy0
2536
2537 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
2538 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
2539 $canv2 conf -scrollregion [list 0 0 0 $ymax]
2540 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002541}
2542
2543proc visiblerows {} {
2544 global canv numcommits linespc
2545
2546 set ymax [lindex [$canv cget -scrollregion] 3]
2547 if {$ymax eq {} || $ymax == 0} return
2548 set f [$canv yview]
2549 set y0 [expr {int([lindex $f 0] * $ymax)}]
2550 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
2551 if {$r0 < 0} {
2552 set r0 0
2553 }
2554 set y1 [expr {int([lindex $f 1] * $ymax)}]
2555 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
2556 if {$r1 >= $numcommits} {
2557 set r1 [expr {$numcommits - 1}]
2558 }
2559 return [list $r0 $r1]
2560}
2561
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002562proc layoutmore {tmax allread} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002563 global rowlaidout rowoptim commitidx numcommits optim_delay
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002564 global uparrowlen curview rowidlist idinlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002565
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002566 set showlast 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002567 set showdelay $optim_delay
2568 set optdelay [expr {$uparrowlen + 1}]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002569 while {1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002570 if {$rowoptim - $showdelay > $numcommits} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002571 showstuff [expr {$rowoptim - $showdelay}] $showlast
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002572 } elseif {$rowlaidout - $optdelay > $rowoptim} {
2573 set nr [expr {$rowlaidout - $optdelay - $rowoptim}]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002574 if {$nr > 100} {
2575 set nr 100
2576 }
2577 optimize_rows $rowoptim 0 [expr {$rowoptim + $nr}]
2578 incr rowoptim $nr
2579 } elseif {$commitidx($curview) > $rowlaidout} {
2580 set nr [expr {$commitidx($curview) - $rowlaidout}]
2581 # may need to increase this threshold if uparrowlen or
2582 # mingaplen are increased...
2583 if {$nr > 150} {
2584 set nr 150
2585 }
2586 set row $rowlaidout
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002587 set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002588 if {$rowlaidout == $row} {
2589 return 0
2590 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002591 } elseif {$allread} {
2592 set optdelay 0
2593 set nrows $commitidx($curview)
2594 if {[lindex $rowidlist $nrows] ne {} ||
2595 [array names idinlist] ne {}} {
2596 layouttail
2597 set rowlaidout $commitidx($curview)
2598 } elseif {$rowoptim == $nrows} {
2599 set showdelay 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002600 set showlast 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002601 if {$numcommits == $nrows} {
2602 return 0
2603 }
2604 }
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002605 } else {
2606 return 0
2607 }
2608 if {$tmax ne {} && [clock clicks -milliseconds] >= $tmax} {
2609 return 1
2610 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002611 }
2612}
2613
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002614proc showstuff {canshow last} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002615 global numcommits commitrow pending_select selectedline curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002616 global lookingforhead mainheadid displayorder nullid selectfirst
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002617
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002618 if {$numcommits == 0} {
2619 global phase
2620 set phase "incrdraw"
2621 allcanvs delete all
2622 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002623 set r0 $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002624 set numcommits $canshow
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002625 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002626 set rows [visiblerows]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002627 set r1 [lindex $rows 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002628 if {$r1 >= $canshow} {
2629 set r1 [expr {$canshow - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002630 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002631 if {$r0 <= $r1} {
2632 drawcommits $r0 $r1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002633 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002634 if {[info exists pending_select] &&
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002635 [info exists commitrow($curview,$pending_select)] &&
2636 $commitrow($curview,$pending_select) < $numcommits} {
2637 selectline $commitrow($curview,$pending_select) 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002638 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10002639 if {$selectfirst} {
2640 if {[info exists selectedline] || [info exists pending_select]} {
2641 set selectfirst 0
2642 } else {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002643 set l [expr {[lindex $displayorder 0] eq $nullid}]
2644 selectline $l 1
Paul Mackerrase507fd42007-06-16 21:51:08 +10002645 set selectfirst 0
2646 }
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10002647 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002648 if {$lookingforhead && [info exists commitrow($curview,$mainheadid)]
2649 && ($last || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2650 set lookingforhead 0
2651 dodiffindex
2652 }
2653}
2654
2655proc doshowlocalchanges {} {
2656 global lookingforhead curview mainheadid phase commitrow
2657
2658 if {[info exists commitrow($curview,$mainheadid)] &&
2659 ($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2660 dodiffindex
2661 } elseif {$phase ne {}} {
2662 set lookingforhead 1
2663 }
2664}
2665
2666proc dohidelocalchanges {} {
2667 global lookingforhead localrow lserial
2668
2669 set lookingforhead 0
2670 if {$localrow >= 0} {
2671 removerow $localrow
2672 set localrow -1
2673 }
2674 incr lserial
2675}
2676
2677# spawn off a process to do git diff-index HEAD
2678proc dodiffindex {} {
2679 global localrow lserial
2680
2681 incr lserial
2682 set localrow -1
2683 set fd [open "|git diff-index HEAD" r]
2684 fconfigure $fd -blocking 0
2685 filerun $fd [list readdiffindex $fd $lserial]
2686}
2687
2688proc readdiffindex {fd serial} {
2689 global localrow commitrow mainheadid nullid curview
2690 global commitinfo commitdata lserial
2691
2692 if {[gets $fd line] < 0} {
2693 if {[eof $fd]} {
2694 close $fd
2695 return 0
2696 }
2697 return 1
2698 }
2699 # we only need to see one line and we don't really care what it says...
2700 close $fd
2701
2702 if {$serial == $lserial && $localrow == -1} {
2703 # add the line for the local diff to the graph
2704 set localrow $commitrow($curview,$mainheadid)
2705 set hl "Local uncommitted changes"
2706 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
2707 set commitdata($nullid) "\n $hl\n"
2708 insertrow $localrow $nullid
2709 }
2710 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002711}
2712
2713proc layoutrows {row endrow last} {
2714 global rowidlist rowoffsets displayorder
2715 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002716 global children parentlist
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002717 global idrowranges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002718 global commitidx curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002719 global idinlist rowchk rowrangelist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002720
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002721 set idlist [lindex $rowidlist $row]
2722 set offs [lindex $rowoffsets $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002723 while {$row < $endrow} {
2724 set id [lindex $displayorder $row]
2725 set oldolds {}
2726 set newolds {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002727 foreach p [lindex $parentlist $row] {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002728 if {![info exists idinlist($p)]} {
2729 lappend newolds $p
2730 } elseif {!$idinlist($p)} {
2731 lappend oldolds $p
2732 }
2733 }
2734 set nev [expr {[llength $idlist] + [llength $newolds]
2735 + [llength $oldolds] - $maxwidth + 1}]
2736 if {$nev > 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002737 if {!$last &&
2738 $row + $uparrowlen + $mingaplen >= $commitidx($curview)} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002739 for {set x [llength $idlist]} {[incr x -1] >= 0} {} {
2740 set i [lindex $idlist $x]
2741 if {![info exists rowchk($i)] || $row >= $rowchk($i)} {
2742 set r [usedinrange $i [expr {$row - $downarrowlen}] \
2743 [expr {$row + $uparrowlen + $mingaplen}]]
2744 if {$r == 0} {
2745 set idlist [lreplace $idlist $x $x]
2746 set offs [lreplace $offs $x $x]
2747 set offs [incrange $offs $x 1]
2748 set idinlist($i) 0
Paul Mackerrasd8d2df02006-03-18 20:42:46 +11002749 set rm1 [expr {$row - 1}]
Paul Mackerras66e46f32006-10-14 19:21:02 +10002750 lappend idrowranges($i) [lindex $displayorder $rm1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002751 if {[incr nev -1] <= 0} break
2752 continue
2753 }
2754 set rowchk($id) [expr {$row + $r}]
2755 }
2756 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002757 lset rowidlist $row $idlist
2758 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002759 }
2760 set col [lsearch -exact $idlist $id]
2761 if {$col < 0} {
2762 set col [llength $idlist]
2763 lappend idlist $id
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002764 lset rowidlist $row $idlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002765 set z {}
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002766 if {$children($curview,$id) ne {}} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002767 set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002768 unset idinlist($id)
2769 }
2770 lappend offs $z
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002771 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002772 if {$z ne {}} {
2773 makeuparrow $id $col $row $z
2774 }
2775 } else {
2776 unset idinlist($id)
2777 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002778 set ranges {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002779 if {[info exists idrowranges($id)]} {
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002780 set ranges $idrowranges($id)
Paul Mackerras66e46f32006-10-14 19:21:02 +10002781 lappend ranges $id
Paul Mackerras22626ef2006-04-17 09:56:02 +10002782 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002783 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002784 lappend rowrangelist $ranges
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002785 incr row
2786 set offs [ntimes [llength $idlist] 0]
2787 set l [llength $newolds]
2788 set idlist [eval lreplace \$idlist $col $col $newolds]
2789 set o 0
2790 if {$l != 1} {
2791 set offs [lrange $offs 0 [expr {$col - 1}]]
2792 foreach x $newolds {
2793 lappend offs {}
2794 incr o -1
2795 }
2796 incr o
2797 set tmp [expr {[llength $idlist] - [llength $offs]}]
2798 if {$tmp > 0} {
2799 set offs [concat $offs [ntimes $tmp $o]]
2800 }
2801 } else {
2802 lset offs $col {}
2803 }
2804 foreach i $newolds {
2805 set idinlist($i) 1
Paul Mackerras66e46f32006-10-14 19:21:02 +10002806 set idrowranges($i) $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002807 }
2808 incr col $l
2809 foreach oid $oldolds {
2810 set idinlist($oid) 1
2811 set idlist [linsert $idlist $col $oid]
2812 set offs [linsert $offs $col $o]
2813 makeuparrow $oid $col $row $o
2814 incr col
2815 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002816 lappend rowidlist $idlist
2817 lappend rowoffsets $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002818 }
2819 return $row
2820}
2821
2822proc addextraid {id row} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10002823 global displayorder commitrow commitinfo
Paul Mackerrase7da3472006-04-17 10:27:59 +10002824 global commitidx commitlisted
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002825 global parentlist children curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002826
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002827 incr commitidx($curview)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002828 lappend displayorder $id
Paul Mackerrase7da3472006-04-17 10:27:59 +10002829 lappend commitlisted 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10002830 lappend parentlist {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002831 set commitrow($curview,$id) $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002832 readcommit $id
2833 if {![info exists commitinfo($id)]} {
2834 set commitinfo($id) {"No commit information available"}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002835 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002836 if {![info exists children($curview,$id)]} {
2837 set children($curview,$id) {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002838 }
2839}
2840
2841proc layouttail {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002842 global rowidlist rowoffsets idinlist commitidx curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002843 global idrowranges rowrangelist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002844
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002845 set row $commitidx($curview)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002846 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002847 while {$idlist ne {}} {
2848 set col [expr {[llength $idlist] - 1}]
2849 set id [lindex $idlist $col]
2850 addextraid $id $row
2851 unset idinlist($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002852 lappend idrowranges($id) $row
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002853 lappend rowrangelist $idrowranges($id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002854 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002855 incr row
2856 set offs [ntimes $col 0]
2857 set idlist [lreplace $idlist $col $col]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002858 lappend rowidlist $idlist
2859 lappend rowoffsets $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002860 }
2861
2862 foreach id [array names idinlist] {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002863 unset idinlist($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002864 addextraid $id $row
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002865 lset rowidlist $row [list $id]
2866 lset rowoffsets $row 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002867 makeuparrow $id 0 $row 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002868 lappend idrowranges($id) $row
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002869 lappend rowrangelist $idrowranges($id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002870 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002871 incr row
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002872 lappend rowidlist {}
2873 lappend rowoffsets {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002874 }
2875}
2876
2877proc insert_pad {row col npad} {
2878 global rowidlist rowoffsets
2879
2880 set pad [ntimes $npad {}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002881 lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad]
2882 set tmp [eval linsert [list [lindex $rowoffsets $row]] $col $pad]
2883 lset rowoffsets $row [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002884}
2885
2886proc optimize_rows {row col endrow} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002887 global rowidlist rowoffsets displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002888
2889 for {} {$row < $endrow} {incr row} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002890 set idlist [lindex $rowidlist $row]
2891 set offs [lindex $rowoffsets $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002892 set haspad 0
2893 for {} {$col < [llength $offs]} {incr col} {
2894 if {[lindex $idlist $col] eq {}} {
2895 set haspad 1
2896 continue
2897 }
2898 set z [lindex $offs $col]
2899 if {$z eq {}} continue
2900 set isarrow 0
2901 set x0 [expr {$col + $z}]
2902 set y0 [expr {$row - 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002903 set z0 [lindex $rowoffsets $y0 $x0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002904 if {$z0 eq {}} {
2905 set id [lindex $idlist $col]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002906 set ranges [rowranges $id]
2907 if {$ranges ne {} && $y0 > [lindex $ranges 0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002908 set isarrow 1
2909 }
2910 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10002911 # Looking at lines from this row to the previous row,
2912 # make them go straight up if they end in an arrow on
2913 # the previous row; otherwise make them go straight up
2914 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002915 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10002916 # Line currently goes left too much;
2917 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002918 set npad [expr {-1 - $z + $isarrow}]
2919 set offs [incrange $offs $col $npad]
2920 insert_pad $y0 $x0 $npad
2921 if {$y0 > 0} {
2922 optimize_rows $y0 $x0 $row
2923 }
2924 set z [lindex $offs $col]
2925 set x0 [expr {$col + $z}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002926 set z0 [lindex $rowoffsets $y0 $x0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002927 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10002928 # Line currently goes right too much;
2929 # insert pads in this line and adjust the next's rowoffsets
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002930 set npad [expr {$z - 1 + $isarrow}]
2931 set y1 [expr {$row + 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002932 set offs2 [lindex $rowoffsets $y1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002933 set x1 -1
2934 foreach z $offs2 {
2935 incr x1
2936 if {$z eq {} || $x1 + $z < $col} continue
2937 if {$x1 + $z > $col} {
2938 incr npad
2939 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002940 lset rowoffsets $y1 [incrange $offs2 $x1 $npad]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002941 break
2942 }
2943 set pad [ntimes $npad {}]
2944 set idlist [eval linsert \$idlist $col $pad]
2945 set tmp [eval linsert \$offs $col $pad]
2946 incr col $npad
2947 set offs [incrange $tmp $col [expr {-$npad}]]
2948 set z [lindex $offs $col]
2949 set haspad 1
2950 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11002951 if {$z0 eq {} && !$isarrow} {
2952 # this line links to its first child on row $row-2
2953 set rm2 [expr {$row - 2}]
2954 set id [lindex $displayorder $rm2]
2955 set xc [lsearch -exact [lindex $rowidlist $rm2] $id]
2956 if {$xc >= 0} {
2957 set z0 [expr {$xc - $x0}]
2958 }
2959 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10002960 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002961 if {$z0 ne {} && $z < 0 && $z0 > 0} {
2962 insert_pad $y0 $x0 1
2963 set offs [incrange $offs $col 1]
2964 optimize_rows $y0 [expr {$x0 + 1}] $row
2965 }
2966 }
2967 if {!$haspad} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11002968 set o {}
Paul Mackerras3fc42792006-09-15 09:45:23 +10002969 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002970 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
2971 set o [lindex $offs $col]
Paul Mackerraseb447a12006-03-18 23:11:37 +11002972 if {$o eq {}} {
2973 # check if this is the link to the first child
2974 set id [lindex $idlist $col]
Paul Mackerras22626ef2006-04-17 09:56:02 +10002975 set ranges [rowranges $id]
2976 if {$ranges ne {} && $row == [lindex $ranges 0]} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11002977 # it is, work out offset to child
2978 set y0 [expr {$row - 1}]
2979 set id [lindex $displayorder $y0]
2980 set x0 [lsearch -exact [lindex $rowidlist $y0] $id]
2981 if {$x0 >= 0} {
2982 set o [expr {$x0 - $col}]
2983 }
2984 }
2985 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002986 if {$o eq {} || $o <= 0} break
2987 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10002988 # Insert a pad at that column as long as it has a line and
2989 # isn't the last column, and adjust the next row' offsets
Paul Mackerraseb447a12006-03-18 23:11:37 +11002990 if {$o ne {} && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002991 set y1 [expr {$row + 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002992 set offs2 [lindex $rowoffsets $y1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002993 set x1 -1
2994 foreach z $offs2 {
2995 incr x1
2996 if {$z eq {} || $x1 + $z < $col} continue
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002997 lset rowoffsets $y1 [incrange $offs2 $x1 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002998 break
2999 }
3000 set idlist [linsert $idlist $col {}]
3001 set tmp [linsert $offs $col {}]
3002 incr col
3003 set offs [incrange $tmp $col -1]
3004 }
3005 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003006 lset rowidlist $row $idlist
3007 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003008 set col 0
3009 }
3010}
3011
3012proc xc {row col} {
3013 global canvx0 linespc
3014 return [expr {$canvx0 + $col * $linespc}]
3015}
3016
3017proc yc {row} {
3018 global canvy0 linespc
3019 return [expr {$canvy0 + $row * $linespc}]
3020}
3021
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003022proc linewidth {id} {
3023 global thickerline lthickness
3024
3025 set wid $lthickness
3026 if {[info exists thickerline] && $id eq $thickerline} {
3027 set wid [expr {2 * $lthickness}]
3028 }
3029 return $wid
3030}
3031
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003032proc rowranges {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003033 global phase idrowranges commitrow rowlaidout rowrangelist curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003034
3035 set ranges {}
Paul Mackerras22626ef2006-04-17 09:56:02 +10003036 if {$phase eq {} ||
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003037 ([info exists commitrow($curview,$id)]
3038 && $commitrow($curview,$id) < $rowlaidout)} {
3039 set ranges [lindex $rowrangelist $commitrow($curview,$id)]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003040 } elseif {[info exists idrowranges($id)]} {
3041 set ranges $idrowranges($id)
3042 }
Paul Mackerras66e46f32006-10-14 19:21:02 +10003043 set linenos {}
3044 foreach rid $ranges {
3045 lappend linenos $commitrow($curview,$rid)
3046 }
3047 if {$linenos ne {}} {
3048 lset linenos 0 [expr {[lindex $linenos 0] + 1}]
3049 }
3050 return $linenos
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003051}
3052
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003053# work around tk8.4 refusal to draw arrows on diagonal segments
3054proc adjarrowhigh {coords} {
3055 global linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003056
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003057 set x0 [lindex $coords 0]
3058 set x1 [lindex $coords 2]
3059 if {$x0 != $x1} {
3060 set y0 [lindex $coords 1]
3061 set y1 [lindex $coords 3]
3062 if {$y0 - $y1 <= 2 * $linespc && $x1 == [lindex $coords 4]} {
3063 # we have a nearby vertical segment, just trim off the diag bit
3064 set coords [lrange $coords 2 end]
3065 } else {
3066 set slope [expr {($x0 - $x1) / ($y0 - $y1)}]
3067 set xi [expr {$x0 - $slope * $linespc / 2}]
3068 set yi [expr {$y0 - $linespc / 2}]
3069 set coords [lreplace $coords 0 1 $xi $y0 $xi $yi]
Paul Mackerraseb447a12006-03-18 23:11:37 +11003070 }
3071 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003072 return $coords
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003073}
3074
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003075proc drawlineseg {id row endrow arrowlow} {
3076 global rowidlist displayorder iddrawn linesegs
3077 global canv colormap linespc curview maxlinelen
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003078
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003079 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
3080 set le [expr {$row + 1}]
3081 set arrowhigh 1
3082 while {1} {
3083 set c [lsearch -exact [lindex $rowidlist $le] $id]
3084 if {$c < 0} {
3085 incr le -1
3086 break
3087 }
3088 lappend cols $c
3089 set x [lindex $displayorder $le]
3090 if {$x eq $id} {
3091 set arrowhigh 0
3092 break
3093 }
3094 if {[info exists iddrawn($x)] || $le == $endrow} {
3095 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
3096 if {$c >= 0} {
3097 lappend cols $c
3098 set arrowhigh 0
3099 }
3100 break
3101 }
3102 incr le
3103 }
3104 if {$le <= $row} {
3105 return $row
3106 }
3107
3108 set lines {}
3109 set i 0
3110 set joinhigh 0
3111 if {[info exists linesegs($id)]} {
3112 set lines $linesegs($id)
3113 foreach li $lines {
3114 set r0 [lindex $li 0]
3115 if {$r0 > $row} {
3116 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
3117 set joinhigh 1
3118 }
3119 break
3120 }
3121 incr i
3122 }
3123 }
3124 set joinlow 0
3125 if {$i > 0} {
3126 set li [lindex $lines [expr {$i-1}]]
3127 set r1 [lindex $li 1]
3128 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
3129 set joinlow 1
3130 }
3131 }
3132
3133 set x [lindex $cols [expr {$le - $row}]]
3134 set xp [lindex $cols [expr {$le - 1 - $row}]]
3135 set dir [expr {$xp - $x}]
3136 if {$joinhigh} {
3137 set ith [lindex $lines $i 2]
3138 set coords [$canv coords $ith]
3139 set ah [$canv itemcget $ith -arrow]
3140 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
3141 set x2 [lindex $cols [expr {$le + 1 - $row}]]
3142 if {$x2 ne {} && $x - $x2 == $dir} {
3143 set coords [lrange $coords 0 end-2]
3144 }
3145 } else {
3146 set coords [list [xc $le $x] [yc $le]]
3147 }
3148 if {$joinlow} {
3149 set itl [lindex $lines [expr {$i-1}] 2]
3150 set al [$canv itemcget $itl -arrow]
3151 set arrowlow [expr {$al eq "last" || $al eq "both"}]
3152 } elseif {$arrowlow &&
3153 [lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0} {
3154 set arrowlow 0
3155 }
3156 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
3157 for {set y $le} {[incr y -1] > $row} {} {
3158 set x $xp
3159 set xp [lindex $cols [expr {$y - 1 - $row}]]
3160 set ndir [expr {$xp - $x}]
3161 if {$dir != $ndir || $xp < 0} {
3162 lappend coords [xc $y $x] [yc $y]
3163 }
3164 set dir $ndir
3165 }
3166 if {!$joinlow} {
3167 if {$xp < 0} {
3168 # join parent line to first child
3169 set ch [lindex $displayorder $row]
3170 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
3171 if {$xc < 0} {
3172 puts "oops: drawlineseg: child $ch not on row $row"
3173 } else {
3174 if {$xc < $x - 1} {
3175 lappend coords [xc $row [expr {$x-1}]] [yc $row]
3176 } elseif {$xc > $x + 1} {
3177 lappend coords [xc $row [expr {$x+1}]] [yc $row]
3178 }
3179 set x $xc
3180 }
3181 lappend coords [xc $row $x] [yc $row]
3182 } else {
3183 set xn [xc $row $xp]
3184 set yn [yc $row]
3185 # work around tk8.4 refusal to draw arrows on diagonal segments
3186 if {$arrowlow && $xn != [lindex $coords end-1]} {
3187 if {[llength $coords] < 4 ||
3188 [lindex $coords end-3] != [lindex $coords end-1] ||
3189 [lindex $coords end] - $yn > 2 * $linespc} {
3190 set xn [xc $row [expr {$xp - 0.5 * $dir}]]
3191 set yo [yc [expr {$row + 0.5}]]
3192 lappend coords $xn $yo $xn $yn
3193 }
3194 } else {
3195 lappend coords $xn $yn
3196 }
3197 }
3198 if {!$joinhigh} {
3199 if {$arrowhigh} {
3200 set coords [adjarrowhigh $coords]
3201 }
3202 assigncolor $id
3203 set t [$canv create line $coords -width [linewidth $id] \
3204 -fill $colormap($id) -tags lines.$id -arrow $arrow]
3205 $canv lower $t
3206 bindline $t $id
3207 set lines [linsert $lines $i [list $row $le $t]]
3208 } else {
3209 $canv coords $ith $coords
3210 if {$arrow ne $ah} {
3211 $canv itemconf $ith -arrow $arrow
3212 }
3213 lset lines $i 0 $row
3214 }
3215 } else {
3216 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
3217 set ndir [expr {$xo - $xp}]
3218 set clow [$canv coords $itl]
3219 if {$dir == $ndir} {
3220 set clow [lrange $clow 2 end]
3221 }
3222 set coords [concat $coords $clow]
3223 if {!$joinhigh} {
3224 lset lines [expr {$i-1}] 1 $le
3225 if {$arrowhigh} {
3226 set coords [adjarrowhigh $coords]
3227 }
3228 } else {
3229 # coalesce two pieces
3230 $canv delete $ith
3231 set b [lindex $lines [expr {$i-1}] 0]
3232 set e [lindex $lines $i 1]
3233 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
3234 }
3235 $canv coords $itl $coords
3236 if {$arrow ne $al} {
3237 $canv itemconf $itl -arrow $arrow
3238 }
3239 }
3240
3241 set linesegs($id) $lines
3242 return $le
3243}
3244
3245proc drawparentlinks {id row} {
3246 global rowidlist canv colormap curview parentlist
3247 global idpos
3248
3249 set rowids [lindex $rowidlist $row]
3250 set col [lsearch -exact $rowids $id]
3251 if {$col < 0} return
3252 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003253 set row2 [expr {$row + 1}]
3254 set x [xc $row $col]
3255 set y [yc $row]
3256 set y2 [yc $row2]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003257 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003258 # rmx = right-most X coord used
3259 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003260 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11003261 set i [lsearch -exact $ids $p]
3262 if {$i < 0} {
3263 puts "oops, parent $p of $id not in list"
3264 continue
3265 }
3266 set x2 [xc $row2 $i]
3267 if {$x2 > $rmx} {
3268 set rmx $x2
3269 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003270 if {[lsearch -exact $rowids $p] < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003271 # drawlineseg will do this one for us
3272 continue
3273 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003274 assigncolor $p
3275 # should handle duplicated parents here...
3276 set coords [list $x $y]
3277 if {$i < $col - 1} {
3278 lappend coords [xc $row [expr {$i + 1}]] $y
3279 } elseif {$i > $col + 1} {
3280 lappend coords [xc $row [expr {$i - 1}]] $y
3281 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003282 lappend coords $x2 $y2
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003283 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003284 -fill $colormap($p) -tags lines.$p]
3285 $canv lower $t
3286 bindline $t $p
3287 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003288 if {$rmx > [lindex $idpos($id) 1]} {
3289 lset idpos($id) 1 $rmx
3290 redrawtags $id
3291 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003292}
3293
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003294proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003295 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003296
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003297 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003298}
3299
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003300proc drawcmittext {id row col} {
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003301 global linespc canv canv2 canv3 canvy0 fgcolor
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003302 global commitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003303 global rowtextx idpos idtags idheads idotherrefs
3304 global linehtag linentag linedtag
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003305 global mainfont canvxmax boldrows boldnamerows fgcolor nullid
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003306
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003307 if {$id eq $nullid} {
3308 set ofill red
3309 } else {
3310 set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}]
3311 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003312 set x [xc $row $col]
3313 set y [yc $row]
3314 set orad [expr {$linespc / 3}]
3315 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
3316 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003317 -fill $ofill -outline $fgcolor -width 1 -tags circle]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003318 $canv raise $t
3319 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003320 set rmx [llength [lindex $rowidlist $row]]
3321 set olds [lindex $parentlist $row]
3322 if {$olds ne {}} {
3323 set nextids [lindex $rowidlist [expr {$row + 1}]]
3324 foreach p $olds {
3325 set i [lsearch -exact $nextids $p]
3326 if {$i > $rmx} {
3327 set rmx $i
3328 }
3329 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003330 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003331 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003332 set rowtextx($row) $xt
3333 set idpos($id) [list $x $xt $y]
3334 if {[info exists idtags($id)] || [info exists idheads($id)]
3335 || [info exists idotherrefs($id)]} {
3336 set xt [drawtags $id $x $xt $y]
3337 }
3338 set headline [lindex $commitinfo($id) 0]
3339 set name [lindex $commitinfo($id) 1]
3340 set date [lindex $commitinfo($id) 2]
3341 set date [formatdate $date]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003342 set font $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10003343 set nfont $mainfont
3344 set isbold [ishighlighted $row]
3345 if {$isbold > 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003346 lappend boldrows $row
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003347 lappend font bold
Paul Mackerras908c3582006-05-20 09:38:11 +10003348 if {$isbold > 1} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003349 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003350 lappend nfont bold
3351 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003352 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003353 set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
3354 -text $headline -font $font -tags text]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003355 $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003356 set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
3357 -text $name -font $nfont -tags text]
3358 set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
3359 -text $date -font $mainfont -tags text]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11003360 set xr [expr {$xt + [font measure $mainfont $headline]}]
3361 if {$xr > $canvxmax} {
3362 set canvxmax $xr
3363 setcanvscroll
3364 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003365}
3366
3367proc drawcmitrow {row} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003368 global displayorder rowidlist
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003369 global iddrawn
Paul Mackerrase7da3472006-04-17 10:27:59 +10003370 global commitinfo parentlist numcommits
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003371 global filehighlight fhighlights findstring nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10003372 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10003373 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003374
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003375 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003376
3377 set id [lindex $displayorder $row]
Paul Mackerras908c3582006-05-20 09:38:11 +10003378 if {[info exists hlview] && ![info exists vhighlights($row)]} {
3379 askvhighlight $row $id
3380 }
3381 if {[info exists filehighlight] && ![info exists fhighlights($row)]} {
3382 askfilehighlight $row $id
3383 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003384 if {$findstring ne {} && ![info exists nhighlights($row)]} {
3385 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10003386 }
Paul Mackerras164ff272006-05-29 19:50:02 +10003387 if {$highlight_related ne "None" && ![info exists rhighlights($row)]} {
3388 askrelhighlight $row $id
3389 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003390 if {[info exists iddrawn($id)]} return
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003391 set col [lsearch -exact [lindex $rowidlist $row] $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003392 if {$col < 0} {
3393 puts "oops, row $row id $id not in list"
3394 return
3395 }
3396 if {![info exists commitinfo($id)]} {
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11003397 getcommit $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003398 }
3399 assigncolor $id
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003400 drawcmittext $id $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003401 set iddrawn($id) 1
3402}
3403
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003404proc drawcommits {row {endrow {}}} {
3405 global numcommits iddrawn displayorder curview
3406 global parentlist rowidlist
3407
3408 if {$row < 0} {
3409 set row 0
3410 }
3411 if {$endrow eq {}} {
3412 set endrow $row
3413 }
3414 if {$endrow >= $numcommits} {
3415 set endrow [expr {$numcommits - 1}]
3416 }
3417
3418 # make the lines join to already-drawn rows either side
3419 set r [expr {$row - 1}]
3420 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
3421 set r $row
3422 }
3423 set er [expr {$endrow + 1}]
3424 if {$er >= $numcommits ||
3425 ![info exists iddrawn([lindex $displayorder $er])]} {
3426 set er $endrow
3427 }
3428 for {} {$r <= $er} {incr r} {
3429 set id [lindex $displayorder $r]
3430 set wasdrawn [info exists iddrawn($id)]
3431 if {!$wasdrawn} {
3432 drawcmitrow $r
3433 }
3434 if {$r == $er} break
3435 set nextid [lindex $displayorder [expr {$r + 1}]]
3436 if {$wasdrawn && [info exists iddrawn($nextid)]} {
3437 catch {unset prevlines}
3438 continue
3439 }
3440 drawparentlinks $id $r
3441
3442 if {[info exists lineends($r)]} {
3443 foreach lid $lineends($r) {
3444 unset prevlines($lid)
3445 }
3446 }
3447 set rowids [lindex $rowidlist $r]
3448 foreach lid $rowids {
3449 if {$lid eq {}} continue
3450 if {$lid eq $id} {
3451 # see if this is the first child of any of its parents
3452 foreach p [lindex $parentlist $r] {
3453 if {[lsearch -exact $rowids $p] < 0} {
3454 # make this line extend up to the child
3455 set le [drawlineseg $p $r $er 0]
3456 lappend lineends($le) $p
3457 set prevlines($p) 1
3458 }
3459 }
3460 } elseif {![info exists prevlines($lid)]} {
3461 set le [drawlineseg $lid $r $er 1]
3462 lappend lineends($le) $lid
3463 set prevlines($lid) 1
3464 }
3465 }
3466 }
3467}
3468
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003469proc drawfrac {f0 f1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003470 global canv linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003471
3472 set ymax [lindex [$canv cget -scrollregion] 3]
3473 if {$ymax eq {} || $ymax == 0} return
3474 set y0 [expr {int($f0 * $ymax)}]
3475 set row [expr {int(($y0 - 3) / $linespc) - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003476 set y1 [expr {int($f1 * $ymax)}]
3477 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003478 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003479}
3480
3481proc drawvisible {} {
3482 global canv
3483 eval drawfrac [$canv yview]
3484}
3485
3486proc clear_display {} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003487 global iddrawn linesegs
Paul Mackerras164ff272006-05-29 19:50:02 +10003488 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003489
3490 allcanvs delete all
3491 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003492 catch {unset linesegs}
Paul Mackerras908c3582006-05-20 09:38:11 +10003493 catch {unset vhighlights}
3494 catch {unset fhighlights}
3495 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10003496 catch {unset rhighlights}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003497}
3498
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003499proc findcrossings {id} {
3500 global rowidlist parentlist numcommits rowoffsets displayorder
3501
3502 set cross {}
3503 set ccross {}
3504 foreach {s e} [rowranges $id] {
3505 if {$e >= $numcommits} {
3506 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003507 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10003508 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003509 set x [lsearch -exact [lindex $rowidlist $e] $id]
3510 if {$x < 0} {
3511 puts "findcrossings: oops, no [shortids $id] in row $e"
3512 continue
3513 }
3514 for {set row $e} {[incr row -1] >= $s} {} {
3515 set olds [lindex $parentlist $row]
3516 set kid [lindex $displayorder $row]
3517 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
3518 if {$kidx < 0} continue
3519 set nextrow [lindex $rowidlist [expr {$row + 1}]]
3520 foreach p $olds {
3521 set px [lsearch -exact $nextrow $p]
3522 if {$px < 0} continue
3523 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
3524 if {[lsearch -exact $ccross $p] >= 0} continue
3525 if {$x == $px + ($kidx < $px? -1: 1)} {
3526 lappend ccross $p
3527 } elseif {[lsearch -exact $cross $p] < 0} {
3528 lappend cross $p
3529 }
3530 }
3531 }
3532 set inc [lindex $rowoffsets $row $x]
3533 if {$inc eq {}} break
3534 incr x $inc
3535 }
3536 }
3537 return [concat $ccross {{}} $cross]
3538}
3539
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003540proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11003541 global colormap colors nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003542 global commitrow parentlist children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003543
Paul Mackerras418c4c72006-02-07 09:10:18 +11003544 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003545 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003546 if {[info exists children($curview,$id)]} {
3547 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10003548 } else {
3549 set kids {}
3550 }
3551 if {[llength $kids] == 1} {
3552 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003553 if {[info exists colormap($child)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003554 && [llength [lindex $parentlist $commitrow($curview,$child)]] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003555 set colormap($id) $colormap($child)
3556 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003557 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003558 }
3559 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003560 set origbad {}
3561 foreach x [findcrossings $id] {
3562 if {$x eq {}} {
3563 # delimiter between corner crossings and other crossings
3564 if {[llength $badcolors] >= $ncolors - 1} break
3565 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003566 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003567 if {[info exists colormap($x)]
3568 && [lsearch -exact $badcolors $colormap($x)] < 0} {
3569 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003570 }
3571 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003572 if {[llength $badcolors] >= $ncolors} {
3573 set badcolors $origbad
3574 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003575 set origbad $badcolors
3576 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003577 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003578 if {[info exists colormap($child)]
3579 && [lsearch -exact $badcolors $colormap($child)] < 0} {
3580 lappend badcolors $colormap($child)
3581 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003582 foreach p [lindex $parentlist $commitrow($curview,$child)] {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003583 if {[info exists colormap($p)]
3584 && [lsearch -exact $badcolors $colormap($p)] < 0} {
3585 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003586 }
3587 }
3588 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003589 if {[llength $badcolors] >= $ncolors} {
3590 set badcolors $origbad
3591 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003592 }
3593 for {set i 0} {$i <= $ncolors} {incr i} {
3594 set c [lindex $colors $nextcolor]
3595 if {[incr nextcolor] >= $ncolors} {
3596 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003597 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003598 if {[lsearch -exact $badcolors $c]} break
3599 }
3600 set colormap($id) $c
3601}
3602
Paul Mackerrasa823a912005-06-21 10:01:38 +10003603proc bindline {t id} {
3604 global canv
3605
Paul Mackerrasa823a912005-06-21 10:01:38 +10003606 $canv bind $t <Enter> "lineenter %x %y $id"
3607 $canv bind $t <Motion> "linemotion %x %y $id"
3608 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10003609 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10003610}
3611
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003612proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10003613 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003614 global linespc lthickness
Paul Mackerras8a485712006-07-06 10:21:23 +10003615 global canv mainfont commitrow rowtextx curview fgcolor bgcolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003616
3617 set marks {}
3618 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003619 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003620 if {[info exists idtags($id)]} {
3621 set marks $idtags($id)
3622 set ntags [llength $marks]
3623 }
3624 if {[info exists idheads($id)]} {
3625 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003626 set nheads [llength $idheads($id)]
3627 }
3628 if {[info exists idotherrefs($id)]} {
3629 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003630 }
3631 if {$marks eq {}} {
3632 return $xt
3633 }
3634
3635 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003636 set yt [expr {$y1 - 0.5 * $linespc}]
3637 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003638 set xvals {}
3639 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10003640 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003641 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10003642 incr i
3643 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
3644 set wid [font measure [concat $mainfont bold] $tag]
3645 } else {
3646 set wid [font measure $mainfont $tag]
3647 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003648 lappend xvals $xt
3649 lappend wvals $wid
3650 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
3651 }
3652 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
3653 -width $lthickness -fill black -tags tag.$id]
3654 $canv lower $t
3655 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003656 set xl [expr {$x + $delta}]
3657 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras8a485712006-07-06 10:21:23 +10003658 set font $mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003659 if {[incr ntags -1] >= 0} {
3660 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003661 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
3662 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10003663 -width 1 -outline black -fill yellow -tags tag.$id]
3664 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003665 set rowtextx($commitrow($curview,$id)) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003666 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003667 # draw a head or other ref
3668 if {[incr nheads -1] >= 0} {
3669 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10003670 if {$tag eq $mainhead} {
3671 lappend font bold
3672 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003673 } else {
3674 set col "#ddddff"
3675 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003676 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003677 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003678 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02003679 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
3680 set rwid [font measure $mainfont $remoteprefix]
3681 set xi [expr {$x + 1}]
3682 set yti [expr {$yt + 1}]
3683 set xri [expr {$x + $rwid}]
3684 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
3685 -width 0 -fill "#ffddaa" -tags tag.$id
3686 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003687 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003688 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10003689 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10003690 if {$ntags >= 0} {
3691 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10003692 } elseif {$nheads >= 0} {
3693 $canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10003694 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003695 }
3696 return $xt
3697}
3698
Paul Mackerras8d858d12005-08-05 09:52:16 +10003699proc xcoord {i level ln} {
3700 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003701
Paul Mackerras8d858d12005-08-05 09:52:16 +10003702 set x [expr {$canvx0 + $i * $xspc1($ln)}]
3703 if {$i > 0 && $i == $level} {
3704 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
3705 } elseif {$i > $level} {
3706 set x [expr {$x + $xspc2 - $xspc1($ln)}]
3707 }
3708 return $x
3709}
3710
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003711proc show_status {msg} {
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003712 global canv mainfont fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003713
3714 clear_display
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003715 $canv create text 3 3 -anchor nw -text $msg -font $mainfont \
3716 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003717}
3718
Paul Mackerras561d0382006-08-28 22:41:09 +10003719# Insert a new commit as the child of the commit on row $row.
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003720# The new commit will be displayed on row $row and the commits
3721# on that row and below will move down one row.
3722proc insertrow {row newcmit} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003723 global displayorder parentlist commitlisted children
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003724 global commitrow curview rowidlist rowoffsets numcommits
Paul Mackerras66e46f32006-10-14 19:21:02 +10003725 global rowrangelist rowlaidout rowoptim numcommits
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003726 global selectedline rowchk commitidx
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003727
3728 if {$row >= $numcommits} {
3729 puts "oops, inserting new row $row but only have $numcommits rows"
3730 return
3731 }
3732 set p [lindex $displayorder $row]
3733 set displayorder [linsert $displayorder $row $newcmit]
3734 set parentlist [linsert $parentlist $row $p]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003735 set kids $children($curview,$p)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003736 lappend kids $newcmit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003737 set children($curview,$p) $kids
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003738 set children($curview,$newcmit) {}
Paul Mackerras561d0382006-08-28 22:41:09 +10003739 set commitlisted [linsert $commitlisted $row 1]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003740 set l [llength $displayorder]
3741 for {set r $row} {$r < $l} {incr r} {
3742 set id [lindex $displayorder $r]
3743 set commitrow($curview,$id) $r
3744 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003745 incr commitidx($curview)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003746
3747 set idlist [lindex $rowidlist $row]
3748 set offs [lindex $rowoffsets $row]
3749 set newoffs {}
3750 foreach x $idlist {
3751 if {$x eq {} || ($x eq $p && [llength $kids] == 1)} {
3752 lappend newoffs {}
3753 } else {
3754 lappend newoffs 0
3755 }
3756 }
3757 if {[llength $kids] == 1} {
3758 set col [lsearch -exact $idlist $p]
3759 lset idlist $col $newcmit
3760 } else {
3761 set col [llength $idlist]
3762 lappend idlist $newcmit
3763 lappend offs {}
3764 lset rowoffsets $row $offs
3765 }
3766 set rowidlist [linsert $rowidlist $row $idlist]
3767 set rowoffsets [linsert $rowoffsets [expr {$row+1}] $newoffs]
3768
3769 set rowrangelist [linsert $rowrangelist $row {}]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003770 if {[llength $kids] > 1} {
3771 set rp1 [expr {$row + 1}]
3772 set ranges [lindex $rowrangelist $rp1]
3773 if {$ranges eq {}} {
Paul Mackerras66e46f32006-10-14 19:21:02 +10003774 set ranges [list $newcmit $p]
3775 } elseif {[lindex $ranges end-1] eq $p} {
3776 lset ranges end-1 $newcmit
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003777 }
3778 lset rowrangelist $rp1 $ranges
3779 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003780
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003781 catch {unset rowchk}
3782
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003783 incr rowlaidout
3784 incr rowoptim
3785 incr numcommits
3786
Paul Mackerras561d0382006-08-28 22:41:09 +10003787 if {[info exists selectedline] && $selectedline >= $row} {
3788 incr selectedline
3789 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003790 redisplay
3791}
3792
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003793# Remove a commit that was inserted with insertrow on row $row.
3794proc removerow {row} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003795 global displayorder parentlist commitlisted children
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003796 global commitrow curview rowidlist rowoffsets numcommits
3797 global rowrangelist idrowranges rowlaidout rowoptim numcommits
3798 global linesegends selectedline rowchk commitidx
3799
3800 if {$row >= $numcommits} {
3801 puts "oops, removing row $row but only have $numcommits rows"
3802 return
3803 }
3804 set rp1 [expr {$row + 1}]
3805 set id [lindex $displayorder $row]
3806 set p [lindex $parentlist $row]
3807 set displayorder [lreplace $displayorder $row $row]
3808 set parentlist [lreplace $parentlist $row $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003809 set commitlisted [lreplace $commitlisted $row $row]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003810 set kids $children($curview,$p)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003811 set i [lsearch -exact $kids $id]
3812 if {$i >= 0} {
3813 set kids [lreplace $kids $i $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003814 set children($curview,$p) $kids
3815 }
3816 set l [llength $displayorder]
3817 for {set r $row} {$r < $l} {incr r} {
3818 set id [lindex $displayorder $r]
3819 set commitrow($curview,$id) $r
3820 }
3821 incr commitidx($curview) -1
3822
3823 set rowidlist [lreplace $rowidlist $row $row]
3824 set rowoffsets [lreplace $rowoffsets $rp1 $rp1]
3825 if {$kids ne {}} {
3826 set offs [lindex $rowoffsets $row]
3827 set offs [lreplace $offs end end]
3828 lset rowoffsets $row $offs
3829 }
3830
3831 set rowrangelist [lreplace $rowrangelist $row $row]
3832 if {[llength $kids] > 0} {
3833 set ranges [lindex $rowrangelist $row]
3834 if {[lindex $ranges end-1] eq $id} {
3835 set ranges [lreplace $ranges end-1 end]
3836 lset rowrangelist $row $ranges
3837 }
3838 }
3839
3840 catch {unset rowchk}
3841
3842 incr rowlaidout -1
3843 incr rowoptim -1
3844 incr numcommits -1
3845
3846 if {[info exists selectedline] && $selectedline > $row} {
3847 incr selectedline -1
3848 }
3849 redisplay
3850}
3851
Paul Mackerras94a2eed2005-08-07 15:27:57 +10003852# Don't change the text pane cursor if it is currently the hand cursor,
3853# showing that we are over a sha1 ID link.
3854proc settextcursor {c} {
3855 global ctext curtextcursor
3856
3857 if {[$ctext cget -cursor] == $curtextcursor} {
3858 $ctext config -cursor $c
3859 }
3860 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003861}
3862
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003863proc nowbusy {what} {
3864 global isbusy
3865
3866 if {[array names isbusy] eq {}} {
3867 . config -cursor watch
3868 settextcursor watch
3869 }
3870 set isbusy($what) 1
3871}
3872
3873proc notbusy {what} {
3874 global isbusy maincursor textcursor
3875
3876 catch {unset isbusy($what)}
3877 if {[array names isbusy] eq {}} {
3878 . config -cursor $maincursor
3879 settextcursor $textcursor
3880 }
3881}
3882
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003883proc findmatches {f} {
3884 global findtype foundstring foundstrlen
3885 if {$findtype == "Regexp"} {
3886 set matches [regexp -indices -all -inline $foundstring $f]
3887 } else {
3888 if {$findtype == "IgnCase"} {
3889 set str [string tolower $f]
3890 } else {
3891 set str $f
3892 }
3893 set matches {}
3894 set i 0
3895 while {[set j [string first $foundstring $str $i]] >= 0} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003896 lappend matches [list $j [expr {$j+$foundstrlen-1}]]
3897 set i [expr {$j + $foundstrlen}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003898 }
3899 }
3900 return $matches
3901}
3902
Paul Mackerras98f350e2005-05-15 05:56:51 +00003903proc dofind {} {
3904 global findtype findloc findstring markedmatches commitinfo
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003905 global numcommits displayorder linehtag linentag linedtag
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003906 global mainfont canv canv2 canv3 selectedline
Paul Mackerras8ed16482006-03-02 22:56:44 +11003907 global matchinglines foundstring foundstrlen matchstring
3908 global commitdata
Paul Mackerrasb74fd572005-07-16 07:46:13 -04003909
3910 stopfindproc
Paul Mackerras98f350e2005-05-15 05:56:51 +00003911 unmarkmatches
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003912 cancel_next_highlight
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003913 focus .
Paul Mackerras98f350e2005-05-15 05:56:51 +00003914 set matchinglines {}
Paul Mackerras98f350e2005-05-15 05:56:51 +00003915 if {$findtype == "IgnCase"} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003916 set foundstring [string tolower $findstring]
Paul Mackerras98f350e2005-05-15 05:56:51 +00003917 } else {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003918 set foundstring $findstring
Paul Mackerras98f350e2005-05-15 05:56:51 +00003919 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003920 set foundstrlen [string length $findstring]
3921 if {$foundstrlen == 0} return
Paul Mackerras8ed16482006-03-02 22:56:44 +11003922 regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
3923 set matchstring "*$matchstring*"
Paul Mackerras98f350e2005-05-15 05:56:51 +00003924 if {![info exists selectedline]} {
3925 set oldsel -1
3926 } else {
3927 set oldsel $selectedline
3928 }
3929 set didsel 0
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003930 set fldtypes {Headline Author Date Committer CDate Comments}
Paul Mackerras8ed16482006-03-02 22:56:44 +11003931 set l -1
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11003932 foreach id $displayorder {
3933 set d $commitdata($id)
Paul Mackerras8ed16482006-03-02 22:56:44 +11003934 incr l
3935 if {$findtype == "Regexp"} {
3936 set doesmatch [regexp $foundstring $d]
3937 } elseif {$findtype == "IgnCase"} {
3938 set doesmatch [string match -nocase $matchstring $d]
3939 } else {
3940 set doesmatch [string match $matchstring $d]
3941 }
3942 if {!$doesmatch} continue
Paul Mackerras8ed16482006-03-02 22:56:44 +11003943 if {![info exists commitinfo($id)]} {
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11003944 getcommit $id
Paul Mackerras8ed16482006-03-02 22:56:44 +11003945 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00003946 set info $commitinfo($id)
3947 set doesmatch 0
3948 foreach f $info ty $fldtypes {
3949 if {$findloc != "All fields" && $findloc != $ty} {
3950 continue
3951 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003952 set matches [findmatches $f]
Paul Mackerras98f350e2005-05-15 05:56:51 +00003953 if {$matches == {}} continue
3954 set doesmatch 1
3955 if {$ty == "Headline"} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003956 drawcommits $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00003957 markmatches $canv $l $f $linehtag($l) $matches $mainfont
3958 } elseif {$ty == "Author"} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003959 drawcommits $l
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003960 markmatches $canv2 $l $f $linentag($l) $matches $mainfont
Paul Mackerras98f350e2005-05-15 05:56:51 +00003961 } elseif {$ty == "Date"} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003962 drawcommits $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00003963 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
3964 }
3965 }
3966 if {$doesmatch} {
3967 lappend matchinglines $l
3968 if {!$didsel && $l > $oldsel} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003969 findselectline $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00003970 set didsel 1
3971 }
3972 }
3973 }
3974 if {$matchinglines == {}} {
3975 bell
3976 } elseif {!$didsel} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003977 findselectline [lindex $matchinglines 0]
3978 }
3979}
3980
3981proc findselectline {l} {
3982 global findloc commentend ctext
Paul Mackerrasd6982062005-08-06 22:06:06 +10003983 selectline $l 1
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003984 if {$findloc == "All fields" || $findloc == "Comments"} {
3985 # highlight the matches in the comments
3986 set f [$ctext get 1.0 $commentend]
3987 set matches [findmatches $f]
3988 foreach match $matches {
3989 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003990 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00003991 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
3992 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00003993 }
3994}
3995
Paul Mackerrasb74fd572005-07-16 07:46:13 -04003996proc findnext {restart} {
Paul Mackerras98f350e2005-05-15 05:56:51 +00003997 global matchinglines selectedline
3998 if {![info exists matchinglines]} {
Paul Mackerrasb74fd572005-07-16 07:46:13 -04003999 if {$restart} {
4000 dofind
4001 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004002 return
4003 }
4004 if {![info exists selectedline]} return
4005 foreach l $matchinglines {
4006 if {$l > $selectedline} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004007 findselectline $l
Paul Mackerras98f350e2005-05-15 05:56:51 +00004008 return
4009 }
4010 }
4011 bell
4012}
4013
4014proc findprev {} {
4015 global matchinglines selectedline
4016 if {![info exists matchinglines]} {
4017 dofind
4018 return
4019 }
4020 if {![info exists selectedline]} return
4021 set prev {}
4022 foreach l $matchinglines {
4023 if {$l >= $selectedline} break
4024 set prev $l
4025 }
4026 if {$prev != {}} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004027 findselectline $prev
Paul Mackerras98f350e2005-05-15 05:56:51 +00004028 } else {
4029 bell
4030 }
4031}
4032
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004033proc stopfindproc {{done 0}} {
4034 global findprocpid findprocfile findids
4035 global ctext findoldcursor phase maincursor textcursor
4036 global findinprogress
4037
4038 catch {unset findids}
4039 if {[info exists findprocpid]} {
4040 if {!$done} {
4041 catch {exec kill $findprocpid}
4042 }
4043 catch {close $findprocfile}
4044 unset findprocpid
4045 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004046 catch {unset findinprogress}
4047 notbusy find
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004048}
4049
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004050# mark a commit as matching by putting a yellow background
4051# behind the headline
4052proc markheadline {l id} {
Paul Mackerras8ed16482006-03-02 22:56:44 +11004053 global canv mainfont linehtag
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004054
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004055 drawcommits $l
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004056 set bbox [$canv bbox $linehtag($l)]
4057 set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
4058 $canv lower $t
4059}
4060
4061# mark the bits of a headline, author or date that match a find string
Paul Mackerras98f350e2005-05-15 05:56:51 +00004062proc markmatches {canv l str tag matches font} {
4063 set bbox [$canv bbox $tag]
4064 set x0 [lindex $bbox 0]
4065 set y0 [lindex $bbox 1]
4066 set y1 [lindex $bbox 3]
4067 foreach match $matches {
4068 set start [lindex $match 0]
4069 set end [lindex $match 1]
4070 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004071 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
4072 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
4073 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
4074 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras98f350e2005-05-15 05:56:51 +00004075 -outline {} -tags matches -fill yellow]
4076 $canv lower $t
4077 }
4078}
4079
4080proc unmarkmatches {} {
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004081 global matchinglines findids
Paul Mackerras98f350e2005-05-15 05:56:51 +00004082 allcanvs delete matches
4083 catch {unset matchinglines}
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004084 catch {unset findids}
Paul Mackerras98f350e2005-05-15 05:56:51 +00004085}
4086
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004087proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004088 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004089 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00004090 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00004091 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00004092 set yfrac [lindex [$canv yview] 0]
4093 set y [expr {$y + $yfrac * $ymax}]
4094 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
4095 if {$l < 0} {
4096 set l 0
4097 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004098 if {$w eq $canv} {
4099 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
4100 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004101 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004102 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004103}
4104
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004105proc commit_descriptor {p} {
4106 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10004107 if {![info exists commitinfo($p)]} {
4108 getcommit $p
4109 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004110 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10004111 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004112 set l [lindex $commitinfo($p) 0]
4113 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004114 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004115}
4116
Paul Mackerras106288c2005-08-19 23:11:39 +10004117# append some text to the ctext widget, and make any SHA1 ID
4118# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004119proc appendwithlinks {text tags} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004120 global ctext commitrow linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10004121
4122 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004123 $ctext insert end $text $tags
Paul Mackerras106288c2005-08-19 23:11:39 +10004124 set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
4125 foreach l $links {
4126 set s [lindex $l 0]
4127 set e [lindex $l 1]
4128 set linkid [string range $text $s $e]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004129 if {![info exists commitrow($curview,$linkid)]} continue
Paul Mackerras106288c2005-08-19 23:11:39 +10004130 incr e
4131 $ctext tag add link "$start + $s c" "$start + $e c"
4132 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004133 $ctext tag bind link$linknum <1> \
4134 [list selectline $commitrow($curview,$linkid) 1]
Paul Mackerras106288c2005-08-19 23:11:39 +10004135 incr linknum
4136 }
4137 $ctext tag conf link -foreground blue -underline 1
4138 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
4139 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
4140}
4141
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004142proc viewnextline {dir} {
4143 global canv linespc
4144
4145 $canv delete hover
4146 set ymax [lindex [$canv cget -scrollregion] 3]
4147 set wnow [$canv yview]
4148 set wtop [expr {[lindex $wnow 0] * $ymax}]
4149 set newtop [expr {$wtop + $dir * $linespc}]
4150 if {$newtop < 0} {
4151 set newtop 0
4152 } elseif {$newtop > $ymax} {
4153 set newtop $ymax
4154 }
4155 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
4156}
4157
Paul Mackerrasef030b82006-06-04 11:50:38 +10004158# add a list of tag or branch names at position pos
4159# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10004160proc appendrefs {pos ids var} {
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004161 global ctext commitrow linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004162
Paul Mackerrasef030b82006-06-04 11:50:38 +10004163 if {[catch {$ctext index $pos}]} {
4164 return 0
4165 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004166 $ctext conf -state normal
4167 $ctext delete $pos "$pos lineend"
4168 set tags {}
4169 foreach id $ids {
4170 foreach tag [set $var\($id\)] {
4171 lappend tags [list $tag $id]
4172 }
4173 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004174 if {[llength $tags] > $maxrefs} {
4175 $ctext insert $pos "many ([llength $tags])"
4176 } else {
4177 set tags [lsort -index 0 -decreasing $tags]
4178 set sep {}
4179 foreach ti $tags {
4180 set id [lindex $ti 1]
4181 set lk link$linknum
4182 incr linknum
4183 $ctext tag delete $lk
4184 $ctext insert $pos $sep
4185 $ctext insert $pos [lindex $ti 0] $lk
4186 if {[info exists commitrow($curview,$id)]} {
4187 $ctext tag conf $lk -foreground blue
4188 $ctext tag bind $lk <1> \
4189 [list selectline $commitrow($curview,$id) 1]
4190 $ctext tag conf $lk -underline 1
4191 $ctext tag bind $lk <Enter> { %W configure -cursor hand2 }
4192 $ctext tag bind $lk <Leave> \
4193 { %W configure -cursor $curtextcursor }
4194 }
4195 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004196 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004197 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004198 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10004199 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004200}
4201
4202# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10004203proc dispneartags {delay} {
4204 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004205
4206 if {![info exists selectedline] || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10004207 after cancel dispnexttag
4208 if {$delay} {
4209 after 200 dispnexttag
4210 set tagphase -1
4211 } else {
4212 after idle dispnexttag
4213 set tagphase 0
4214 }
4215}
4216
4217proc dispnexttag {} {
4218 global selectedline currentid showneartags tagphase ctext
4219
4220 if {![info exists selectedline] || !$showneartags} return
4221 switch -- $tagphase {
4222 0 {
4223 set dtags [desctags $currentid]
4224 if {$dtags ne {}} {
4225 appendrefs precedes $dtags idtags
4226 }
4227 }
4228 1 {
4229 set atags [anctags $currentid]
4230 if {$atags ne {}} {
4231 appendrefs follows $atags idtags
4232 }
4233 }
4234 2 {
4235 set dheads [descheads $currentid]
4236 if {$dheads ne {}} {
4237 if {[appendrefs branch $dheads idheads] > 1
4238 && [$ctext get "branch -3c"] eq "h"} {
4239 # turn "Branch" into "Branches"
4240 $ctext conf -state normal
4241 $ctext insert "branch -2c" "es"
4242 $ctext conf -state disabled
4243 }
4244 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004245 }
4246 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004247 if {[incr tagphase] <= 2} {
4248 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004249 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004250}
4251
Paul Mackerrasd6982062005-08-06 22:06:06 +10004252proc selectline {l isnew} {
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004253 global canv canv2 canv3 ctext commitinfo selectedline
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004254 global displayorder linehtag linentag linedtag
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004255 global canvy0 linespc parentlist children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004256 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004257 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004258 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10004259 global cmitmode showneartags allcommits
Paul Mackerrasd6982062005-08-06 22:06:06 +10004260
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004261 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00004262 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10004263 normalline
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004264 cancel_next_highlight
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004265 if {$l < 0 || $l >= $numcommits} return
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004266 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00004267 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00004268 set ytop [expr {$y - $linespc - 1}]
4269 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004270 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004271 set wtop [expr {[lindex $wnow 0] * $ymax}]
4272 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00004273 set wh [expr {$wbot - $wtop}]
4274 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00004275 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00004276 if {$ybot < $wtop} {
4277 set newtop [expr {$y - $wh / 2.0}]
4278 } else {
4279 set newtop $ytop
4280 if {$newtop > $wtop - $linespc} {
4281 set newtop [expr {$wtop - $linespc}]
4282 }
Paul Mackerras17386062005-05-18 22:51:00 +00004283 }
Paul Mackerras58422152005-05-19 10:56:42 +00004284 } elseif {$ybot > $wbot} {
4285 if {$ytop > $wbot} {
4286 set newtop [expr {$y - $wh / 2.0}]
4287 } else {
4288 set newtop [expr {$ybot - $wh}]
4289 if {$newtop < $wtop + $linespc} {
4290 set newtop [expr {$wtop + $linespc}]
4291 }
Paul Mackerras17386062005-05-18 22:51:00 +00004292 }
Paul Mackerras58422152005-05-19 10:56:42 +00004293 }
4294 if {$newtop != $wtop} {
4295 if {$newtop < 0} {
4296 set newtop 0
4297 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004298 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004299 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004300 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004301
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004302 if {![info exists linehtag($l)]} return
4303 $canv delete secsel
4304 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
4305 -tags secsel -fill [$canv cget -selectbackground]]
4306 $canv lower $t
4307 $canv2 delete secsel
4308 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
4309 -tags secsel -fill [$canv2 cget -selectbackground]]
4310 $canv2 lower $t
4311 $canv3 delete secsel
4312 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
4313 -tags secsel -fill [$canv3 cget -selectbackground]]
4314 $canv3 lower $t
4315
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004316 if {$isnew} {
4317 addtohistory [list selectline $l 0]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004318 }
4319
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004320 set selectedline $l
4321
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004322 set id [lindex $displayorder $l]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004323 set currentid $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004324 $sha1entry delete 0 end
4325 $sha1entry insert 0 $id
4326 $sha1entry selection from 0
4327 $sha1entry selection to end
Paul Mackerras164ff272006-05-29 19:50:02 +10004328 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004329
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004330 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004331 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10004332 set linknum 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00004333 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11004334 set date [formatdate [lindex $info 2]]
4335 $ctext insert end "Author: [lindex $info 1] $date\n"
4336 set date [formatdate [lindex $info 4]]
4337 $ctext insert end "Committer: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004338 if {[info exists idtags($id)]} {
4339 $ctext insert end "Tags:"
4340 foreach tag $idtags($id) {
4341 $ctext insert end " $tag"
4342 }
4343 $ctext insert end "\n"
4344 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004345
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004346 set headers {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004347 set olds [lindex $parentlist $l]
4348 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004349 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10004350 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004351 if {$np >= $mergemax} {
4352 set tag mmax
4353 } else {
4354 set tag m$np
4355 }
4356 $ctext insert end "Parent: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004357 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004358 incr np
4359 }
4360 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004361 foreach p $olds {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004362 append headers "Parent: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004363 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004364 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004365
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004366 foreach c $children($curview,$id) {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004367 append headers "Child: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004368 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004369
4370 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004371 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004372 if {$showneartags} {
4373 if {![info exists allcommits]} {
4374 getallcommits
4375 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004376 $ctext insert end "Branch: "
4377 $ctext mark set branch "end -1c"
4378 $ctext mark gravity branch left
Paul Mackerrasef030b82006-06-04 11:50:38 +10004379 $ctext insert end "\nFollows: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004380 $ctext mark set follows "end -1c"
4381 $ctext mark gravity follows left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004382 $ctext insert end "\nPrecedes: "
4383 $ctext mark set precedes "end -1c"
4384 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004385 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10004386 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004387 }
4388 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10004389 set comment [lindex $info 5]
4390 if {[string first "\r" $comment] >= 0} {
4391 set comment [string map {"\r" "\n "} $comment]
4392 }
4393 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10004394
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004395 $ctext tag delete Comments
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004396 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004397 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004398 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004399
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004400 init_flist "Comments"
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004401 if {$cmitmode eq "tree"} {
4402 gettree $id
4403 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11004404 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11004405 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004406 mergediff $id $l
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004407 }
4408}
4409
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004410proc selfirstline {} {
4411 unmarkmatches
4412 selectline 0 1
4413}
4414
4415proc sellastline {} {
4416 global numcommits
4417 unmarkmatches
4418 set l [expr {$numcommits - 1}]
4419 selectline $l 1
4420}
4421
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004422proc selnextline {dir} {
4423 global selectedline
4424 if {![info exists selectedline]} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004425 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004426 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004427 selectline $l 1
4428}
4429
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004430proc selnextpage {dir} {
4431 global canv linespc selectedline numcommits
4432
4433 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
4434 if {$lpp < 1} {
4435 set lpp 1
4436 }
4437 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10004438 drawvisible
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004439 if {![info exists selectedline]} return
4440 set l [expr {$selectedline + $dir * $lpp}]
4441 if {$l < 0} {
4442 set l 0
4443 } elseif {$l >= $numcommits} {
4444 set l [expr $numcommits - 1]
4445 }
4446 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004447 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004448}
4449
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004450proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004451 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004452
4453 catch {unset selectedline}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004454 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004455 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10004456 rhighlight_none
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004457 cancel_next_highlight
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004458}
4459
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004460proc reselectline {} {
4461 global selectedline
4462
4463 if {[info exists selectedline]} {
4464 selectline $selectedline 0
4465 }
4466}
4467
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004468proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004469 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004470
Paul Mackerras2516dae2006-04-21 10:35:31 +10004471 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004472 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10004473 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004474 return
4475 }
4476
4477 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004478 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004479 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004480 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004481 }
4482 incr historyindex
4483 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004484 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004485 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004486 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004487 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004488 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004489}
4490
Paul Mackerras2516dae2006-04-21 10:35:31 +10004491proc godo {elt} {
4492 global curview
4493
4494 set view [lindex $elt 0]
4495 set cmd [lindex $elt 1]
4496 if {$curview != $view} {
4497 showview $view
4498 }
4499 eval $cmd
4500}
4501
Paul Mackerrasd6982062005-08-06 22:06:06 +10004502proc goback {} {
4503 global history historyindex
4504
4505 if {$historyindex > 1} {
4506 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10004507 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004508 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004509 }
4510 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004511 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004512 }
4513}
4514
4515proc goforw {} {
4516 global history historyindex
4517
4518 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004519 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004520 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10004521 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004522 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004523 }
4524 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004525 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004526 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004527}
4528
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004529proc gettree {id} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004530 global treefilelist treeidlist diffids diffmergeid treepending nullid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004531
4532 set diffids $id
4533 catch {unset diffmergeid}
4534 if {![info exists treefilelist($id)]} {
4535 if {![info exists treepending]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004536 if {$id ne $nullid} {
4537 set cmd [concat | git ls-tree -r $id]
4538 } else {
4539 set cmd [concat | git ls-files]
4540 }
4541 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004542 return
4543 }
4544 set treepending $id
4545 set treefilelist($id) {}
4546 set treeidlist($id) {}
4547 fconfigure $gtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004548 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004549 }
4550 } else {
4551 setfilelist $id
4552 }
4553}
4554
4555proc gettreeline {gtf id} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004556 global treefilelist treeidlist treepending cmitmode diffids nullid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004557
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004558 set nl 0
4559 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004560 if {$diffids ne $nullid} {
4561 set tl [split $line "\t"]
4562 if {[lindex $tl 0 1] ne "blob"} continue
4563 set sha1 [lindex $tl 0 2]
4564 set fname [lindex $tl 1]
4565 if {[string index $fname 0] eq "\""} {
4566 set fname [lindex $fname 0]
4567 }
4568 lappend treeidlist($id) $sha1
4569 } else {
4570 set fname $line
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004571 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004572 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004573 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004574 if {![eof $gtf]} {
4575 return [expr {$nl >= 1000? 2: 1}]
4576 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004577 close $gtf
4578 unset treepending
4579 if {$cmitmode ne "tree"} {
4580 if {![info exists diffmergeid]} {
4581 gettreediffs $diffids
4582 }
4583 } elseif {$id ne $diffids} {
4584 gettree $diffids
4585 } else {
4586 setfilelist $id
4587 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004588 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004589}
4590
4591proc showfile {f} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004592 global treefilelist treeidlist diffids nullid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004593 global ctext commentend
4594
4595 set i [lsearch -exact $treefilelist($diffids) $f]
4596 if {$i < 0} {
4597 puts "oops, $f not in list for id $diffids"
4598 return
4599 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004600 if {$diffids ne $nullid} {
4601 set blob [lindex $treeidlist($diffids) $i]
4602 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
4603 puts "oops, error reading blob $blob: $err"
4604 return
4605 }
4606 } else {
4607 if {[catch {set bf [open $f r]} err]} {
4608 puts "oops, can't read $f: $err"
4609 return
4610 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004611 }
4612 fconfigure $bf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004613 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004614 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004615 clear_ctext $commentend
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004616 $ctext insert end "\n"
4617 $ctext insert end "$f\n" filesep
4618 $ctext config -state disabled
4619 $ctext yview $commentend
4620}
4621
4622proc getblobline {bf id} {
4623 global diffids cmitmode ctext
4624
4625 if {$id ne $diffids || $cmitmode ne "tree"} {
4626 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004627 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004628 }
4629 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004630 set nl 0
4631 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004632 $ctext insert end "$line\n"
4633 }
4634 if {[eof $bf]} {
4635 # delete last newline
4636 $ctext delete "end - 2c" "end - 1c"
4637 close $bf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004638 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004639 }
4640 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004641 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004642}
4643
Paul Mackerras79b2c752006-04-02 20:47:40 +10004644proc mergediff {id l} {
4645 global diffmergeid diffopts mdifffd
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004646 global diffids
Paul Mackerras79b2c752006-04-02 20:47:40 +10004647 global parentlist
Paul Mackerrase2ed4322005-07-17 03:39:44 -04004648
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004649 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004650 set diffids $id
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004651 # this doesn't seem to actually affect anything...
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004652 set env(GIT_DIFF_OPTS) $diffopts
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03004653 set cmd [concat | git diff-tree --no-commit-id --cc $id]
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004654 if {[catch {set mdf [open $cmd r]} err]} {
4655 error_popup "Error getting merge diffs: $err"
4656 return
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004657 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004658 fconfigure $mdf -blocking 0
4659 set mdifffd($id) $mdf
Paul Mackerras79b2c752006-04-02 20:47:40 +10004660 set np [llength [lindex $parentlist $l]]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004661 filerun $mdf [list getmergediffline $mdf $id $np]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004662}
4663
Paul Mackerras79b2c752006-04-02 20:47:40 +10004664proc getmergediffline {mdf id np} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004665 global diffmergeid ctext cflist mergemax
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004666 global difffilestart mdifffd
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004667
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004668 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004669 set nr 0
4670 while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
4671 if {![info exists diffmergeid] || $id != $diffmergeid
4672 || $mdf != $mdifffd($id)} {
4673 close $mdf
4674 return 0
4675 }
4676 if {[regexp {^diff --cc (.*)} $line match fname]} {
4677 # start of a new file
4678 $ctext insert end "\n"
4679 set here [$ctext index "end - 1c"]
4680 lappend difffilestart $here
4681 add_flist [list $fname]
4682 set l [expr {(78 - [string length $fname]) / 2}]
4683 set pad [string range "----------------------------------------" 1 $l]
4684 $ctext insert end "$pad $fname $pad\n" filesep
4685 } elseif {[regexp {^@@} $line]} {
4686 $ctext insert end "$line\n" hunksep
4687 } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
4688 # do nothing
4689 } else {
4690 # parse the prefix - one ' ', '-' or '+' for each parent
4691 set spaces {}
4692 set minuses {}
4693 set pluses {}
4694 set isbad 0
4695 for {set j 0} {$j < $np} {incr j} {
4696 set c [string range $line $j $j]
4697 if {$c == " "} {
4698 lappend spaces $j
4699 } elseif {$c == "-"} {
4700 lappend minuses $j
4701 } elseif {$c == "+"} {
4702 lappend pluses $j
4703 } else {
4704 set isbad 1
4705 break
4706 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004707 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004708 set tags {}
4709 set num {}
4710 if {!$isbad && $minuses ne {} && $pluses eq {}} {
4711 # line doesn't appear in result, parents in $minuses have the line
4712 set num [lindex $minuses 0]
4713 } elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
4714 # line appears in result, parents in $pluses don't have the line
4715 lappend tags mresult
4716 set num [lindex $spaces 0]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004717 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004718 if {$num ne {}} {
4719 if {$num >= $mergemax} {
4720 set num "max"
4721 }
4722 lappend tags m$num
4723 }
4724 $ctext insert end "$line\n" $tags
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004725 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004726 }
4727 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004728 if {[eof $mdf]} {
4729 close $mdf
4730 return 0
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05004731 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004732 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05004733}
4734
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004735proc startdiff {ids} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004736 global treediffs diffids treepending diffmergeid nullid
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004737
4738 set diffids $ids
4739 catch {unset diffmergeid}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004740 if {![info exists treediffs($ids)] || [lsearch -exact $ids $nullid] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004741 if {![info exists treepending]} {
4742 gettreediffs $ids
4743 }
4744 } else {
4745 addtocflist $ids
4746 }
4747}
4748
4749proc addtocflist {ids} {
4750 global treediffs cflist
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004751 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004752 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004753}
4754
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004755proc diffcmd {ids flags} {
4756 global nullid
4757
4758 set i [lsearch -exact $ids $nullid]
4759 if {$i >= 0} {
4760 set cmd [concat | git diff-index $flags]
4761 if {[llength $ids] > 1} {
4762 if {$i == 0} {
4763 lappend cmd -R [lindex $ids 1]
4764 } else {
4765 lappend cmd [lindex $ids 0]
4766 }
4767 } else {
4768 lappend cmd HEAD
4769 }
4770 } else {
4771 set cmd [concat | git diff-tree --no-commit-id -r $flags $ids]
4772 }
4773 return $cmd
4774}
4775
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004776proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004777 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004778
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004779 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004780 set treediff {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004781 if {[catch {set gdtf [open [diffcmd $ids {}] r]}]} return
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004782 fconfigure $gdtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004783 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004784}
4785
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004786proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004787 global treediff treediffs treepending diffids diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004788 global cmitmode
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004789
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004790 set nr 0
4791 while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
4792 set file [lindex $line 5]
4793 lappend treediff $file
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004794 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004795 if {![eof $gdtf]} {
4796 return [expr {$nr >= 1000? 2: 1}]
4797 }
4798 close $gdtf
4799 set treediffs($ids) $treediff
4800 unset treepending
4801 if {$cmitmode eq "tree"} {
4802 gettree $diffids
4803 } elseif {$ids != $diffids} {
4804 if {![info exists diffmergeid]} {
4805 gettreediffs $diffids
4806 }
4807 } else {
4808 addtocflist $ids
4809 }
4810 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004811}
4812
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004813proc getblobdiffs {ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004814 global diffopts blobdifffd diffids env curdifftag curtagstart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004815 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004816
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004817 set env(GIT_DIFF_OPTS) $diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004818 if {[catch {set bdf [open [diffcmd $ids {-p -C}] r]} err]} {
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004819 puts "error getting diffs: $err"
4820 return
4821 }
Paul Mackerras4f2c2642005-07-17 11:11:44 -04004822 set diffinhdr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004823 fconfigure $bdf -blocking 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004824 set blobdifffd($ids) $bdf
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004825 set curdifftag Comments
4826 set curtagstart 0.0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004827 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004828}
4829
Paul Mackerras89b11d32006-05-02 19:55:31 +10004830proc setinlist {var i val} {
4831 global $var
4832
4833 while {[llength [set $var]] < $i} {
4834 lappend $var {}
4835 }
4836 if {[llength [set $var]] == $i} {
4837 lappend $var $val
4838 } else {
4839 lset $var $i $val
4840 }
4841}
4842
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004843proc getblobdiffline {bdf ids} {
Paul Mackerras4f2c2642005-07-17 11:11:44 -04004844 global diffids blobdifffd ctext curdifftag curtagstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04004845 global diffnexthead diffnextnote difffilestart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004846 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004847
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004848 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004849 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004850 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
4851 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
4852 close $bdf
4853 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10004854 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004855 if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} {
4856 # start of a new file
4857 $ctext insert end "\n"
4858 $ctext tag add $curdifftag $curtagstart end
4859 set here [$ctext index "end - 1c"]
4860 set curtagstart $here
4861 set header $newname
4862 set i [lsearch -exact $treediffs($ids) $fname]
Paul Mackerras89b11d32006-05-02 19:55:31 +10004863 if {$i >= 0} {
4864 setinlist difffilestart $i $here
4865 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004866 if {$newname ne $fname} {
4867 set i [lsearch -exact $treediffs($ids) $newname]
4868 if {$i >= 0} {
4869 setinlist difffilestart $i $here
4870 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004871 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004872 set curdifftag "f:$fname"
4873 $ctext tag delete $curdifftag
4874 set l [expr {(78 - [string length $header]) / 2}]
4875 set pad [string range "----------------------------------------" \
4876 1 $l]
4877 $ctext insert end "$pad $header $pad\n" filesep
4878 set diffinhdr 1
4879 } elseif {$diffinhdr && [string compare -length 3 $line "---"] == 0} {
4880 # do nothing
4881 } elseif {$diffinhdr && [string compare -length 3 $line "+++"] == 0} {
4882 set diffinhdr 0
4883 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
4884 $line match f1l f1c f2l f2c rest]} {
4885 $ctext insert end "$line\n" hunksep
4886 set diffinhdr 0
4887 } else {
4888 set x [string range $line 0 0]
4889 if {$x == "-" || $x == "+"} {
4890 set tag [expr {$x == "+"}]
4891 $ctext insert end "$line\n" d$tag
4892 } elseif {$x == " "} {
4893 $ctext insert end "$line\n"
4894 } elseif {$diffinhdr || $x == "\\"} {
4895 # e.g. "\ No newline at end of file"
4896 $ctext insert end "$line\n" filesep
4897 } else {
4898 # Something else we don't recognize
4899 if {$curdifftag != "Comments"} {
4900 $ctext insert end "\n"
4901 $ctext tag add $curdifftag $curtagstart end
4902 set curtagstart [$ctext index "end - 1c"]
4903 set curdifftag Comments
4904 }
4905 $ctext insert end "$line\n" filesep
4906 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004907 }
4908 }
4909 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004910 if {[eof $bdf]} {
4911 close $bdf
4912 if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
4913 $ctext tag add $curdifftag $curtagstart end
4914 }
4915 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004916 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004917 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004918}
4919
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10004920proc changediffdisp {} {
4921 global ctext diffelide
4922
4923 $ctext tag conf d0 -elide [lindex $diffelide 0]
4924 $ctext tag conf d1 -elide [lindex $diffelide 1]
4925}
4926
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09004927proc prevfile {} {
4928 global difffilestart ctext
4929 set prev [lindex $difffilestart 0]
4930 set here [$ctext index @0,0]
4931 foreach loc $difffilestart {
4932 if {[$ctext compare $loc >= $here]} {
4933 $ctext yview $prev
4934 return
4935 }
4936 set prev $loc
4937 }
4938 $ctext yview $prev
4939}
4940
Paul Mackerras39ad8572005-05-19 12:35:53 +00004941proc nextfile {} {
4942 global difffilestart ctext
4943 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004944 foreach loc $difffilestart {
4945 if {[$ctext compare $loc > $here]} {
4946 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09004947 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00004948 }
4949 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00004950}
4951
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004952proc clear_ctext {{first 1.0}} {
4953 global ctext smarktop smarkbot
4954
Paul Mackerras1902c272006-05-25 21:25:13 +10004955 set l [lindex [split $first .] 0]
4956 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
4957 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004958 }
Paul Mackerras1902c272006-05-25 21:25:13 +10004959 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
4960 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004961 }
4962 $ctext delete $first end
4963}
4964
4965proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10004966 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004967
4968 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10004969 if {[catch {$ctext index anchor}]} {
4970 # no anchor set, use start of selection, or of visible area
4971 set sel [$ctext tag ranges sel]
4972 if {$sel ne {}} {
4973 $ctext mark set anchor [lindex $sel 0]
4974 } elseif {$searchdirn eq "-forwards"} {
4975 $ctext mark set anchor @0,0
4976 } else {
4977 $ctext mark set anchor @0,[winfo height $ctext]
4978 }
4979 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004980 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10004981 set here [$ctext search $searchdirn -- $searchstring anchor]
4982 if {$here ne {}} {
4983 $ctext see $here
4984 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004985 searchmarkvisible 1
4986 }
4987}
4988
4989proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10004990 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004991
4992 focus $sstring
4993 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10004994 set searchdirn -forwards
4995 if {$searchstring ne {}} {
4996 set sel [$ctext tag ranges sel]
4997 if {$sel ne {}} {
4998 set start "[lindex $sel 0] + 1c"
4999 } elseif {[catch {set start [$ctext index anchor]}]} {
5000 set start "@0,0"
5001 }
5002 set match [$ctext search -count mlen -- $searchstring $start]
5003 $ctext tag remove sel 1.0 end
5004 if {$match eq {}} {
5005 bell
5006 return
5007 }
5008 $ctext see $match
5009 set mend "$match + $mlen c"
5010 $ctext tag add sel $match $mend
5011 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005012 }
Paul Mackerras1902c272006-05-25 21:25:13 +10005013}
5014
5015proc dosearchback {} {
5016 global sstring ctext searchstring searchdirn
5017
5018 focus $sstring
5019 $sstring icursor end
5020 set searchdirn -backwards
5021 if {$searchstring ne {}} {
5022 set sel [$ctext tag ranges sel]
5023 if {$sel ne {}} {
5024 set start [lindex $sel 0]
5025 } elseif {[catch {set start [$ctext index anchor]}]} {
5026 set start @0,[winfo height $ctext]
5027 }
5028 set match [$ctext search -backwards -count ml -- $searchstring $start]
5029 $ctext tag remove sel 1.0 end
5030 if {$match eq {}} {
5031 bell
5032 return
5033 }
5034 $ctext see $match
5035 set mend "$match + $ml c"
5036 $ctext tag add sel $match $mend
5037 $ctext mark unset anchor
5038 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005039}
5040
5041proc searchmark {first last} {
5042 global ctext searchstring
5043
5044 set mend $first.0
5045 while {1} {
5046 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
5047 if {$match eq {}} break
5048 set mend "$match + $mlen c"
5049 $ctext tag add found $match $mend
5050 }
5051}
5052
5053proc searchmarkvisible {doall} {
5054 global ctext smarktop smarkbot
5055
5056 set topline [lindex [split [$ctext index @0,0] .] 0]
5057 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
5058 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
5059 # no overlap with previous
5060 searchmark $topline $botline
5061 set smarktop $topline
5062 set smarkbot $botline
5063 } else {
5064 if {$topline < $smarktop} {
5065 searchmark $topline [expr {$smarktop-1}]
5066 set smarktop $topline
5067 }
5068 if {$botline > $smarkbot} {
5069 searchmark [expr {$smarkbot+1}] $botline
5070 set smarkbot $botline
5071 }
5072 }
5073}
5074
5075proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005076 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005077
Junio C Hamanoe9937d22007-02-01 08:46:38 -05005078 .bleft.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005079 if {$searchstring ne {}} {
5080 searchmarkvisible 0
5081 }
5082}
5083
Paul Mackerras1d10f362005-05-15 12:55:47 +00005084proc setcoords {} {
5085 global linespc charspc canvx0 canvy0 mainfont
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005086 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10005087
Paul Mackerras1d10f362005-05-15 12:55:47 +00005088 set linespc [font metrics $mainfont -linespace]
5089 set charspc [font measure $mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005090 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
5091 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005092 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10005093 set xspc1(0) $linespc
5094 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00005095}
Paul Mackerras1db95b02005-05-09 04:08:39 +00005096
Paul Mackerras1d10f362005-05-15 12:55:47 +00005097proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005098 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005099 global selectedline
5100
5101 set ymax [lindex [$canv cget -scrollregion] 3]
5102 if {$ymax eq {} || $ymax == 0} return
5103 set span [$canv yview]
5104 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005105 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005106 allcanvs yview moveto [lindex $span 0]
5107 drawvisible
5108 if {[info exists selectedline]} {
5109 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005110 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00005111 }
5112}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005113
5114proc incrfont {inc} {
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005115 global mainfont textfont ctext canv phase cflist
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005116 global charspc tabstop
Paul Mackerrascfb45632005-05-31 12:14:42 +00005117 global stopped entries
Paul Mackerras1d10f362005-05-15 12:55:47 +00005118 unmarkmatches
5119 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
Paul Mackerras1d10f362005-05-15 12:55:47 +00005120 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
5121 setcoords
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005122 $ctext conf -font $textfont -tabs "[expr {$tabstop * $charspc}]"
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005123 $cflist conf -font $textfont
Paul Mackerras1d10f362005-05-15 12:55:47 +00005124 $ctext tag conf filesep -font [concat $textfont bold]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005125 foreach e $entries {
5126 $e conf -font $mainfont
5127 }
Paul Mackerras22626ef2006-04-17 09:56:02 +10005128 if {$phase eq "getcommits"} {
Paul Mackerras1d10f362005-05-15 12:55:47 +00005129 $canv itemconf textitems -font $mainfont
5130 }
5131 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00005132}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005133
Paul Mackerrasee3dc722005-06-25 16:37:13 +10005134proc clearsha1 {} {
5135 global sha1entry sha1string
5136 if {[string length $sha1string] == 40} {
5137 $sha1entry delete 0 end
5138 }
5139}
5140
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005141proc sha1change {n1 n2 op} {
5142 global sha1string currentid sha1but
5143 if {$sha1string == {}
5144 || ([info exists currentid] && $sha1string == $currentid)} {
5145 set state disabled
5146 } else {
5147 set state normal
5148 }
5149 if {[$sha1but cget -state] == $state} return
5150 if {$state == "normal"} {
5151 $sha1but conf -state normal -relief raised -text "Goto: "
5152 } else {
5153 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
5154 }
5155}
5156
5157proc gotocommit {} {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005158 global sha1string currentid commitrow tagids headids
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005159 global displayorder numcommits curview
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005160
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005161 if {$sha1string == {}
5162 || ([info exists currentid] && $sha1string == $currentid)} return
5163 if {[info exists tagids($sha1string)]} {
5164 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11005165 } elseif {[info exists headids($sha1string)]} {
5166 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005167 } else {
5168 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005169 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
5170 set matches {}
Paul Mackerras8ed16482006-03-02 22:56:44 +11005171 foreach i $displayorder {
5172 if {[string match $id* $i]} {
5173 lappend matches $i
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005174 }
5175 }
5176 if {$matches ne {}} {
5177 if {[llength $matches] > 1} {
5178 error_popup "Short SHA1 id $id is ambiguous"
5179 return
5180 }
5181 set id [lindex $matches 0]
5182 }
5183 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005184 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005185 if {[info exists commitrow($curview,$id)]} {
5186 selectline $commitrow($curview,$id) 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005187 return
5188 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005189 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005190 set type "SHA1 id"
5191 } else {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005192 set type "Tag/Head"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005193 }
5194 error_popup "$type $sha1string is not known"
5195}
5196
Paul Mackerras84ba7342005-06-17 00:12:26 +00005197proc lineenter {x y id} {
5198 global hoverx hovery hoverid hovertimer
5199 global commitinfo canv
5200
Paul Mackerras8ed16482006-03-02 22:56:44 +11005201 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00005202 set hoverx $x
5203 set hovery $y
5204 set hoverid $id
5205 if {[info exists hovertimer]} {
5206 after cancel $hovertimer
5207 }
5208 set hovertimer [after 500 linehover]
5209 $canv delete hover
5210}
5211
5212proc linemotion {x y id} {
5213 global hoverx hovery hoverid hovertimer
5214
5215 if {[info exists hoverid] && $id == $hoverid} {
5216 set hoverx $x
5217 set hovery $y
5218 if {[info exists hovertimer]} {
5219 after cancel $hovertimer
5220 }
5221 set hovertimer [after 500 linehover]
5222 }
5223}
5224
5225proc lineleave {id} {
5226 global hoverid hovertimer canv
5227
5228 if {[info exists hoverid] && $id == $hoverid} {
5229 $canv delete hover
5230 if {[info exists hovertimer]} {
5231 after cancel $hovertimer
5232 unset hovertimer
5233 }
5234 unset hoverid
5235 }
5236}
5237
5238proc linehover {} {
5239 global hoverx hovery hoverid hovertimer
5240 global canv linespc lthickness
5241 global commitinfo mainfont
5242
5243 set text [lindex $commitinfo($hoverid) 0]
5244 set ymax [lindex [$canv cget -scrollregion] 3]
5245 if {$ymax == {}} return
5246 set yfrac [lindex [$canv yview] 0]
5247 set x [expr {$hoverx + 2 * $linespc}]
5248 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
5249 set x0 [expr {$x - 2 * $lthickness}]
5250 set y0 [expr {$y - 2 * $lthickness}]
5251 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
5252 set y1 [expr {$y + $linespc + 2 * $lthickness}]
5253 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
5254 -fill \#ffff80 -outline black -width 1 -tags hover]
5255 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10005256 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
5257 -font $mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00005258 $canv raise $t
5259}
5260
Paul Mackerras9843c302005-08-30 10:57:11 +10005261proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005262 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10005263
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005264 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10005265 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005266 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005267 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005268 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005269 if {abs([yc $row] - $y) < $thresh} {
5270 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10005271 }
5272 }
5273 return {}
5274}
5275
Paul Mackerrasf6342482006-02-28 10:02:03 +11005276proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005277 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10005278
Paul Mackerrasf6342482006-02-28 10:02:03 +11005279 # 1 <-> 2, 3 <-> 4, etc...
5280 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005281 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005282 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10005283 set ymax [lindex [$canv cget -scrollregion] 3]
5284 if {$ymax eq {} || $ymax <= 0} return
5285 set view [$canv yview]
5286 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
5287 set yfrac [expr {$yt / $ymax - $yspan / 2}]
5288 if {$yfrac < 0} {
5289 set yfrac 0
5290 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11005291 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10005292}
5293
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005294proc lineclick {x y id isnew} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005295 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005296
Paul Mackerras8ed16482006-03-02 22:56:44 +11005297 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005298 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005299 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10005300 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005301 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10005302 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10005303 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005304 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005305 if {$isnew} {
5306 set ymax [lindex [$canv cget -scrollregion] 3]
5307 if {$ymax eq {}} return
5308 set yfrac [lindex [$canv yview] 0]
5309 set y [expr {$y + $yfrac * $ymax}]
5310 }
5311 set dirn [clickisonarrow $id $y]
5312 if {$dirn ne {}} {
5313 arrowjump $id $dirn $y
5314 return
5315 }
5316
5317 if {$isnew} {
5318 addtohistory [list lineclick $x $y $id 0]
5319 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005320 # fill the details pane with info about this line
5321 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005322 clear_ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005323 $ctext tag conf link -foreground blue -underline 1
5324 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
5325 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
5326 $ctext insert end "Parent:\t"
5327 $ctext insert end $id [list link link0]
5328 $ctext tag bind link0 <1> [list selbyid $id]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005329 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005330 $ctext insert end "\n\t[lindex $info 0]\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005331 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11005332 set date [formatdate [lindex $info 2]]
5333 $ctext insert end "\tDate:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005334 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005335 if {$kids ne {}} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005336 $ctext insert end "\nChildren:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005337 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10005338 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005339 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11005340 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005341 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005342 $ctext insert end "\n\t"
5343 $ctext insert end $child [list link link$i]
5344 $ctext tag bind link$i <1> [list selbyid $child]
5345 $ctext insert end "\n\t[lindex $info 0]"
5346 $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11005347 set date [formatdate [lindex $info 2]]
5348 $ctext insert end "\n\tDate:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005349 }
5350 }
5351 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005352 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005353}
5354
Paul Mackerras9843c302005-08-30 10:57:11 +10005355proc normalline {} {
5356 global thickerline
5357 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005358 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10005359 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005360 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005361 }
5362}
5363
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005364proc selbyid {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005365 global commitrow curview
5366 if {[info exists commitrow($curview,$id)]} {
5367 selectline $commitrow($curview,$id) 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005368 }
5369}
5370
5371proc mstime {} {
5372 global startmstime
5373 if {![info exists startmstime]} {
5374 set startmstime [clock clicks -milliseconds]
5375 }
5376 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
5377}
5378
5379proc rowmenu {x y id} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005380 global rowctxmenu commitrow selectedline rowmenuid curview nullid
5381 global fakerowmenu
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005382
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005383 set rowmenuid $id
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005384 if {![info exists selectedline]
5385 || $commitrow($curview,$id) eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005386 set state disabled
5387 } else {
5388 set state normal
5389 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005390 if {$id ne $nullid} {
5391 set menu $rowctxmenu
5392 } else {
5393 set menu $fakerowmenu
5394 }
5395 $menu entryconfigure "Diff this*" -state $state
5396 $menu entryconfigure "Diff selected*" -state $state
5397 $menu entryconfigure "Make patch" -state $state
5398 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005399}
5400
5401proc diffvssel {dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005402 global rowmenuid selectedline displayorder
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005403
5404 if {![info exists selectedline]} return
5405 if {$dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005406 set oldid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005407 set newid $rowmenuid
5408 } else {
5409 set oldid $rowmenuid
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005410 set newid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005411 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005412 addtohistory [list doseldiff $oldid $newid]
5413 doseldiff $oldid $newid
5414}
5415
5416proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005417 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005418 global commitinfo
5419
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005420 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005421 clear_ctext
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005422 init_flist "Top"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005423 $ctext insert end "From "
5424 $ctext tag conf link -foreground blue -underline 1
5425 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
5426 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
5427 $ctext tag bind link0 <1> [list selbyid $oldid]
5428 $ctext insert end $oldid [list link link0]
5429 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005430 $ctext insert end [lindex $commitinfo($oldid) 0]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005431 $ctext insert end "\n\nTo "
5432 $ctext tag bind link1 <1> [list selbyid $newid]
5433 $ctext insert end $newid [list link link1]
5434 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005435 $ctext insert end [lindex $commitinfo($newid) 0]
5436 $ctext insert end "\n"
5437 $ctext conf -state disabled
5438 $ctext tag delete Comments
5439 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11005440 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005441}
5442
Paul Mackerras74daedb2005-06-27 19:27:32 +10005443proc mkpatch {} {
5444 global rowmenuid currentid commitinfo patchtop patchnum
5445
5446 if {![info exists currentid]} return
5447 set oldid $currentid
5448 set oldhead [lindex $commitinfo($oldid) 0]
5449 set newid $rowmenuid
5450 set newhead [lindex $commitinfo($newid) 0]
5451 set top .patch
5452 set patchtop $top
5453 catch {destroy $top}
5454 toplevel $top
5455 label $top.title -text "Generate patch"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005456 grid $top.title - -pady 10
Paul Mackerras74daedb2005-06-27 19:27:32 +10005457 label $top.from -text "From:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005458 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005459 $top.fromsha1 insert 0 $oldid
5460 $top.fromsha1 conf -state readonly
5461 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005462 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005463 $top.fromhead insert 0 $oldhead
5464 $top.fromhead conf -state readonly
5465 grid x $top.fromhead -sticky w
5466 label $top.to -text "To:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005467 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005468 $top.tosha1 insert 0 $newid
5469 $top.tosha1 conf -state readonly
5470 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005471 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005472 $top.tohead insert 0 $newhead
5473 $top.tohead conf -state readonly
5474 grid x $top.tohead -sticky w
5475 button $top.rev -text "Reverse" -command mkpatchrev -padx 5
5476 grid $top.rev x -pady 10
5477 label $top.flab -text "Output file:"
5478 entry $top.fname -width 60
5479 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
5480 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005481 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10005482 frame $top.buts
5483 button $top.buts.gen -text "Generate" -command mkpatchgo
5484 button $top.buts.can -text "Cancel" -command mkpatchcan
5485 grid $top.buts.gen $top.buts.can
5486 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5487 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5488 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005489 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10005490}
5491
5492proc mkpatchrev {} {
5493 global patchtop
5494
5495 set oldid [$patchtop.fromsha1 get]
5496 set oldhead [$patchtop.fromhead get]
5497 set newid [$patchtop.tosha1 get]
5498 set newhead [$patchtop.tohead get]
5499 foreach e [list fromsha1 fromhead tosha1 tohead] \
5500 v [list $newid $newhead $oldid $oldhead] {
5501 $patchtop.$e conf -state normal
5502 $patchtop.$e delete 0 end
5503 $patchtop.$e insert 0 $v
5504 $patchtop.$e conf -state readonly
5505 }
5506}
5507
5508proc mkpatchgo {} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005509 global patchtop nullid
Paul Mackerras74daedb2005-06-27 19:27:32 +10005510
5511 set oldid [$patchtop.fromsha1 get]
5512 set newid [$patchtop.tosha1 get]
5513 set fname [$patchtop.fname get]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005514 if {$newid eq $nullid} {
5515 set cmd [list git diff-index -p $oldid]
5516 } elseif {$oldid eq $nullid} {
5517 set cmd [list git diff-index -p -R $newid]
5518 } else {
5519 set cmd [list git diff-tree -p $oldid $newid]
5520 }
5521 lappend cmd >$fname &
5522 if {[catch {eval exec $cmd} err]} {
Paul Mackerras74daedb2005-06-27 19:27:32 +10005523 error_popup "Error creating patch: $err"
5524 }
5525 catch {destroy $patchtop}
5526 unset patchtop
5527}
5528
5529proc mkpatchcan {} {
5530 global patchtop
5531
5532 catch {destroy $patchtop}
5533 unset patchtop
5534}
5535
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005536proc mktag {} {
5537 global rowmenuid mktagtop commitinfo
5538
5539 set top .maketag
5540 set mktagtop $top
5541 catch {destroy $top}
5542 toplevel $top
5543 label $top.title -text "Create tag"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005544 grid $top.title - -pady 10
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005545 label $top.id -text "ID:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005546 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005547 $top.sha1 insert 0 $rowmenuid
5548 $top.sha1 conf -state readonly
5549 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005550 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005551 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5552 $top.head conf -state readonly
5553 grid x $top.head -sticky w
5554 label $top.tlab -text "Tag name:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005555 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005556 grid $top.tlab $top.tag -sticky w
5557 frame $top.buts
5558 button $top.buts.gen -text "Create" -command mktaggo
5559 button $top.buts.can -text "Cancel" -command mktagcan
5560 grid $top.buts.gen $top.buts.can
5561 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5562 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5563 grid $top.buts - -pady 10 -sticky ew
5564 focus $top.tag
5565}
5566
5567proc domktag {} {
5568 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005569
5570 set id [$mktagtop.sha1 get]
5571 set tag [$mktagtop.tag get]
5572 if {$tag == {}} {
5573 error_popup "No tag name specified"
5574 return
5575 }
5576 if {[info exists tagids($tag)]} {
5577 error_popup "Tag \"$tag\" already exists"
5578 return
5579 }
5580 if {[catch {
Junio C Hamano73b6a6c2005-07-28 00:28:44 -07005581 set dir [gitdir]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005582 set fname [file join $dir "refs/tags" $tag]
5583 set f [open $fname w]
5584 puts $f $id
5585 close $f
5586 } err]} {
5587 error_popup "Error creating tag: $err"
5588 return
5589 }
5590
5591 set tagids($tag) $id
5592 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005593 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10005594 addedtag $id
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005595}
5596
5597proc redrawtags {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005598 global canv linehtag commitrow idpos selectedline curview
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005599 global mainfont canvxmax iddrawn
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005600
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005601 if {![info exists commitrow($curview,$id)]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005602 if {![info exists iddrawn($id)]} return
5603 drawcommits $commitrow($curview,$id)
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005604 $canv delete tag.$id
5605 set xt [eval drawtags $id $idpos($id)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005606 $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005607 set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text]
5608 set xr [expr {$xt + [font measure $mainfont $text]}]
5609 if {$xr > $canvxmax} {
5610 set canvxmax $xr
5611 setcanvscroll
5612 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005613 if {[info exists selectedline]
5614 && $selectedline == $commitrow($curview,$id)} {
Paul Mackerrasd6982062005-08-06 22:06:06 +10005615 selectline $selectedline 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005616 }
5617}
5618
5619proc mktagcan {} {
5620 global mktagtop
5621
5622 catch {destroy $mktagtop}
5623 unset mktagtop
5624}
5625
5626proc mktaggo {} {
5627 domktag
5628 mktagcan
5629}
5630
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005631proc writecommit {} {
5632 global rowmenuid wrcomtop commitinfo wrcomcmd
5633
5634 set top .writecommit
5635 set wrcomtop $top
5636 catch {destroy $top}
5637 toplevel $top
5638 label $top.title -text "Write commit to file"
5639 grid $top.title - -pady 10
5640 label $top.id -text "ID:"
5641 entry $top.sha1 -width 40 -relief flat
5642 $top.sha1 insert 0 $rowmenuid
5643 $top.sha1 conf -state readonly
5644 grid $top.id $top.sha1 -sticky w
5645 entry $top.head -width 60 -relief flat
5646 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5647 $top.head conf -state readonly
5648 grid x $top.head -sticky w
5649 label $top.clab -text "Command:"
5650 entry $top.cmd -width 60 -textvariable wrcomcmd
5651 grid $top.clab $top.cmd -sticky w -pady 10
5652 label $top.flab -text "Output file:"
5653 entry $top.fname -width 60
5654 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
5655 grid $top.flab $top.fname -sticky w
5656 frame $top.buts
5657 button $top.buts.gen -text "Write" -command wrcomgo
5658 button $top.buts.can -text "Cancel" -command wrcomcan
5659 grid $top.buts.gen $top.buts.can
5660 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5661 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5662 grid $top.buts - -pady 10 -sticky ew
5663 focus $top.fname
5664}
5665
5666proc wrcomgo {} {
5667 global wrcomtop
5668
5669 set id [$wrcomtop.sha1 get]
5670 set cmd "echo $id | [$wrcomtop.cmd get]"
5671 set fname [$wrcomtop.fname get]
5672 if {[catch {exec sh -c $cmd >$fname &} err]} {
5673 error_popup "Error writing commit: $err"
5674 }
5675 catch {destroy $wrcomtop}
5676 unset wrcomtop
5677}
5678
5679proc wrcomcan {} {
5680 global wrcomtop
5681
5682 catch {destroy $wrcomtop}
5683 unset wrcomtop
5684}
5685
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005686proc mkbranch {} {
5687 global rowmenuid mkbrtop
5688
5689 set top .makebranch
5690 catch {destroy $top}
5691 toplevel $top
5692 label $top.title -text "Create new branch"
5693 grid $top.title - -pady 10
5694 label $top.id -text "ID:"
5695 entry $top.sha1 -width 40 -relief flat
5696 $top.sha1 insert 0 $rowmenuid
5697 $top.sha1 conf -state readonly
5698 grid $top.id $top.sha1 -sticky w
5699 label $top.nlab -text "Name:"
5700 entry $top.name -width 40
5701 grid $top.nlab $top.name -sticky w
5702 frame $top.buts
5703 button $top.buts.go -text "Create" -command [list mkbrgo $top]
5704 button $top.buts.can -text "Cancel" -command "catch {destroy $top}"
5705 grid $top.buts.go $top.buts.can
5706 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5707 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5708 grid $top.buts - -pady 10 -sticky ew
5709 focus $top.name
5710}
5711
5712proc mkbrgo {top} {
5713 global headids idheads
5714
5715 set name [$top.name get]
5716 set id [$top.sha1 get]
5717 if {$name eq {}} {
5718 error_popup "Please specify a name for the new branch"
5719 return
5720 }
5721 catch {destroy $top}
5722 nowbusy newbranch
5723 update
5724 if {[catch {
5725 exec git branch $name $id
5726 } err]} {
5727 notbusy newbranch
5728 error_popup $err
5729 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005730 set headids($name) $id
5731 lappend idheads($id) $name
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005732 addedhead $id $name
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005733 notbusy newbranch
5734 redrawtags $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10005735 dispneartags 0
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005736 }
5737}
5738
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005739proc cherrypick {} {
5740 global rowmenuid curview commitrow
Paul Mackerrase11f1232007-06-16 20:29:25 +10005741 global mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005742
Paul Mackerrase11f1232007-06-16 20:29:25 +10005743 set oldhead [exec git rev-parse HEAD]
5744 set dheads [descheads $rowmenuid]
5745 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005746 set ok [confirm_popup "Commit [string range $rowmenuid 0 7] is already\
5747 included in branch $mainhead -- really re-apply it?"]
5748 if {!$ok} return
5749 }
5750 nowbusy cherrypick
5751 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005752 # Unfortunately git-cherry-pick writes stuff to stderr even when
5753 # no error occurs, and exec takes that as an indication of error...
5754 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
5755 notbusy cherrypick
5756 error_popup $err
5757 return
5758 }
5759 set newhead [exec git rev-parse HEAD]
5760 if {$newhead eq $oldhead} {
5761 notbusy cherrypick
5762 error_popup "No changes committed"
5763 return
5764 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005765 addnewchild $newhead $oldhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005766 if {[info exists commitrow($curview,$oldhead)]} {
5767 insertrow $commitrow($curview,$oldhead) $newhead
5768 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005769 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005770 movedhead $newhead $mainhead
5771 }
5772 redrawtags $oldhead
5773 redrawtags $newhead
5774 }
5775 notbusy cherrypick
5776}
5777
Paul Mackerras10299152006-08-02 09:52:01 +10005778# context menu for a head
5779proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10005780 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10005781
5782 set headmenuid $id
5783 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10005784 set state normal
5785 if {$head eq $mainhead} {
5786 set state disabled
5787 }
5788 $headctxmenu entryconfigure 0 -state $state
5789 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10005790 tk_popup $headctxmenu $x $y
5791}
5792
5793proc cobranch {} {
5794 global headmenuid headmenuhead mainhead headids
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005795 global showlocalchanges mainheadid
Paul Mackerras10299152006-08-02 09:52:01 +10005796
5797 # check the tree is clean first??
5798 set oldmainhead $mainhead
5799 nowbusy checkout
5800 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005801 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10005802 if {[catch {
Paul Mackerras696cf492007-05-22 09:52:00 +10005803 exec git checkout -q $headmenuhead
Paul Mackerras10299152006-08-02 09:52:01 +10005804 } err]} {
5805 notbusy checkout
5806 error_popup $err
5807 } else {
5808 notbusy checkout
Paul Mackerras53cda8d2006-08-02 19:43:34 +10005809 set mainhead $headmenuhead
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005810 set mainheadid $headmenuid
Paul Mackerras10299152006-08-02 09:52:01 +10005811 if {[info exists headids($oldmainhead)]} {
5812 redrawtags $headids($oldmainhead)
5813 }
5814 redrawtags $headmenuid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005815 if {$showlocalchanges} {
5816 dodiffindex
5817 }
Paul Mackerras10299152006-08-02 09:52:01 +10005818 }
5819}
5820
5821proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005822 global headmenuid headmenuhead mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10005823 global headids idheads
5824
5825 set head $headmenuhead
5826 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10005827 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10005828 if {$head eq $mainhead} {
5829 error_popup "Cannot delete the currently checked-out branch"
5830 return
5831 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005832 set dheads [descheads $id]
5833 if {$dheads eq $headids($head)} {
Paul Mackerras10299152006-08-02 09:52:01 +10005834 # the stuff on this branch isn't on any other branch
5835 if {![confirm_popup "The commits on branch $head aren't on any other\
5836 branch.\nReally delete branch $head?"]} return
5837 }
5838 nowbusy rmbranch
5839 update
5840 if {[catch {exec git branch -D $head} err]} {
5841 notbusy rmbranch
5842 error_popup $err
5843 return
5844 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005845 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005846 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10005847 redrawtags $id
5848 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10005849 dispneartags 0
Paul Mackerras10299152006-08-02 09:52:01 +10005850}
5851
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005852# Stuff for finding nearby tags
5853proc getallcommits {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005854 global allcommits allids nbmp nextarc seeds
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005855
Paul Mackerrascec7bec2006-08-02 09:38:10 +10005856 set allids {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10005857 set nbmp 0
5858 set nextarc 0
5859 set allcommits 0
5860 set seeds {}
5861 regetallcommits
5862}
5863
5864# Called when the graph might have changed
5865proc regetallcommits {} {
5866 global allcommits seeds
5867
5868 set cmd [concat | git rev-list --all --parents]
5869 foreach id $seeds {
5870 lappend cmd "^$id"
5871 }
5872 set fd [open $cmd r]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005873 fconfigure $fd -blocking 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10005874 incr allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005875 nowbusy allcommits
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005876 filerun $fd [list getallclines $fd]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005877}
5878
Paul Mackerrase11f1232007-06-16 20:29:25 +10005879# Since most commits have 1 parent and 1 child, we group strings of
5880# such commits into "arcs" joining branch/merge points (BMPs), which
5881# are commits that either don't have 1 parent or don't have 1 child.
5882#
5883# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
5884# arcout(id) - outgoing arcs for BMP
5885# arcids(a) - list of IDs on arc including end but not start
5886# arcstart(a) - BMP ID at start of arc
5887# arcend(a) - BMP ID at end of arc
5888# growing(a) - arc a is still growing
5889# arctags(a) - IDs out of arcids (excluding end) that have tags
5890# archeads(a) - IDs out of arcids (excluding end) that have heads
5891# The start of an arc is at the descendent end, so "incoming" means
5892# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10005893
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005894proc getallclines {fd} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005895 global allids allparents allchildren idtags nextarc nbmp
5896 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005897 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005898
Paul Mackerrase11f1232007-06-16 20:29:25 +10005899 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005900 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005901 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10005902 if {[info exists allparents($id)]} {
5903 # seen it already
5904 continue
5905 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005906 lappend allids $id
5907 set olds [lrange $line 1 end]
5908 set allparents($id) $olds
5909 if {![info exists allchildren($id)]} {
5910 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10005911 set arcnos($id) {}
5912 lappend seeds $id
5913 } else {
5914 set a $arcnos($id)
5915 if {[llength $olds] == 1 && [llength $a] == 1} {
5916 lappend arcids($a) $id
5917 if {[info exists idtags($id)]} {
5918 lappend arctags($a) $id
5919 }
5920 if {[info exists idheads($id)]} {
5921 lappend archeads($a) $id
5922 }
5923 if {[info exists allparents($olds)]} {
5924 # seen parent already
5925 if {![info exists arcout($olds)]} {
5926 splitarc $olds
5927 }
5928 lappend arcids($a) $olds
5929 set arcend($a) $olds
5930 unset growing($a)
5931 }
5932 lappend allchildren($olds) $id
5933 lappend arcnos($olds) $a
5934 continue
5935 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005936 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005937 incr nbmp
5938 foreach a $arcnos($id) {
5939 lappend arcids($a) $id
5940 set arcend($a) $id
5941 unset growing($a)
5942 }
5943
5944 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005945 foreach p $olds {
5946 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10005947 set a [incr nextarc]
5948 set arcstart($a) $id
5949 set archeads($a) {}
5950 set arctags($a) {}
5951 set archeads($a) {}
5952 set arcids($a) {}
5953 lappend ao $a
5954 set growing($a) 1
5955 if {[info exists allparents($p)]} {
5956 # seen it already, may need to make a new branch
5957 if {![info exists arcout($p)]} {
5958 splitarc $p
5959 }
5960 lappend arcids($a) $p
5961 set arcend($a) $p
5962 unset growing($a)
5963 }
5964 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005965 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005966 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005967 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005968 if {![eof $fd]} {
5969 return [expr {$nid >= 1000? 2: 1}]
5970 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005971 close $fd
5972 if {[incr allcommits -1] == 0} {
5973 notbusy allcommits
5974 }
5975 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005976 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10005977}
5978
5979proc recalcarc {a} {
5980 global arctags archeads arcids idtags idheads
5981
5982 set at {}
5983 set ah {}
5984 foreach id [lrange $arcids($a) 0 end-1] {
5985 if {[info exists idtags($id)]} {
5986 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005987 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005988 if {[info exists idheads($id)]} {
5989 lappend ah $id
5990 }
5991 }
5992 set arctags($a) $at
5993 set archeads($a) $ah
5994}
5995
5996proc splitarc {p} {
5997 global arcnos arcids nextarc nbmp arctags archeads idtags idheads
5998 global arcstart arcend arcout allparents growing
5999
6000 set a $arcnos($p)
6001 if {[llength $a] != 1} {
6002 puts "oops splitarc called but [llength $a] arcs already"
6003 return
6004 }
6005 set a [lindex $a 0]
6006 set i [lsearch -exact $arcids($a) $p]
6007 if {$i < 0} {
6008 puts "oops splitarc $p not in arc $a"
6009 return
6010 }
6011 set na [incr nextarc]
6012 if {[info exists arcend($a)]} {
6013 set arcend($na) $arcend($a)
6014 } else {
6015 set l [lindex $allparents([lindex $arcids($a) end]) 0]
6016 set j [lsearch -exact $arcnos($l) $a]
6017 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
6018 }
6019 set tail [lrange $arcids($a) [expr {$i+1}] end]
6020 set arcids($a) [lrange $arcids($a) 0 $i]
6021 set arcend($a) $p
6022 set arcstart($na) $p
6023 set arcout($p) $na
6024 set arcids($na) $tail
6025 if {[info exists growing($a)]} {
6026 set growing($na) 1
6027 unset growing($a)
6028 }
6029 incr nbmp
6030
6031 foreach id $tail {
6032 if {[llength $arcnos($id)] == 1} {
6033 set arcnos($id) $na
6034 } else {
6035 set j [lsearch -exact $arcnos($id) $a]
6036 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
6037 }
6038 }
6039
6040 # reconstruct tags and heads lists
6041 if {$arctags($a) ne {} || $archeads($a) ne {}} {
6042 recalcarc $a
6043 recalcarc $na
6044 } else {
6045 set arctags($na) {}
6046 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006047 }
6048}
6049
Paul Mackerrase11f1232007-06-16 20:29:25 +10006050# Update things for a new commit added that is a child of one
6051# existing commit. Used when cherry-picking.
6052proc addnewchild {id p} {
6053 global allids allparents allchildren idtags nextarc nbmp
6054 global arcnos arcids arctags arcout arcend arcstart archeads growing
6055 global seeds
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006056
Paul Mackerrase11f1232007-06-16 20:29:25 +10006057 lappend allids $id
6058 set allparents($id) [list $p]
6059 set allchildren($id) {}
6060 set arcnos($id) {}
6061 lappend seeds $id
6062 incr nbmp
6063 lappend allchildren($p) $id
6064 set a [incr nextarc]
6065 set arcstart($a) $id
6066 set archeads($a) {}
6067 set arctags($a) {}
6068 set arcids($a) [list $p]
6069 set arcend($a) $p
6070 if {![info exists arcout($p)]} {
6071 splitarc $p
6072 }
6073 lappend arcnos($p) $a
6074 set arcout($id) [list $a]
6075}
6076
6077# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
6078# or 0 if neither is true.
6079proc anc_or_desc {a b} {
6080 global arcout arcstart arcend arcnos cached_isanc
6081
6082 if {$arcnos($a) eq $arcnos($b)} {
6083 # Both are on the same arc(s); either both are the same BMP,
6084 # or if one is not a BMP, the other is also not a BMP or is
6085 # the BMP at end of the arc (and it only has 1 incoming arc).
6086 if {$a eq $b} {
6087 return 0
6088 }
6089 # assert {[llength $arcnos($a)] == 1}
6090 set arc [lindex $arcnos($a) 0]
6091 set i [lsearch -exact $arcids($arc) $a]
6092 set j [lsearch -exact $arcids($arc) $b]
6093 if {$i < 0 || $i > $j} {
6094 return 1
6095 } else {
6096 return -1
6097 }
6098 }
6099
6100 if {![info exists arcout($a)]} {
6101 set arc [lindex $arcnos($a) 0]
6102 if {[info exists arcend($arc)]} {
6103 set aend $arcend($arc)
6104 } else {
6105 set aend {}
6106 }
6107 set a $arcstart($arc)
6108 } else {
6109 set aend $a
6110 }
6111 if {![info exists arcout($b)]} {
6112 set arc [lindex $arcnos($b) 0]
6113 if {[info exists arcend($arc)]} {
6114 set bend $arcend($arc)
6115 } else {
6116 set bend {}
6117 }
6118 set b $arcstart($arc)
6119 } else {
6120 set bend $b
6121 }
6122 if {$a eq $bend} {
6123 return 1
6124 }
6125 if {$b eq $aend} {
6126 return -1
6127 }
6128 if {[info exists cached_isanc($a,$bend)]} {
6129 if {$cached_isanc($a,$bend)} {
6130 return 1
6131 }
6132 }
6133 if {[info exists cached_isanc($b,$aend)]} {
6134 if {$cached_isanc($b,$aend)} {
6135 return -1
6136 }
6137 if {[info exists cached_isanc($a,$bend)]} {
6138 return 0
6139 }
6140 }
6141
6142 set todo [list $a $b]
6143 set anc($a) a
6144 set anc($b) b
6145 for {set i 0} {$i < [llength $todo]} {incr i} {
6146 set x [lindex $todo $i]
6147 if {$anc($x) eq {}} {
6148 continue
6149 }
6150 foreach arc $arcnos($x) {
6151 set xd $arcstart($arc)
6152 if {$xd eq $bend} {
6153 set cached_isanc($a,$bend) 1
6154 set cached_isanc($b,$aend) 0
6155 return 1
6156 } elseif {$xd eq $aend} {
6157 set cached_isanc($b,$aend) 1
6158 set cached_isanc($a,$bend) 0
6159 return -1
6160 }
6161 if {![info exists anc($xd)]} {
6162 set anc($xd) $anc($x)
6163 lappend todo $xd
6164 } elseif {$anc($xd) ne $anc($x)} {
6165 set anc($xd) {}
6166 }
6167 }
6168 }
6169 set cached_isanc($a,$bend) 0
6170 set cached_isanc($b,$aend) 0
6171 return 0
6172}
6173
6174# This identifies whether $desc has an ancestor that is
6175# a growing tip of the graph and which is not an ancestor of $anc
6176# and returns 0 if so and 1 if not.
6177# If we subsequently discover a tag on such a growing tip, and that
6178# turns out to be a descendent of $anc (which it could, since we
6179# don't necessarily see children before parents), then $desc
6180# isn't a good choice to display as a descendent tag of
6181# $anc (since it is the descendent of another tag which is
6182# a descendent of $anc). Similarly, $anc isn't a good choice to
6183# display as a ancestor tag of $desc.
6184#
6185proc is_certain {desc anc} {
6186 global arcnos arcout arcstart arcend growing problems
6187
6188 set certain {}
6189 if {[llength $arcnos($anc)] == 1} {
6190 # tags on the same arc are certain
6191 if {$arcnos($desc) eq $arcnos($anc)} {
6192 return 1
6193 }
6194 if {![info exists arcout($anc)]} {
6195 # if $anc is partway along an arc, use the start of the arc instead
6196 set a [lindex $arcnos($anc) 0]
6197 set anc $arcstart($a)
6198 }
6199 }
6200 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
6201 set x $desc
6202 } else {
6203 set a [lindex $arcnos($desc) 0]
6204 set x $arcend($a)
6205 }
6206 if {$x == $anc} {
6207 return 1
6208 }
6209 set anclist [list $x]
6210 set dl($x) 1
6211 set nnh 1
6212 set ngrowanc 0
6213 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
6214 set x [lindex $anclist $i]
6215 if {$dl($x)} {
6216 incr nnh -1
6217 }
6218 set done($x) 1
6219 foreach a $arcout($x) {
6220 if {[info exists growing($a)]} {
6221 if {![info exists growanc($x)] && $dl($x)} {
6222 set growanc($x) 1
6223 incr ngrowanc
6224 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006225 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006226 set y $arcend($a)
6227 if {[info exists dl($y)]} {
6228 if {$dl($y)} {
6229 if {!$dl($x)} {
6230 set dl($y) 0
6231 if {![info exists done($y)]} {
6232 incr nnh -1
6233 }
6234 if {[info exists growanc($x)]} {
6235 incr ngrowanc -1
6236 }
6237 set xl [list $y]
6238 for {set k 0} {$k < [llength $xl]} {incr k} {
6239 set z [lindex $xl $k]
6240 foreach c $arcout($z) {
6241 if {[info exists arcend($c)]} {
6242 set v $arcend($c)
6243 if {[info exists dl($v)] && $dl($v)} {
6244 set dl($v) 0
6245 if {![info exists done($v)]} {
6246 incr nnh -1
6247 }
6248 if {[info exists growanc($v)]} {
6249 incr ngrowanc -1
6250 }
6251 lappend xl $v
6252 }
6253 }
6254 }
6255 }
6256 }
6257 }
6258 } elseif {$y eq $anc || !$dl($x)} {
6259 set dl($y) 0
6260 lappend anclist $y
6261 } else {
6262 set dl($y) 1
6263 lappend anclist $y
6264 incr nnh
6265 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006266 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006267 }
6268 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006269 foreach x [array names growanc] {
6270 if {$dl($x)} {
6271 return 0
6272 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006273 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006274 }
6275 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006276}
6277
Paul Mackerrase11f1232007-06-16 20:29:25 +10006278proc validate_arctags {a} {
6279 global arctags idtags
6280
6281 set i -1
6282 set na $arctags($a)
6283 foreach id $arctags($a) {
6284 incr i
6285 if {![info exists idtags($id)]} {
6286 set na [lreplace $na $i $i]
6287 incr i -1
6288 }
6289 }
6290 set arctags($a) $na
6291}
6292
6293proc validate_archeads {a} {
6294 global archeads idheads
6295
6296 set i -1
6297 set na $archeads($a)
6298 foreach id $archeads($a) {
6299 incr i
6300 if {![info exists idheads($id)]} {
6301 set na [lreplace $na $i $i]
6302 incr i -1
6303 }
6304 }
6305 set archeads($a) $na
6306}
6307
6308# Return the list of IDs that have tags that are descendents of id,
6309# ignoring IDs that are descendents of IDs already reported.
6310proc desctags {id} {
6311 global arcnos arcstart arcids arctags idtags allparents
6312 global growing cached_dtags
6313
6314 if {![info exists allparents($id)]} {
6315 return {}
6316 }
6317 set t1 [clock clicks -milliseconds]
6318 set argid $id
6319 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6320 # part-way along an arc; check that arc first
6321 set a [lindex $arcnos($id) 0]
6322 if {$arctags($a) ne {}} {
6323 validate_arctags $a
6324 set i [lsearch -exact $arcids($a) $id]
6325 set tid {}
6326 foreach t $arctags($a) {
6327 set j [lsearch -exact $arcids($a) $t]
6328 if {$j >= $i} break
6329 set tid $t
6330 }
6331 if {$tid ne {}} {
6332 return $tid
6333 }
6334 }
6335 set id $arcstart($a)
6336 if {[info exists idtags($id)]} {
6337 return $id
6338 }
6339 }
6340 if {[info exists cached_dtags($id)]} {
6341 return $cached_dtags($id)
6342 }
6343
6344 set origid $id
6345 set todo [list $id]
6346 set queued($id) 1
6347 set nc 1
6348 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
6349 set id [lindex $todo $i]
6350 set done($id) 1
6351 set ta [info exists hastaggedancestor($id)]
6352 if {!$ta} {
6353 incr nc -1
6354 }
6355 # ignore tags on starting node
6356 if {!$ta && $i > 0} {
6357 if {[info exists idtags($id)]} {
6358 set tagloc($id) $id
6359 set ta 1
6360 } elseif {[info exists cached_dtags($id)]} {
6361 set tagloc($id) $cached_dtags($id)
6362 set ta 1
6363 }
6364 }
6365 foreach a $arcnos($id) {
6366 set d $arcstart($a)
6367 if {!$ta && $arctags($a) ne {}} {
6368 validate_arctags $a
6369 if {$arctags($a) ne {}} {
6370 lappend tagloc($id) [lindex $arctags($a) end]
6371 }
6372 }
6373 if {$ta || $arctags($a) ne {}} {
6374 set tomark [list $d]
6375 for {set j 0} {$j < [llength $tomark]} {incr j} {
6376 set dd [lindex $tomark $j]
6377 if {![info exists hastaggedancestor($dd)]} {
6378 if {[info exists done($dd)]} {
6379 foreach b $arcnos($dd) {
6380 lappend tomark $arcstart($b)
6381 }
6382 if {[info exists tagloc($dd)]} {
6383 unset tagloc($dd)
6384 }
6385 } elseif {[info exists queued($dd)]} {
6386 incr nc -1
6387 }
6388 set hastaggedancestor($dd) 1
6389 }
6390 }
6391 }
6392 if {![info exists queued($d)]} {
6393 lappend todo $d
6394 set queued($d) 1
6395 if {![info exists hastaggedancestor($d)]} {
6396 incr nc
6397 }
6398 }
6399 }
6400 }
6401 set tags {}
6402 foreach id [array names tagloc] {
6403 if {![info exists hastaggedancestor($id)]} {
6404 foreach t $tagloc($id) {
6405 if {[lsearch -exact $tags $t] < 0} {
6406 lappend tags $t
6407 }
6408 }
6409 }
6410 }
6411 set t2 [clock clicks -milliseconds]
6412 set loopix $i
6413
6414 # remove tags that are descendents of other tags
6415 for {set i 0} {$i < [llength $tags]} {incr i} {
6416 set a [lindex $tags $i]
6417 for {set j 0} {$j < $i} {incr j} {
6418 set b [lindex $tags $j]
6419 set r [anc_or_desc $a $b]
6420 if {$r == 1} {
6421 set tags [lreplace $tags $j $j]
6422 incr j -1
6423 incr i -1
6424 } elseif {$r == -1} {
6425 set tags [lreplace $tags $i $i]
6426 incr i -1
6427 break
6428 }
6429 }
6430 }
6431
6432 if {[array names growing] ne {}} {
6433 # graph isn't finished, need to check if any tag could get
6434 # eclipsed by another tag coming later. Simply ignore any
6435 # tags that could later get eclipsed.
6436 set ctags {}
6437 foreach t $tags {
6438 if {[is_certain $t $origid]} {
6439 lappend ctags $t
6440 }
6441 }
6442 if {$tags eq $ctags} {
6443 set cached_dtags($origid) $tags
6444 } else {
6445 set tags $ctags
6446 }
6447 } else {
6448 set cached_dtags($origid) $tags
6449 }
6450 set t3 [clock clicks -milliseconds]
6451 if {0 && $t3 - $t1 >= 100} {
6452 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
6453 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
6454 }
6455 return $tags
6456}
6457
6458proc anctags {id} {
6459 global arcnos arcids arcout arcend arctags idtags allparents
6460 global growing cached_atags
6461
6462 if {![info exists allparents($id)]} {
6463 return {}
6464 }
6465 set t1 [clock clicks -milliseconds]
6466 set argid $id
6467 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6468 # part-way along an arc; check that arc first
6469 set a [lindex $arcnos($id) 0]
6470 if {$arctags($a) ne {}} {
6471 validate_arctags $a
6472 set i [lsearch -exact $arcids($a) $id]
6473 foreach t $arctags($a) {
6474 set j [lsearch -exact $arcids($a) $t]
6475 if {$j > $i} {
6476 return $t
6477 }
6478 }
6479 }
6480 if {![info exists arcend($a)]} {
6481 return {}
6482 }
6483 set id $arcend($a)
6484 if {[info exists idtags($id)]} {
6485 return $id
6486 }
6487 }
6488 if {[info exists cached_atags($id)]} {
6489 return $cached_atags($id)
6490 }
6491
6492 set origid $id
6493 set todo [list $id]
6494 set queued($id) 1
6495 set taglist {}
6496 set nc 1
6497 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
6498 set id [lindex $todo $i]
6499 set done($id) 1
6500 set td [info exists hastaggeddescendent($id)]
6501 if {!$td} {
6502 incr nc -1
6503 }
6504 # ignore tags on starting node
6505 if {!$td && $i > 0} {
6506 if {[info exists idtags($id)]} {
6507 set tagloc($id) $id
6508 set td 1
6509 } elseif {[info exists cached_atags($id)]} {
6510 set tagloc($id) $cached_atags($id)
6511 set td 1
6512 }
6513 }
6514 foreach a $arcout($id) {
6515 if {!$td && $arctags($a) ne {}} {
6516 validate_arctags $a
6517 if {$arctags($a) ne {}} {
6518 lappend tagloc($id) [lindex $arctags($a) 0]
6519 }
6520 }
6521 if {![info exists arcend($a)]} continue
6522 set d $arcend($a)
6523 if {$td || $arctags($a) ne {}} {
6524 set tomark [list $d]
6525 for {set j 0} {$j < [llength $tomark]} {incr j} {
6526 set dd [lindex $tomark $j]
6527 if {![info exists hastaggeddescendent($dd)]} {
6528 if {[info exists done($dd)]} {
6529 foreach b $arcout($dd) {
6530 if {[info exists arcend($b)]} {
6531 lappend tomark $arcend($b)
6532 }
6533 }
6534 if {[info exists tagloc($dd)]} {
6535 unset tagloc($dd)
6536 }
6537 } elseif {[info exists queued($dd)]} {
6538 incr nc -1
6539 }
6540 set hastaggeddescendent($dd) 1
6541 }
6542 }
6543 }
6544 if {![info exists queued($d)]} {
6545 lappend todo $d
6546 set queued($d) 1
6547 if {![info exists hastaggeddescendent($d)]} {
6548 incr nc
6549 }
6550 }
6551 }
6552 }
6553 set t2 [clock clicks -milliseconds]
6554 set loopix $i
6555 set tags {}
6556 foreach id [array names tagloc] {
6557 if {![info exists hastaggeddescendent($id)]} {
6558 foreach t $tagloc($id) {
6559 if {[lsearch -exact $tags $t] < 0} {
6560 lappend tags $t
6561 }
6562 }
6563 }
6564 }
6565
6566 # remove tags that are ancestors of other tags
6567 for {set i 0} {$i < [llength $tags]} {incr i} {
6568 set a [lindex $tags $i]
6569 for {set j 0} {$j < $i} {incr j} {
6570 set b [lindex $tags $j]
6571 set r [anc_or_desc $a $b]
6572 if {$r == -1} {
6573 set tags [lreplace $tags $j $j]
6574 incr j -1
6575 incr i -1
6576 } elseif {$r == 1} {
6577 set tags [lreplace $tags $i $i]
6578 incr i -1
6579 break
6580 }
6581 }
6582 }
6583
6584 if {[array names growing] ne {}} {
6585 # graph isn't finished, need to check if any tag could get
6586 # eclipsed by another tag coming later. Simply ignore any
6587 # tags that could later get eclipsed.
6588 set ctags {}
6589 foreach t $tags {
6590 if {[is_certain $origid $t]} {
6591 lappend ctags $t
6592 }
6593 }
6594 if {$tags eq $ctags} {
6595 set cached_atags($origid) $tags
6596 } else {
6597 set tags $ctags
6598 }
6599 } else {
6600 set cached_atags($origid) $tags
6601 }
6602 set t3 [clock clicks -milliseconds]
6603 if {0 && $t3 - $t1 >= 100} {
6604 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
6605 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
6606 }
6607 return $tags
6608}
6609
6610# Return the list of IDs that have heads that are descendents of id,
6611# including id itself if it has a head.
6612proc descheads {id} {
6613 global arcnos arcstart arcids archeads idheads cached_dheads
6614 global allparents
6615
6616 if {![info exists allparents($id)]} {
6617 return {}
6618 }
6619 set ret {}
6620 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6621 # part-way along an arc; check it first
6622 set a [lindex $arcnos($id) 0]
6623 if {$archeads($a) ne {}} {
6624 validate_archeads $a
6625 set i [lsearch -exact $arcids($a) $id]
6626 foreach t $archeads($a) {
6627 set j [lsearch -exact $arcids($a) $t]
6628 if {$j > $i} break
6629 lappend $ret $t
6630 }
6631 }
6632 set id $arcstart($a)
6633 }
6634 set origid $id
6635 set todo [list $id]
6636 set seen($id) 1
6637 for {set i 0} {$i < [llength $todo]} {incr i} {
6638 set id [lindex $todo $i]
6639 if {[info exists cached_dheads($id)]} {
6640 set ret [concat $ret $cached_dheads($id)]
6641 } else {
6642 if {[info exists idheads($id)]} {
6643 lappend ret $id
6644 }
6645 foreach a $arcnos($id) {
6646 if {$archeads($a) ne {}} {
6647 set ret [concat $ret $archeads($a)]
6648 }
6649 set d $arcstart($a)
6650 if {![info exists seen($d)]} {
6651 lappend todo $d
6652 set seen($d) 1
6653 }
6654 }
6655 }
6656 }
6657 set ret [lsort -unique $ret]
6658 set cached_dheads($origid) $ret
6659}
6660
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006661proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006662 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006663
Paul Mackerrase11f1232007-06-16 20:29:25 +10006664 if {![info exists arcnos($id)]} return
6665 if {![info exists arcout($id)]} {
6666 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006667 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006668 catch {unset cached_dtags}
6669 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +10006670}
6671
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006672proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006673 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006674
Paul Mackerrase11f1232007-06-16 20:29:25 +10006675 if {![info exists arcnos($hid)]} return
6676 if {![info exists arcout($hid)]} {
6677 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006678 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006679 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10006680}
6681
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006682proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006683 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006684
Paul Mackerrase11f1232007-06-16 20:29:25 +10006685 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +10006686}
6687
Paul Mackerrase11f1232007-06-16 20:29:25 +10006688proc movedhead {hid head} {
6689 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006690
Paul Mackerrase11f1232007-06-16 20:29:25 +10006691 if {![info exists arcnos($hid)]} return
6692 if {![info exists arcout($hid)]} {
6693 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006694 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006695 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006696}
6697
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006698proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006699 global cached_dheads cached_dtags cached_atags
6700 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006701
Paul Mackerrase11f1232007-06-16 20:29:25 +10006702 foreach id [concat [array names idheads] [array names idtags]] {
6703 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
6704 set a [lindex $arcnos($id) 0]
6705 if {![info exists donearc($a)]} {
6706 recalcarc $a
6707 set donearc($a) 1
6708 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006709 }
6710 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006711 catch {unset cached_dtags}
6712 catch {unset cached_atags}
6713 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006714}
6715
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006716proc rereadrefs {} {
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006717 global idtags idheads idotherrefs mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006718
6719 set refids [concat [array names idtags] \
6720 [array names idheads] [array names idotherrefs]]
6721 foreach id $refids {
6722 if {![info exists ref($id)]} {
6723 set ref($id) [listrefs $id]
6724 }
6725 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006726 set oldmainhead $mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006727 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006728 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006729 set refids [lsort -unique [concat $refids [array names idtags] \
6730 [array names idheads] [array names idotherrefs]]]
6731 foreach id $refids {
6732 set v [listrefs $id]
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006733 if {![info exists ref($id)] || $ref($id) != $v ||
6734 ($id eq $oldmainhead && $id ne $mainhead) ||
6735 ($id eq $mainhead && $id ne $oldmainhead)} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006736 redrawtags $id
6737 }
6738 }
6739}
6740
Junio C Hamano2e1ded42006-06-11 09:50:47 -07006741proc listrefs {id} {
6742 global idtags idheads idotherrefs
6743
6744 set x {}
6745 if {[info exists idtags($id)]} {
6746 set x $idtags($id)
6747 }
6748 set y {}
6749 if {[info exists idheads($id)]} {
6750 set y $idheads($id)
6751 }
6752 set z {}
6753 if {[info exists idotherrefs($id)]} {
6754 set z $idotherrefs($id)
6755 }
6756 return [list $x $y $z]
6757}
6758
Paul Mackerras106288c2005-08-19 23:11:39 +10006759proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10006760 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +10006761
6762 if {$isnew} {
6763 addtohistory [list showtag $tag 0]
6764 }
6765 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006766 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10006767 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +10006768 if {![info exists tagcontents($tag)]} {
6769 catch {
6770 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
6771 }
6772 }
Paul Mackerras106288c2005-08-19 23:11:39 +10006773 if {[info exists tagcontents($tag)]} {
6774 set text $tagcontents($tag)
6775 } else {
6776 set text "Tag: $tag\nId: $tagids($tag)"
6777 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006778 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +10006779 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006780 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +10006781}
6782
Paul Mackerras1d10f362005-05-15 12:55:47 +00006783proc doquit {} {
6784 global stopped
6785 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -05006786 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +00006787 destroy .
6788}
6789
Paul Mackerras712fcc02005-11-30 09:28:16 +11006790proc doprefs {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006791 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006792 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl60378c02007-05-20 12:12:48 -04006793 global bgcolor fgcolor ctext diffcolors selectbgcolor
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006794 global uifont tabstop
Paul Mackerras232475d2005-11-15 10:34:03 +11006795
Paul Mackerras712fcc02005-11-30 09:28:16 +11006796 set top .gitkprefs
6797 set prefstop $top
6798 if {[winfo exists $top]} {
6799 raise $top
6800 return
Paul Mackerras757f17b2005-11-21 09:56:07 +11006801 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006802 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11006803 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +11006804 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11006805 toplevel $top
6806 wm title $top "Gitk preferences"
6807 label $top.ldisp -text "Commit list display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006808 $top.ldisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11006809 grid $top.ldisp - -sticky w -pady 10
6810 label $top.spacer -text " "
6811 label $top.maxwidthl -text "Maximum graph width (lines)" \
6812 -font optionfont
6813 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
6814 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
6815 label $top.maxpctl -text "Maximum graph width (% of pane)" \
6816 -font optionfont
6817 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
6818 grid x $top.maxpctl $top.maxpct -sticky w
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006819 frame $top.showlocal
6820 label $top.showlocal.l -text "Show local changes" -font optionfont
6821 checkbutton $top.showlocal.b -variable showlocalchanges
6822 pack $top.showlocal.b $top.showlocal.l -side left
6823 grid x $top.showlocal -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006824
Paul Mackerras712fcc02005-11-30 09:28:16 +11006825 label $top.ddisp -text "Diff display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006826 $top.ddisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11006827 grid $top.ddisp - -sticky w -pady 10
6828 label $top.diffoptl -text "Options for diff program" \
6829 -font optionfont
6830 entry $top.diffopt -width 20 -textvariable diffopts
6831 grid x $top.diffoptl $top.diffopt -sticky w
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006832 frame $top.ntag
6833 label $top.ntag.l -text "Display nearby tags" -font optionfont
6834 checkbutton $top.ntag.b -variable showneartags
6835 pack $top.ntag.b $top.ntag.l -side left
6836 grid x $top.ntag -sticky w
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006837 label $top.tabstopl -text "tabstop" -font optionfont
6838 entry $top.tabstop -width 10 -textvariable tabstop
6839 grid x $top.tabstopl $top.tabstop -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006840
6841 label $top.cdisp -text "Colors: press to choose"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006842 $top.cdisp configure -font $uifont
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006843 grid $top.cdisp - -sticky w -pady 10
6844 label $top.bg -padx 40 -relief sunk -background $bgcolor
6845 button $top.bgbut -text "Background" -font optionfont \
6846 -command [list choosecolor bgcolor 0 $top.bg background setbg]
6847 grid x $top.bgbut $top.bg -sticky w
6848 label $top.fg -padx 40 -relief sunk -background $fgcolor
6849 button $top.fgbut -text "Foreground" -font optionfont \
6850 -command [list choosecolor fgcolor 0 $top.fg foreground setfg]
6851 grid x $top.fgbut $top.fg -sticky w
6852 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
6853 button $top.diffoldbut -text "Diff: old lines" -font optionfont \
6854 -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
6855 [list $ctext tag conf d0 -foreground]]
6856 grid x $top.diffoldbut $top.diffold -sticky w
6857 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
6858 button $top.diffnewbut -text "Diff: new lines" -font optionfont \
6859 -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
6860 [list $ctext tag conf d1 -foreground]]
6861 grid x $top.diffnewbut $top.diffnew -sticky w
6862 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
6863 button $top.hunksepbut -text "Diff: hunk header" -font optionfont \
6864 -command [list choosecolor diffcolors 2 $top.hunksep \
6865 "diff hunk header" \
6866 [list $ctext tag conf hunksep -foreground]]
6867 grid x $top.hunksepbut $top.hunksep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -04006868 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
6869 button $top.selbgbut -text "Select bg" -font optionfont \
6870 -command [list choosecolor selectbgcolor 0 $top.bg background setselbg]
6871 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006872
Paul Mackerras712fcc02005-11-30 09:28:16 +11006873 frame $top.buts
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04006874 button $top.buts.ok -text "OK" -command prefsok -default active
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006875 $top.buts.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04006876 button $top.buts.can -text "Cancel" -command prefscan -default normal
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04006877 $top.buts.can configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11006878 grid $top.buts.ok $top.buts.can
6879 grid columnconfigure $top.buts 0 -weight 1 -uniform a
6880 grid columnconfigure $top.buts 1 -weight 1 -uniform a
6881 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04006882 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +11006883}
6884
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006885proc choosecolor {v vi w x cmd} {
6886 global $v
6887
6888 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
6889 -title "Gitk: choose color for $x"]
6890 if {$c eq {}} return
6891 $w conf -background $c
6892 lset $v $vi $c
6893 eval $cmd $c
6894}
6895
Mark Levedahl60378c02007-05-20 12:12:48 -04006896proc setselbg {c} {
6897 global bglist cflist
6898 foreach w $bglist {
6899 $w configure -selectbackground $c
6900 }
6901 $cflist tag configure highlight \
6902 -background [$cflist cget -selectbackground]
6903 allcanvs itemconf secsel -fill $c
6904}
6905
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006906proc setbg {c} {
6907 global bglist
6908
6909 foreach w $bglist {
6910 $w conf -background $c
6911 }
6912}
6913
6914proc setfg {c} {
6915 global fglist canv
6916
6917 foreach w $fglist {
6918 $w conf -foreground $c
6919 }
6920 allcanvs itemconf text -fill $c
6921 $canv itemconf circle -outline $c
6922}
6923
Paul Mackerras712fcc02005-11-30 09:28:16 +11006924proc prefscan {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006925 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006926 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras712fcc02005-11-30 09:28:16 +11006927
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006928 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11006929 set $v $oldprefs($v)
6930 }
6931 catch {destroy $prefstop}
6932 unset prefstop
6933}
6934
6935proc prefsok {} {
6936 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006937 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006938 global charspc ctext tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11006939
6940 catch {destroy $prefstop}
6941 unset prefstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04006942 $ctext configure -tabs "[expr {$tabstop * $charspc}]"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006943 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
6944 if {$showlocalchanges} {
6945 doshowlocalchanges
6946 } else {
6947 dohidelocalchanges
6948 }
6949 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11006950 if {$maxwidth != $oldprefs(maxwidth)
6951 || $maxgraphpct != $oldprefs(maxgraphpct)} {
6952 redisplay
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006953 } elseif {$showneartags != $oldprefs(showneartags)} {
6954 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +11006955 }
6956}
6957
6958proc formatdate {d} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006959 if {$d ne {}} {
6960 set d [clock format $d -format "%Y-%m-%d %H:%M:%S"]
6961 }
6962 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +11006963}
6964
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11006965# This list of encoding names and aliases is distilled from
6966# http://www.iana.org/assignments/character-sets.
6967# Not all of them are supported by Tcl.
6968set encoding_aliases {
6969 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
6970 ISO646-US US-ASCII us IBM367 cp367 csASCII }
6971 { ISO-10646-UTF-1 csISO10646UTF1 }
6972 { ISO_646.basic:1983 ref csISO646basic1983 }
6973 { INVARIANT csINVARIANT }
6974 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
6975 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
6976 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
6977 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
6978 { NATS-DANO iso-ir-9-1 csNATSDANO }
6979 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
6980 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
6981 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
6982 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
6983 { ISO-2022-KR csISO2022KR }
6984 { EUC-KR csEUCKR }
6985 { ISO-2022-JP csISO2022JP }
6986 { ISO-2022-JP-2 csISO2022JP2 }
6987 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
6988 csISO13JISC6220jp }
6989 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
6990 { IT iso-ir-15 ISO646-IT csISO15Italian }
6991 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
6992 { ES iso-ir-17 ISO646-ES csISO17Spanish }
6993 { greek7-old iso-ir-18 csISO18Greek7Old }
6994 { latin-greek iso-ir-19 csISO19LatinGreek }
6995 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
6996 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
6997 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
6998 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
6999 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
7000 { BS_viewdata iso-ir-47 csISO47BSViewdata }
7001 { INIS iso-ir-49 csISO49INIS }
7002 { INIS-8 iso-ir-50 csISO50INIS8 }
7003 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
7004 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
7005 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
7006 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
7007 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
7008 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
7009 csISO60Norwegian1 }
7010 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
7011 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
7012 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
7013 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
7014 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
7015 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
7016 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
7017 { greek7 iso-ir-88 csISO88Greek7 }
7018 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
7019 { iso-ir-90 csISO90 }
7020 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
7021 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
7022 csISO92JISC62991984b }
7023 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
7024 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
7025 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
7026 csISO95JIS62291984handadd }
7027 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
7028 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
7029 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
7030 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
7031 CP819 csISOLatin1 }
7032 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
7033 { T.61-7bit iso-ir-102 csISO102T617bit }
7034 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
7035 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
7036 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
7037 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
7038 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
7039 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
7040 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
7041 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
7042 arabic csISOLatinArabic }
7043 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
7044 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
7045 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
7046 greek greek8 csISOLatinGreek }
7047 { T.101-G2 iso-ir-128 csISO128T101G2 }
7048 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
7049 csISOLatinHebrew }
7050 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
7051 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
7052 { CSN_369103 iso-ir-139 csISO139CSN369103 }
7053 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
7054 { ISO_6937-2-add iso-ir-142 csISOTextComm }
7055 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
7056 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
7057 csISOLatinCyrillic }
7058 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
7059 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
7060 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
7061 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
7062 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
7063 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
7064 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
7065 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
7066 { ISO_10367-box iso-ir-155 csISO10367Box }
7067 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
7068 { latin-lap lap iso-ir-158 csISO158Lap }
7069 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
7070 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
7071 { us-dk csUSDK }
7072 { dk-us csDKUS }
7073 { JIS_X0201 X0201 csHalfWidthKatakana }
7074 { KSC5636 ISO646-KR csKSC5636 }
7075 { ISO-10646-UCS-2 csUnicode }
7076 { ISO-10646-UCS-4 csUCS4 }
7077 { DEC-MCS dec csDECMCS }
7078 { hp-roman8 roman8 r8 csHPRoman8 }
7079 { macintosh mac csMacintosh }
7080 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
7081 csIBM037 }
7082 { IBM038 EBCDIC-INT cp038 csIBM038 }
7083 { IBM273 CP273 csIBM273 }
7084 { IBM274 EBCDIC-BE CP274 csIBM274 }
7085 { IBM275 EBCDIC-BR cp275 csIBM275 }
7086 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
7087 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
7088 { IBM280 CP280 ebcdic-cp-it csIBM280 }
7089 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
7090 { IBM284 CP284 ebcdic-cp-es csIBM284 }
7091 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
7092 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
7093 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
7094 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
7095 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
7096 { IBM424 cp424 ebcdic-cp-he csIBM424 }
7097 { IBM437 cp437 437 csPC8CodePage437 }
7098 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
7099 { IBM775 cp775 csPC775Baltic }
7100 { IBM850 cp850 850 csPC850Multilingual }
7101 { IBM851 cp851 851 csIBM851 }
7102 { IBM852 cp852 852 csPCp852 }
7103 { IBM855 cp855 855 csIBM855 }
7104 { IBM857 cp857 857 csIBM857 }
7105 { IBM860 cp860 860 csIBM860 }
7106 { IBM861 cp861 861 cp-is csIBM861 }
7107 { IBM862 cp862 862 csPC862LatinHebrew }
7108 { IBM863 cp863 863 csIBM863 }
7109 { IBM864 cp864 csIBM864 }
7110 { IBM865 cp865 865 csIBM865 }
7111 { IBM866 cp866 866 csIBM866 }
7112 { IBM868 CP868 cp-ar csIBM868 }
7113 { IBM869 cp869 869 cp-gr csIBM869 }
7114 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
7115 { IBM871 CP871 ebcdic-cp-is csIBM871 }
7116 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
7117 { IBM891 cp891 csIBM891 }
7118 { IBM903 cp903 csIBM903 }
7119 { IBM904 cp904 904 csIBBM904 }
7120 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
7121 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
7122 { IBM1026 CP1026 csIBM1026 }
7123 { EBCDIC-AT-DE csIBMEBCDICATDE }
7124 { EBCDIC-AT-DE-A csEBCDICATDEA }
7125 { EBCDIC-CA-FR csEBCDICCAFR }
7126 { EBCDIC-DK-NO csEBCDICDKNO }
7127 { EBCDIC-DK-NO-A csEBCDICDKNOA }
7128 { EBCDIC-FI-SE csEBCDICFISE }
7129 { EBCDIC-FI-SE-A csEBCDICFISEA }
7130 { EBCDIC-FR csEBCDICFR }
7131 { EBCDIC-IT csEBCDICIT }
7132 { EBCDIC-PT csEBCDICPT }
7133 { EBCDIC-ES csEBCDICES }
7134 { EBCDIC-ES-A csEBCDICESA }
7135 { EBCDIC-ES-S csEBCDICESS }
7136 { EBCDIC-UK csEBCDICUK }
7137 { EBCDIC-US csEBCDICUS }
7138 { UNKNOWN-8BIT csUnknown8BiT }
7139 { MNEMONIC csMnemonic }
7140 { MNEM csMnem }
7141 { VISCII csVISCII }
7142 { VIQR csVIQR }
7143 { KOI8-R csKOI8R }
7144 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
7145 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
7146 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
7147 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
7148 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
7149 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
7150 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
7151 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
7152 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
7153 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
7154 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
7155 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
7156 { IBM1047 IBM-1047 }
7157 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
7158 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
7159 { UNICODE-1-1 csUnicode11 }
7160 { CESU-8 csCESU-8 }
7161 { BOCU-1 csBOCU-1 }
7162 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
7163 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
7164 l8 }
7165 { ISO-8859-15 ISO_8859-15 Latin-9 }
7166 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
7167 { GBK CP936 MS936 windows-936 }
7168 { JIS_Encoding csJISEncoding }
7169 { Shift_JIS MS_Kanji csShiftJIS }
7170 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
7171 EUC-JP }
7172 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
7173 { ISO-10646-UCS-Basic csUnicodeASCII }
7174 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
7175 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
7176 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
7177 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
7178 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
7179 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
7180 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
7181 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
7182 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
7183 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
7184 { Adobe-Standard-Encoding csAdobeStandardEncoding }
7185 { Ventura-US csVenturaUS }
7186 { Ventura-International csVenturaInternational }
7187 { PC8-Danish-Norwegian csPC8DanishNorwegian }
7188 { PC8-Turkish csPC8Turkish }
7189 { IBM-Symbols csIBMSymbols }
7190 { IBM-Thai csIBMThai }
7191 { HP-Legal csHPLegal }
7192 { HP-Pi-font csHPPiFont }
7193 { HP-Math8 csHPMath8 }
7194 { Adobe-Symbol-Encoding csHPPSMath }
7195 { HP-DeskTop csHPDesktop }
7196 { Ventura-Math csVenturaMath }
7197 { Microsoft-Publishing csMicrosoftPublishing }
7198 { Windows-31J csWindows31J }
7199 { GB2312 csGB2312 }
7200 { Big5 csBig5 }
7201}
7202
7203proc tcl_encoding {enc} {
7204 global encoding_aliases
7205 set names [encoding names]
7206 set lcnames [string tolower $names]
7207 set enc [string tolower $enc]
7208 set i [lsearch -exact $lcnames $enc]
7209 if {$i < 0} {
7210 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
7211 if {[regsub {^iso[-_]} $enc iso encx]} {
7212 set i [lsearch -exact $lcnames $encx]
7213 }
7214 }
7215 if {$i < 0} {
7216 foreach l $encoding_aliases {
7217 set ll [string tolower $l]
7218 if {[lsearch -exact $ll $enc] < 0} continue
7219 # look through the aliases for one that tcl knows about
7220 foreach e $ll {
7221 set i [lsearch -exact $lcnames $e]
7222 if {$i < 0} {
7223 if {[regsub {^iso[-_]} $e iso ex]} {
7224 set i [lsearch -exact $lcnames $ex]
7225 }
7226 }
7227 if {$i >= 0} break
7228 }
7229 break
7230 }
7231 }
7232 if {$i >= 0} {
7233 return [lindex $names $i]
7234 }
7235 return {}
7236}
7237
Paul Mackerras1d10f362005-05-15 12:55:47 +00007238# defaults...
7239set datemode 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007240set diffopts "-U 5 -p"
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03007241set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -08007242
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007243set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -08007244catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +11007245 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -08007246}
7247if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007248 set gitencoding "utf-8"
7249}
7250set tclencoding [tcl_encoding $gitencoding]
7251if {$tclencoding == {}} {
7252 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -08007253}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007254
7255set mainfont {Helvetica 9}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007256set textfont {Courier 9}
Keith Packard4840be62006-04-04 00:19:45 -07007257set uifont {Helvetica 9 bold}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007258set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -04007259set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +10007260set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007261set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +11007262set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +11007263set fastdate 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007264set uparrowlen 7
7265set downarrowlen 7
7266set mingaplen 30
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007267set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007268set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007269set showneartags 1
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007270set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +10007271set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007272set showlocalchanges 1
Paul Mackerras1d10f362005-05-15 12:55:47 +00007273
7274set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007275set bgcolor white
7276set fgcolor black
7277set diffcolors {red "#00a000" blue}
Mark Levedahl60378c02007-05-20 12:12:48 -04007278set selectbgcolor gray85
Paul Mackerras1d10f362005-05-15 12:55:47 +00007279
7280catch {source ~/.gitk}
7281
Paul Mackerras712fcc02005-11-30 09:28:16 +11007282font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +00007283
Paul Mackerras1d10f362005-05-15 12:55:47 +00007284set revtreeargs {}
7285foreach arg $argv {
7286 switch -regexp -- $arg {
7287 "^$" { }
Paul Mackerras1d10f362005-05-15 12:55:47 +00007288 "^-d" { set datemode 1 }
Paul Mackerras1d10f362005-05-15 12:55:47 +00007289 default {
7290 lappend revtreeargs $arg
7291 }
7292 }
7293}
7294
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007295# check that we can find a .git directory somewhere...
7296set gitdir [gitdir]
7297if {![file isdirectory $gitdir]} {
Paul Mackerrase54be9e2006-05-26 22:34:30 +10007298 show_error {} . "Cannot find the git directory \"$gitdir\"."
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007299 exit 1
7300}
7301
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007302set cmdline_files {}
7303set i [lsearch -exact $revtreeargs "--"]
7304if {$i >= 0} {
7305 set cmdline_files [lrange $revtreeargs [expr {$i + 1}] end]
7306 set revtreeargs [lrange $revtreeargs 0 [expr {$i - 1}]]
7307} elseif {$revtreeargs ne {}} {
7308 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03007309 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007310 set cmdline_files [split $f "\n"]
7311 set n [llength $cmdline_files]
7312 set revtreeargs [lrange $revtreeargs 0 end-$n]
7313 } err]} {
7314 # unfortunately we get both stdout and stderr in $err,
7315 # so look for "fatal:".
7316 set i [string first "fatal:" $err]
7317 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -07007318 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007319 }
Paul Mackerrase54be9e2006-05-26 22:34:30 +10007320 show_error {} . "Bad arguments to gitk:\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007321 exit 1
7322 }
7323}
7324
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007325set nullid "0000000000000000000000000000000000000000"
7326
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007327set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007328set history {}
7329set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007330set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007331set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +10007332set highlight_paths {}
Paul Mackerras1902c272006-05-25 21:25:13 +10007333set searchdirn -forwards
Paul Mackerras4e7d6772006-05-30 21:33:07 +10007334set boldrows {}
7335set boldnamerows {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007336set diffelide {0 0}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007337
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007338set optim_delay 16
7339
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007340set nextviewnum 1
7341set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007342set selectedview 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007343set selectedhlview None
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007344set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007345set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007346set viewargs(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007347
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007348set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007349set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +00007350set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +10007351set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007352set lookingforhead 0
7353set localrow -1
7354set lserial 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007355setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007356makewindow
Doug Maxey6c283322006-12-10 14:31:46 -06007357wm title . "[file tail $argv0]: [file tail [pwd]]"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007358readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10007359
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007360if {$cmdline_files ne {} || $revtreeargs ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007361 # create a view for the files/dirs specified on the command line
7362 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007363 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007364 set nextviewnum 2
7365 set viewname(1) "Command line"
7366 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007367 set viewargs(1) $revtreeargs
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007368 set viewperm(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007369 addviewmenu 1
Paul Mackerras3cd204e2006-11-23 21:06:16 +11007370 .bar.view entryconf Edit* -state normal
7371 .bar.view entryconf Delete* -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007372}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007373
7374if {[info exists permviews]} {
7375 foreach v $permviews {
7376 set n $nextviewnum
7377 incr nextviewnum
7378 set viewname($n) [lindex $v 0]
7379 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007380 set viewargs($n) [lindex $v 2]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007381 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007382 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007383 }
7384}
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10007385getcommits