blob: 666a545751780a0d1e0a4c2136a28682e1e6eb8c [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 Mackerras9f1afe02006-02-19 22:44:47 +110090 set order "--topo-order"
91 if {$datemode} {
92 set order "--date-order"
93 }
Paul Mackerras418c4c72006-02-07 09:10:18 +110094 if {[catch {
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100095 set fd [open [concat | git log -z --pretty=raw $order --parents \
96 --boundary $viewargs($view) "--" $viewfiles($view)] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +110097 } err]} {
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100098 error_popup "Error executing git rev-list: $err"
Paul Mackerras38ad0912005-12-01 22:42:46 +110099 exit 1
100 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000101 set commfd($view) $fd
102 set leftover($view) {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000103 set lookingforhead $showlocalchanges
Mark Levedahl86da5b62007-07-17 18:42:04 -0400104 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100105 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000106 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100107 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000108 filerun $fd [list getcommitlines $fd $view]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000109 nowbusy $view
Paul Mackerras38ad0912005-12-01 22:42:46 +1100110}
111
Paul Mackerras22626ef2006-04-17 09:56:02 +1000112proc stop_rev_list {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000113 global commfd curview
Paul Mackerras22626ef2006-04-17 09:56:02 +1000114
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000115 if {![info exists commfd($curview)]} return
116 set fd $commfd($curview)
Paul Mackerras22626ef2006-04-17 09:56:02 +1000117 catch {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000118 set pid [pid $fd]
Paul Mackerras22626ef2006-04-17 09:56:02 +1000119 exec kill $pid
120 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000121 catch {close $fd}
122 unset commfd($curview)
Paul Mackerras22626ef2006-04-17 09:56:02 +1000123}
124
Paul Mackerrasa8aaf192006-04-23 22:45:55 +1000125proc getcommits {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000126 global phase canv mainfont curview
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100127
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100128 set phase getcommits
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000129 initlayout
130 start_rev_list $curview
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000131 show_status "Reading commits..."
Paul Mackerras1d10f362005-05-15 12:55:47 +0000132}
133
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000134proc getcommitlines {fd view} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000135 global commitlisted
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000136 global leftover commfd
Paul Mackerras8ed16482006-03-02 22:56:44 +1100137 global displayorder commitidx commitrow commitdata
Paul Mackerras6a90bff2007-06-18 09:48:23 +1000138 global parentlist children curview hlview
139 global vparentlist vdisporder vcmitlisted
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000140
Paul Mackerrasd1e46752006-08-16 20:02:32 +1000141 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +1000142 # git log doesn't terminate the last commit with a null...
143 if {$stuff == {} && $leftover($view) ne {} && [eof $fd]} {
144 set stuff "\0"
145 }
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 Mackerrasc961b222007-07-09 22:45:47 +1000197 if {$j >= 0 && [string match "commit *" $cmit]} {
198 set ids [string range $cmit 7 [expr {$j - 1}]]
199 if {[string match {[-<>]*} $ids]} {
200 switch -- [string index $ids 0] {
201 "-" {set listed 0}
202 "<" {set listed 2}
203 ">" {set listed 3}
204 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100205 set ids [string range $ids 1 end]
206 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000207 set ok 1
208 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100209 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000210 set ok 0
211 break
212 }
213 }
214 }
215 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +1000216 set shortcmit $cmit
217 if {[string length $shortcmit] > 80} {
218 set shortcmit "[string range $shortcmit 0 80]..."
219 }
Paul Mackerrasc961b222007-07-09 22:45:47 +1000220 error_popup "Can't parse git log output: {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +1000221 exit 1
222 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +1000223 set id [lindex $ids 0]
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100224 if {$listed} {
225 set olds [lrange $ids 1 end]
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000226 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +1000227 foreach p $olds {
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000228 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000229 lappend children($view,$p) $id
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000230 }
231 incr i
Paul Mackerras79b2c752006-04-02 20:47:40 +1000232 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +1100233 } else {
234 set olds {}
235 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000236 if {![info exists children($view,$id)]} {
237 set children($view,$id) {}
Paul Mackerras79b2c752006-04-02 20:47:40 +1000238 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100239 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000240 set commitrow($view,$id) $commitidx($view)
241 incr commitidx($view)
242 if {$view == $curview} {
243 lappend parentlist $olds
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000244 lappend displayorder $id
245 lappend commitlisted $listed
246 } else {
247 lappend vparentlist($view) $olds
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000248 lappend vdisporder($view) $id
249 lappend vcmitlisted($view) $listed
250 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100251 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100252 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100253 if {$gotsome} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000254 run chewcommits $view
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100255 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000256 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +0000257}
258
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000259proc chewcommits {view} {
260 global curview hlview commfd
261 global selectedline pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +0000262
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000263 set more 0
264 if {$view == $curview} {
265 set allread [expr {![info exists commfd($view)]}]
266 set tlimit [expr {[clock clicks -milliseconds] + 50}]
267 set more [layoutmore $tlimit $allread]
268 if {$allread && !$more} {
Paul Mackerras8f489362007-07-13 19:49:37 +1000269 global displayorder commitidx phase
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000270 global numcommits startmsecs
271
272 if {[info exists pending_select]} {
Paul Mackerras8f489362007-07-13 19:49:37 +1000273 set row [first_real_row]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000274 selectline $row 1
275 }
276 if {$commitidx($curview) > 0} {
277 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
278 #puts "overall $ms ms for $numcommits commits"
279 } else {
280 show_status "No commits selected"
281 }
282 notbusy layout
283 set phase {}
284 }
Paul Mackerrasb6645502005-08-11 09:56:23 +1000285 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000286 if {[info exists hlview] && $view == $hlview} {
287 vhighlightmore
Paul Mackerrasb6645502005-08-11 09:56:23 +1000288 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000289 return $more
Paul Mackerras1db95b02005-05-09 04:08:39 +0000290}
291
292proc readcommit {id} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300293 if {[catch {set contents [exec git cat-file commit $id]}]} return
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100294 parsecommit $id $contents 0
Paul Mackerrasb490a992005-06-22 10:25:38 +1000295}
296
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000297proc updatecommits {} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000298 global viewdata curview phase displayorder
Paul Mackerras908c3582006-05-20 09:38:11 +1000299 global children commitrow selectedline thickerline
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000300
Paul Mackerras22626ef2006-04-17 09:56:02 +1000301 if {$phase ne {}} {
302 stop_rev_list
303 set phase {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100304 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000305 set n $curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000306 foreach id $displayorder {
307 catch {unset children($n,$id)}
308 catch {unset commitrow($n,$id)}
309 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000310 set curview -1
Paul Mackerras908c3582006-05-20 09:38:11 +1000311 catch {unset selectedline}
312 catch {unset thickerline}
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000313 catch {unset viewdata($n)}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100314 readrefs
Paul Mackerrase11f1232007-06-16 20:29:25 +1000315 changedrefs
316 regetallcommits
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000317 showview $n
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100318}
319
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +1100320proc parsecommit {id contents listed} {
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100321 global commitinfo cdate
322
323 set inhdr 1
324 set comment {}
325 set headline {}
326 set auname {}
327 set audate {}
328 set comname {}
329 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +1100330 set hdrend [string first "\n\n" $contents]
331 if {$hdrend < 0} {
332 # should never happen...
333 set hdrend [string length $contents]
334 }
335 set header [string range $contents 0 [expr {$hdrend - 1}]]
336 set comment [string range $contents [expr {$hdrend + 2}] end]
337 foreach line [split $header "\n"] {
338 set tag [lindex $line 0]
339 if {$tag == "author"} {
340 set audate [lindex $line end-1]
341 set auname [lrange $line 1 end-2]
342 } elseif {$tag == "committer"} {
343 set comdate [lindex $line end-1]
344 set comname [lrange $line 1 end-2]
Paul Mackerras1db95b02005-05-09 04:08:39 +0000345 }
346 }
Paul Mackerras232475d2005-11-15 10:34:03 +1100347 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +1000348 # take the first non-blank line of the comment as the headline
349 set headline [string trimleft $comment]
350 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +1100351 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +1000352 set headline [string range $headline 0 $i]
353 }
354 set headline [string trimright $headline]
355 set i [string first "\r" $headline]
356 if {$i >= 0} {
357 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +1100358 }
359 if {!$listed} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +0300360 # git rev-list indents the comment by 4 spaces;
361 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +1100362 set newcomment {}
363 foreach line [split $comment "\n"] {
364 append newcomment " "
365 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +1100366 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +1100367 }
368 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +0000369 }
370 if {$comdate != {}} {
Paul Mackerrascfb45632005-05-31 12:14:42 +0000371 set cdate($id) $comdate
Paul Mackerras1db95b02005-05-09 04:08:39 +0000372 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +0000373 set commitinfo($id) [list $headline $auname $audate \
374 $comname $comdate $comment]
Paul Mackerras1db95b02005-05-09 04:08:39 +0000375}
376
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100377proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +1000378 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +1100379
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +1100380 if {[info exists commitdata($id)]} {
381 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +1100382 } else {
383 readcommit $id
384 if {![info exists commitinfo($id)]} {
385 set commitinfo($id) {"No commit information available"}
Paul Mackerras8ed16482006-03-02 22:56:44 +1100386 }
387 }
388 return 1
389}
390
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000391proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000392 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000393 global otherrefids idotherrefs mainhead mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000394
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100395 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
396 catch {unset $v}
397 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000398 set refd [open [list | git show-ref -d] r]
399 while {[gets $refd line] >= 0} {
400 if {[string index $line 40] ne " "} continue
401 set id [string range $line 0 39]
402 set ref [string range $line 41 end]
403 if {![string match "refs/*" $ref]} continue
404 set name [string range $ref 5 end]
405 if {[string match "remotes/*" $name]} {
406 if {![string match "*/HEAD" $name]} {
407 set headids($name) $id
408 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000409 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000410 } elseif {[string match "heads/*" $name]} {
411 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800412 set headids($name) $id
413 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +1000414 } elseif {[string match "tags/*" $name]} {
415 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
416 # which is what we want since the former is the commit ID
417 set name [string range $name 5 end]
418 if {[string match "*^{}" $name]} {
419 set name [string range $name 0 end-3]
420 } else {
421 set tagobjid($name) $id
422 }
423 set tagids($name) $id
424 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -0800425 } else {
426 set otherrefids($name) $id
427 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000428 }
429 }
Alex Riesen062d6712007-07-29 22:28:40 +0200430 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +1000431 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000432 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +1000433 catch {
434 set thehead [exec git symbolic-ref HEAD]
435 if {[string match "refs/heads/*" $thehead]} {
436 set mainhead [string range $thehead 11 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000437 if {[info exists headids($mainhead)]} {
438 set mainheadid $headids($mainhead)
439 }
Paul Mackerras8a485712006-07-06 10:21:23 +1000440 }
441 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000442}
443
Paul Mackerras8f489362007-07-13 19:49:37 +1000444# skip over fake commits
445proc first_real_row {} {
446 global nullid nullid2 displayorder numcommits
447
448 for {set row 0} {$row < $numcommits} {incr row} {
449 set id [lindex $displayorder $row]
450 if {$id ne $nullid && $id ne $nullid2} {
451 break
452 }
453 }
454 return $row
455}
456
Paul Mackerrase11f1232007-06-16 20:29:25 +1000457# update things for a head moved to a child of its previous location
458proc movehead {id name} {
459 global headids idheads
460
461 removehead $headids($name) $name
462 set headids($name) $id
463 lappend idheads($id) $name
464}
465
466# update things when a head has been removed
467proc removehead {id name} {
468 global headids idheads
469
470 if {$idheads($id) eq $name} {
471 unset idheads($id)
472 } else {
473 set i [lsearch -exact $idheads($id) $name]
474 if {$i >= 0} {
475 set idheads($id) [lreplace $idheads($id) $i $i]
476 }
477 }
478 unset headids($name)
479}
480
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000481proc show_error {w top msg} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000482 message $w.m -text $msg -justify center -aspect 400
483 pack $w.m -side top -fill x -padx 20 -pady 20
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000484 button $w.ok -text OK -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000485 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000486 bind $top <Visibility> "grab $top; focus $top"
487 bind $top <Key-Return> "destroy $top"
488 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000489}
490
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000491proc error_popup msg {
492 set w .error
493 toplevel $w
494 wm transient $w .
Paul Mackerrase54be9e2006-05-26 22:34:30 +1000495 show_error $w $w $msg
Paul Mackerras098dd8a2006-05-03 09:32:53 +1000496}
497
Paul Mackerras10299152006-08-02 09:52:01 +1000498proc confirm_popup msg {
499 global confirm_ok
500 set confirm_ok 0
501 set w .confirm
502 toplevel $w
503 wm transient $w .
504 message $w.m -text $msg -justify center -aspect 400
505 pack $w.m -side top -fill x -padx 20 -pady 20
506 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
507 pack $w.ok -side left -fill x
508 button $w.cancel -text Cancel -command "destroy $w"
509 pack $w.cancel -side right -fill x
510 bind $w <Visibility> "grab $w; focus $w"
511 tkwait window $w
512 return $confirm_ok
513}
514
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +1000515proc makewindow {} {
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +1000516 global canv canv2 canv3 linespc charspc ctext cflist
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400517 global textfont mainfont uifont tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400518 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000519 global entries sha1entry sha1string sha1but
Paul Mackerras94a2eed2005-08-07 15:27:57 +1000520 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000521 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000522 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000523 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -0400524 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Paul Mackerras10299152006-08-02 09:52:01 +1000525 global headctxmenu
Paul Mackerras9a40c502005-05-12 23:46:16 +0000526
527 menu .bar
528 .bar add cascade -label "File" -menu .bar.file
Keith Packard4840be62006-04-04 00:19:45 -0700529 .bar configure -font $uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +0000530 menu .bar.file
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000531 .bar.file add command -label "Update" -command updatecommits
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +1000532 .bar.file add command -label "Reread references" -command rereadrefs
Paul Mackerras1d10f362005-05-15 12:55:47 +0000533 .bar.file add command -label "Quit" -command doquit
Keith Packard4840be62006-04-04 00:19:45 -0700534 .bar.file configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +1100535 menu .bar.edit
536 .bar add cascade -label "Edit" -menu .bar.edit
537 .bar.edit add command -label "Preferences" -command doprefs
Keith Packard4840be62006-04-04 00:19:45 -0700538 .bar.edit configure -font $uifont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000539
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +1000540 menu .bar.view -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000541 .bar add cascade -label "View" -menu .bar.view
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000542 .bar.view add command -label "New view..." -command {newview 0}
543 .bar.view add command -label "Edit view..." -command editview \
544 -state disabled
Paul Mackerras50b44ec2006-04-04 10:16:22 +1000545 .bar.view add command -label "Delete view" -command delview -state disabled
546 .bar.view add separator
Paul Mackerrasa90a6d22006-04-25 17:12:46 +1000547 .bar.view add radiobutton -label "All files" -command {showview 0} \
548 -variable selectedview -value 0
Mark Levedahl40b87ff2007-02-01 08:44:46 -0500549
Paul Mackerras9a40c502005-05-12 23:46:16 +0000550 menu .bar.help
551 .bar add cascade -label "Help" -menu .bar.help
552 .bar.help add command -label "About gitk" -command about
Paul Mackerras4e95e1f2006-04-05 09:39:51 +1000553 .bar.help add command -label "Key bindings" -command keys
Keith Packard4840be62006-04-04 00:19:45 -0700554 .bar.help configure -font $uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +0000555 . configure -menu .bar
556
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500557 # the gui has upper and lower half, parts of a paned window.
Paul Mackerras0327d272005-05-10 00:23:42 +0000558 panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500559
560 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500561 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500562 set geometry(topheight) [expr {15 * $linespc}]
563 set geometry(topwidth) [expr {80 * $charspc}]
564 set geometry(botheight) [expr {15 * $linespc}]
565 set geometry(botwidth) [expr {50 * $charspc}]
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500566 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
567 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000568 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500569
570 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
571 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
572 frame .tf.histframe
573 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
574
575 # create three canvases
576 set cscroll .tf.histframe.csb
577 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500578 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -0400579 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000580 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100581 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500582 .tf.histframe.pwclist add $canv
583 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500584 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -0400585 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000586 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500587 .tf.histframe.pwclist add $canv2
588 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500589 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -0400590 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000591 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500592 .tf.histframe.pwclist add $canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500593 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
594 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Paul Mackerras98f350e2005-05-15 05:56:51 +0000595
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500596 # a scroll bar to rule them
597 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
598 pack $cscroll -side right -fill y
599 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
600 lappend bglist $canv $canv2 $canv3
601 pack .tf.histframe.pwclist -fill both -expand 1 -side left
602
603 # we have two button bars at bottom of top frame. Bar 1
604 frame .tf.bar
605 frame .tf.lbar -height 15
606
607 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000608 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500609 set sha1but .tf.bar.sha1label
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000610 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
Keith Packard4840be62006-04-04 00:19:45 -0700611 -command gotocommit -width 8 -font $uifont
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000612 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500613 pack .tf.bar.sha1label -side left
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000614 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
615 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +0000616 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +1000617
618 image create bitmap bm-left -data {
619 #define left_width 16
620 #define left_height 16
621 static unsigned char left_bits[] = {
622 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
623 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
624 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
625 }
626 image create bitmap bm-right -data {
627 #define right_width 16
628 #define right_height 16
629 static unsigned char right_bits[] = {
630 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
631 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
632 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
633 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500634 button .tf.bar.leftbut -image bm-left -command goback \
Paul Mackerrasd6982062005-08-06 22:06:06 +1000635 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500636 pack .tf.bar.leftbut -side left -fill y
637 button .tf.bar.rightbut -image bm-right -command goforw \
Paul Mackerrasd6982062005-08-06 22:06:06 +1000638 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500639 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +1000640
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500641 button .tf.bar.findbut -text "Find" -command dofind -font $uifont
642 pack .tf.bar.findbut -side left
Paul Mackerras98f350e2005-05-15 05:56:51 +0000643 set findstring {}
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500644 set fstring .tf.bar.findstring
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000645 lappend entries $fstring
Paul Mackerras908c3582006-05-20 09:38:11 +1000646 entry $fstring -width 30 -font $textfont -textvariable findstring
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000647 trace add variable findstring write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500648 pack $fstring -side left -expand 1 -fill x -in .tf.bar
Paul Mackerras98f350e2005-05-15 05:56:51 +0000649 set findtype Exact
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500650 set findtypemenu [tk_optionMenu .tf.bar.findtype \
651 findtype Exact IgnCase Regexp]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000652 trace add variable findtype write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500653 .tf.bar.findtype configure -font $uifont
654 .tf.bar.findtype.menu configure -font $uifont
Paul Mackerras98f350e2005-05-15 05:56:51 +0000655 set findloc "All fields"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500656 tk_optionMenu .tf.bar.findloc findloc "All fields" Headline \
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000657 Comments Author Committer
658 trace add variable findloc write find_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500659 .tf.bar.findloc configure -font $uifont
660 .tf.bar.findloc.menu configure -font $uifont
661 pack .tf.bar.findloc -side right
662 pack .tf.bar.findtype -side right
Paul Mackerrasb5721c72005-05-10 12:08:22 +0000663
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500664 # build up the bottom bar of upper window
665 label .tf.lbar.flabel -text "Highlight: Commits " \
666 -font $uifont
667 pack .tf.lbar.flabel -side left -fill y
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000668 set gdttype "touching paths:"
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500669 set gm [tk_optionMenu .tf.lbar.gdttype gdttype "touching paths:" \
670 "adding/removing string:"]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +1000671 trace add variable gdttype write hfiles_change
672 $gm conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500673 .tf.lbar.gdttype conf -font $uifont
674 pack .tf.lbar.gdttype -side left -fill y
675 entry .tf.lbar.fent -width 25 -font $textfont \
Paul Mackerras908c3582006-05-20 09:38:11 +1000676 -textvariable highlight_files
677 trace add variable highlight_files write hfiles_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500678 lappend entries .tf.lbar.fent
679 pack .tf.lbar.fent -side left -fill x -expand 1
680 label .tf.lbar.vlabel -text " OR in view" -font $uifont
681 pack .tf.lbar.vlabel -side left -fill y
Paul Mackerras908c3582006-05-20 09:38:11 +1000682 global viewhlmenu selectedhlview
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500683 set viewhlmenu [tk_optionMenu .tf.lbar.vhl selectedhlview None]
Paul Mackerras3cd204e2006-11-23 21:06:16 +1100684 $viewhlmenu entryconf None -command delvhighlight
Paul Mackerras63b79192006-05-20 21:31:52 +1000685 $viewhlmenu conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500686 .tf.lbar.vhl conf -font $uifont
687 pack .tf.lbar.vhl -side left -fill y
688 label .tf.lbar.rlabel -text " OR " -font $uifont
689 pack .tf.lbar.rlabel -side left -fill y
Paul Mackerras164ff272006-05-29 19:50:02 +1000690 global highlight_related
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500691 set m [tk_optionMenu .tf.lbar.relm highlight_related None \
692 "Descendent" "Not descendent" "Ancestor" "Not ancestor"]
Paul Mackerras164ff272006-05-29 19:50:02 +1000693 $m conf -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500694 .tf.lbar.relm conf -font $uifont
Paul Mackerras164ff272006-05-29 19:50:02 +1000695 trace add variable highlight_related write vrel_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500696 pack .tf.lbar.relm -side left -fill y
Paul Mackerras908c3582006-05-20 09:38:11 +1000697
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500698 # Finish putting the upper half of the viewer together
699 pack .tf.lbar -in .tf -side bottom -fill x
700 pack .tf.bar -in .tf -side bottom -fill x
701 pack .tf.histframe -fill both -side top -expand 1
702 .ctop add .tf
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500703 .ctop paneconfigure .tf -height $geometry(topheight)
704 .ctop paneconfigure .tf -width $geometry(topwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500705
706 # now build up the bottom
707 panedwindow .pwbottom -orient horizontal
708
709 # lower left, a text box over search bar, scroll bar to the right
710 # if we know window height, then that will set the lower text height, otherwise
711 # we set lower text height which will drive window height
712 if {[info exists geometry(main)]} {
713 frame .bleft -width $geometry(botwidth)
714 } else {
715 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
716 }
717 frame .bleft.top
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000718 frame .bleft.mid
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500719
720 button .bleft.top.search -text "Search" -command dosearch \
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000721 -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500722 pack .bleft.top.search -side left -padx 5
723 set sstring .bleft.top.sstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000724 entry $sstring -width 20 -font $textfont -textvariable searchstring
725 lappend entries $sstring
726 trace add variable searchstring write incrsearch
727 pack $sstring -side left -expand 1 -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000728 radiobutton .bleft.mid.diff -text "Diff" \
729 -command changediffdisp -variable diffelide -value {0 0}
730 radiobutton .bleft.mid.old -text "Old version" \
731 -command changediffdisp -variable diffelide -value {0 1}
732 radiobutton .bleft.mid.new -text "New version" \
733 -command changediffdisp -variable diffelide -value {1 0}
734 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500735 set ctext .bleft.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000736 text $ctext -background $bgcolor -foreground $fgcolor \
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400737 -tabs "[expr {$tabstop * $charspc}]" \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000738 -state disabled -font $textfont \
Paul Mackerras3ea06f92006-05-24 10:16:03 +1000739 -yscrollcommand scrolltext -wrap none
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500740 scrollbar .bleft.sb -command "$ctext yview"
741 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +1000742 pack .bleft.mid -side top -fill x
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500743 pack .bleft.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000744 pack $ctext -side left -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000745 lappend bglist $ctext
746 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000747
Sergey Vlasovf1b86292006-05-15 19:13:14 +0400748 $ctext tag conf comment -wrap $wrapcomment
Paul Mackerrasf0654862005-07-18 14:29:03 -0400749 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000750 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
751 $ctext tag conf d0 -fore [lindex $diffcolors 0]
752 $ctext tag conf d1 -fore [lindex $diffcolors 1]
Paul Mackerras712fcc02005-11-30 09:28:16 +1100753 $ctext tag conf m0 -fore red
754 $ctext tag conf m1 -fore blue
755 $ctext tag conf m2 -fore green
756 $ctext tag conf m3 -fore purple
757 $ctext tag conf m4 -fore brown
Paul Mackerrasb77b0272006-02-07 09:13:52 +1100758 $ctext tag conf m5 -fore "#009090"
759 $ctext tag conf m6 -fore magenta
760 $ctext tag conf m7 -fore "#808000"
761 $ctext tag conf m8 -fore "#009000"
762 $ctext tag conf m9 -fore "#ff0080"
763 $ctext tag conf m10 -fore cyan
764 $ctext tag conf m11 -fore "#b07070"
765 $ctext tag conf m12 -fore "#70b0f0"
766 $ctext tag conf m13 -fore "#70f0b0"
767 $ctext tag conf m14 -fore "#f0b070"
768 $ctext tag conf m15 -fore "#ff70b0"
Paul Mackerras712fcc02005-11-30 09:28:16 +1100769 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +1100770 set mergemax 16
Paul Mackerras712fcc02005-11-30 09:28:16 +1100771 $ctext tag conf mresult -font [concat $textfont bold]
772 $ctext tag conf msep -font [concat $textfont bold]
773 $ctext tag conf found -back yellow
Paul Mackerrase5c2d852005-05-11 23:44:54 +0000774
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500775 .pwbottom add .bleft
Mark Levedahl9ca72f42007-02-12 19:19:34 -0500776 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500777
778 # lower right
779 frame .bright
780 frame .bright.mode
781 radiobutton .bright.mode.patch -text "Patch" \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000782 -command reselectline -variable cmitmode -value "patch"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +0400783 .bright.mode.patch configure -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500784 radiobutton .bright.mode.tree -text "Tree" \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000785 -command reselectline -variable cmitmode -value "tree"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +0400786 .bright.mode.tree configure -font $uifont
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500787 grid .bright.mode.patch .bright.mode.tree -sticky ew
788 pack .bright.mode -side top -fill x
789 set cflist .bright.cfiles
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000790 set indent [font measure $mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500791 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -0400792 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000793 -background $bgcolor -foreground $fgcolor \
794 -font $mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000795 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500796 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000797 -cursor [. cget -cursor] \
798 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +1000799 lappend bglist $cflist
800 lappend fglist $cflist
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500801 scrollbar .bright.sb -command "$cflist yview"
802 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000803 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +1000804 $cflist tag configure highlight \
805 -background [$cflist cget -selectbackground]
Paul Mackerras63b79192006-05-20 21:31:52 +1000806 $cflist tag configure bold -font [concat $mainfont bold]
Paul Mackerrasd2610d12005-05-11 00:45:38 +0000807
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500808 .pwbottom add .bright
809 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +0000810
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500811 # restore window position if known
812 if {[info exists geometry(main)]} {
813 wm geometry . "$geometry(main)"
814 }
815
Shawn O. Pearced23d98d2007-07-19 00:37:58 -0400816 if {[tk windowingsystem] eq {aqua}} {
817 set M1B M1
818 } else {
819 set M1B Control
820 }
821
Junio C Hamanoe9937d22007-02-01 08:46:38 -0500822 bind .pwbottom <Configure> {resizecdetpanes %W %w}
823 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +1000824 bindall <1> {selcanvline %W %x %y}
825 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -0400826 if {[tk windowingsystem] == "win32"} {
827 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
828 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
829 } else {
830 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
831 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
832 }
Paul Mackerrasbe0cd092006-03-31 09:55:11 +1100833 bindall <2> "canvscan mark %W %x %y"
834 bindall <B2-Motion> "canvscan dragto %W %x %y"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +1000835 bindkey <Home> selfirstline
836 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +0000837 bind . <Key-Up> "selnextline -1"
838 bind . <Key-Down> "selnextline 1"
Paul Mackerras4e7d6772006-05-30 21:33:07 +1000839 bind . <Shift-Key-Up> "next_highlight -1"
840 bind . <Shift-Key-Down> "next_highlight 1"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +1000841 bindkey <Key-Right> "goforw"
842 bindkey <Key-Left> "goback"
843 bind . <Key-Prior> "selnextpage -1"
844 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -0400845 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
846 bind . <$M1B-End> "allcanvs yview moveto 1.0"
847 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
848 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
849 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
850 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +0000851 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
852 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
853 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000854 bindkey p "selnextline -1"
855 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +1000856 bindkey z "goback"
857 bindkey x "goforw"
858 bindkey i "selnextline -1"
859 bindkey k "selnextline 1"
860 bindkey j "goback"
861 bindkey l "goforw"
Paul Mackerrascfb45632005-05-31 12:14:42 +0000862 bindkey b "$ctext yview scroll -1 pages"
863 bindkey d "$ctext yview scroll 18 units"
864 bindkey u "$ctext yview scroll -18 units"
Paul Mackerrasb74fd572005-07-16 07:46:13 -0400865 bindkey / {findnext 1}
866 bindkey <Key-Return> {findnext 0}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000867 bindkey ? findprev
Paul Mackerras39ad8572005-05-19 12:35:53 +0000868 bindkey f nextfile
Eric Wonge7a09192007-02-23 12:36:34 -0800869 bindkey <F5> updatecommits
Shawn O. Pearced23d98d2007-07-19 00:37:58 -0400870 bind . <$M1B-q> doquit
871 bind . <$M1B-f> dofind
872 bind . <$M1B-g> {findnext 0}
873 bind . <$M1B-r> dosearchback
874 bind . <$M1B-s> dosearch
875 bind . <$M1B-equal> {incrfont 1}
876 bind . <$M1B-KP_Add> {incrfont 1}
877 bind . <$M1B-minus> {incrfont -1}
878 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -0500879 wm protocol . WM_DELETE_WINDOW doquit
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000880 bind . <Button-1> "click %W"
Paul Mackerras17386062005-05-18 22:51:00 +0000881 bind $fstring <Key-Return> dofind
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000882 bind $sha1entry <Key-Return> gotocommit
Paul Mackerrasee3dc722005-06-25 16:37:13 +1000883 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +1000884 bind $cflist <1> {sel_flist %W %x %y; break}
885 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +1000886 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerras32447292007-07-27 22:30:15 +1000887 bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
Paul Mackerrasea13cba2005-06-16 10:54:04 +0000888
889 set maincursor [. cget -cursor]
890 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +1000891 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +0000892
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +1000893 set rowctxmenu .rowctxmenu
894 menu $rowctxmenu -tearoff 0
895 $rowctxmenu add command -label "Diff this -> selected" \
896 -command {diffvssel 0}
897 $rowctxmenu add command -label "Diff selected -> this" \
898 -command {diffvssel 1}
Paul Mackerras74daedb2005-06-27 19:27:32 +1000899 $rowctxmenu add command -label "Make patch" -command mkpatch
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +1000900 $rowctxmenu add command -label "Create tag" -command mktag
Paul Mackerras4a2139f2005-06-29 09:47:48 +1000901 $rowctxmenu add command -label "Write commit to file" -command writecommit
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +1000902 $rowctxmenu add command -label "Create new branch" -command mkbranch
Paul Mackerrasca6d8f52006-08-06 21:08:05 +1000903 $rowctxmenu add command -label "Cherry-pick this commit" \
904 -command cherrypick
Paul Mackerras6fb735a2006-10-19 10:09:06 +1000905 $rowctxmenu add command -label "Reset HEAD branch to here" \
906 -command resethead
Paul Mackerras10299152006-08-02 09:52:01 +1000907
Paul Mackerras219ea3a2006-09-07 10:21:39 +1000908 set fakerowmenu .fakerowmenu
909 menu $fakerowmenu -tearoff 0
910 $fakerowmenu add command -label "Diff this -> selected" \
911 -command {diffvssel 0}
912 $fakerowmenu add command -label "Diff selected -> this" \
913 -command {diffvssel 1}
914 $fakerowmenu add command -label "Make patch" -command mkpatch
915# $fakerowmenu add command -label "Commit" -command {mkcommit 0}
916# $fakerowmenu add command -label "Commit all" -command {mkcommit 1}
917# $fakerowmenu add command -label "Revert local changes" -command revertlocal
918
Paul Mackerras10299152006-08-02 09:52:01 +1000919 set headctxmenu .headctxmenu
920 menu $headctxmenu -tearoff 0
921 $headctxmenu add command -label "Check out this branch" \
922 -command cobranch
923 $headctxmenu add command -label "Remove this branch" \
924 -command rmbranch
Paul Mackerras32447292007-07-27 22:30:15 +1000925
926 global flist_menu
927 set flist_menu .flistctxmenu
928 menu $flist_menu -tearoff 0
929 $flist_menu add command -label "Highlight this too" \
930 -command {flist_hl 0}
931 $flist_menu add command -label "Highlight this only" \
932 -command {flist_hl 1}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000933}
934
Mark Levedahl314c3092007-08-07 21:40:35 -0400935# Windows sends all mouse wheel events to the current focused window, not
936# the one where the mouse hovers, so bind those events here and redirect
937# to the correct window
938proc windows_mousewheel_redirector {W X Y D} {
939 global canv canv2 canv3
940 set w [winfo containing -displayof $W $X $Y]
941 if {$w ne ""} {
942 set u [expr {$D < 0 ? 5 : -5}]
943 if {$w == $canv || $w == $canv2 || $w == $canv3} {
944 allcanvs yview scroll $u units
945 } else {
946 catch {
947 $w yview scroll $u units
948 }
949 }
950 }
951}
952
Paul Mackerrasbe0cd092006-03-31 09:55:11 +1100953# mouse-2 makes all windows scan vertically, but only the one
954# the cursor is in scans horizontally
955proc canvscan {op w x y} {
956 global canv canv2 canv3
957 foreach c [list $canv $canv2 $canv3] {
958 if {$c == $w} {
959 $c scan $op $x $y
960 } else {
961 $c scan $op 0 $y
962 }
963 }
964}
965
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100966proc scrollcanv {cscroll f0 f1} {
967 $cscroll set $f0 $f1
968 drawfrac $f0 $f1
Paul Mackerras908c3582006-05-20 09:38:11 +1000969 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +1100970}
971
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000972# when we make a key binding for the toplevel, make sure
973# it doesn't get triggered when that key is pressed in the
974# find string entry widget.
975proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000976 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000977 bind . $ev $script
978 set escript [bind Entry $ev]
979 if {$escript == {}} {
980 set escript [bind Entry <Key>]
981 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000982 foreach e $entries {
983 bind $e $ev "$escript; break"
984 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000985}
986
987# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000988# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000989proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -0400990 global ctext entries
991 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000992 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +0000993 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +0000994 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +0000995}
996
997proc savestuff {w} {
Mark Levedahl7e12f1a2007-05-20 11:45:50 -0400998 global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +1100999 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001000 global maxwidth showneartags showlocalchanges
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001001 global viewname viewfiles viewargs viewperm nextviewnum
Sergey Vlasovf1b86292006-05-15 19:13:14 +04001002 global cmitmode wrapcomment
Mark Levedahl60378c02007-05-20 12:12:48 -04001003 global colors bgcolor fgcolor diffcolors selectbgcolor
Paul Mackerras4ef17532005-07-27 22:16:51 -05001004
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001005 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001006 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001007 catch {
1008 set f [open "~/.gitk-new" w]
Paul Mackerrasf0654862005-07-18 14:29:03 -04001009 puts $f [list set mainfont $mainfont]
1010 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07001011 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04001012 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04001013 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10001014 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10001015 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001016 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04001017 puts $f [list set wrapcomment $wrapcomment]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10001018 puts $f [list set showneartags $showneartags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001019 puts $f [list set showlocalchanges $showlocalchanges]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001020 puts $f [list set bgcolor $bgcolor]
1021 puts $f [list set fgcolor $fgcolor]
1022 puts $f [list set colors $colors]
1023 puts $f [list set diffcolors $diffcolors]
Mark Levedahl60378c02007-05-20 12:12:48 -04001024 puts $f [list set selectbgcolor $selectbgcolor]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001025
Mark Levedahlb6047c52007-02-08 22:22:24 -05001026 puts $f "set geometry(main) [wm geometry .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001027 puts $f "set geometry(topwidth) [winfo width .tf]"
1028 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001029 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
1030 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001031 puts $f "set geometry(botwidth) [winfo width .bleft]"
1032 puts $f "set geometry(botheight) [winfo height .bleft]"
1033
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001034 puts -nonewline $f "set permviews {"
1035 for {set v 0} {$v < $nextviewnum} {incr v} {
1036 if {$viewperm($v)} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001037 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001038 }
1039 }
1040 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001041 close $f
1042 file rename -force "~/.gitk-new" "~/.gitk"
1043 }
1044 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00001045}
1046
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001047proc resizeclistpanes {win w} {
1048 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11001049 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001050 set s0 [$win sash coord 0]
1051 set s1 [$win sash coord 1]
1052 if {$w < 60} {
1053 set sash0 [expr {int($w/2 - 2)}]
1054 set sash1 [expr {int($w*5/6 - 2)}]
1055 } else {
1056 set factor [expr {1.0 * $w / $oldwidth($win)}]
1057 set sash0 [expr {int($factor * [lindex $s0 0])}]
1058 set sash1 [expr {int($factor * [lindex $s1 0])}]
1059 if {$sash0 < 30} {
1060 set sash0 30
1061 }
1062 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001063 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001064 }
1065 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001066 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001067 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001068 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001069 }
1070 }
1071 }
1072 $win sash place 0 $sash0 [lindex $s0 1]
1073 $win sash place 1 $sash1 [lindex $s1 1]
1074 }
1075 set oldwidth($win) $w
1076}
1077
1078proc resizecdetpanes {win w} {
1079 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11001080 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001081 set s0 [$win sash coord 0]
1082 if {$w < 60} {
1083 set sash0 [expr {int($w*3/4 - 2)}]
1084 } else {
1085 set factor [expr {1.0 * $w / $oldwidth($win)}]
1086 set sash0 [expr {int($factor * [lindex $s0 0])}]
1087 if {$sash0 < 45} {
1088 set sash0 45
1089 }
1090 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08001091 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00001092 }
1093 }
1094 $win sash place 0 $sash0 [lindex $s0 1]
1095 }
1096 set oldwidth($win) $w
1097}
1098
Paul Mackerrasb5721c72005-05-10 12:08:22 +00001099proc allcanvs args {
1100 global canv canv2 canv3
1101 eval $canv $args
1102 eval $canv2 $args
1103 eval $canv3 $args
1104}
1105
1106proc bindall {event action} {
1107 global canv canv2 canv3
1108 bind $canv $event $action
1109 bind $canv2 $event $action
1110 bind $canv3 $event $action
1111}
1112
Paul Mackerras9a40c502005-05-12 23:46:16 +00001113proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001114 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00001115 set w .about
1116 if {[winfo exists $w]} {
1117 raise $w
1118 return
1119 }
1120 toplevel $w
1121 wm title $w "About gitk"
1122 message $w.m -text {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001123Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00001124
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001125Copyright © 2005-2006 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00001126
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10001127Use and redistribute under the terms of the GNU General Public License} \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001128 -justify center -aspect 400 -border 2 -bg white -relief groove
1129 pack $w.m -side top -fill x -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001130 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001131 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00001132 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001133 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001134 bind $w <Visibility> "focus $w.ok"
1135 bind $w <Key-Escape> "destroy $w"
1136 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00001137}
1138
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001139proc keys {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001140 global uifont
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001141 set w .keys
1142 if {[winfo exists $w]} {
1143 raise $w
1144 return
1145 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001146 if {[tk windowingsystem] eq {aqua}} {
1147 set M1T Cmd
1148 } else {
1149 set M1T Ctrl
1150 }
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001151 toplevel $w
1152 wm title $w "Gitk key bindings"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001153 message $w.m -text "
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001154Gitk key bindings:
1155
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001156<$M1T-Q> Quit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001157<Home> Move to first commit
1158<End> Move to last commit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001159<Up>, p, i Move up one commit
1160<Down>, n, k Move down one commit
1161<Left>, z, j Go back in history list
1162<Right>, x, l Go forward in history list
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10001163<PageUp> Move up one page in commit list
1164<PageDown> Move down one page in commit list
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001165<$M1T-Home> Scroll to top of commit list
1166<$M1T-End> Scroll to bottom of commit list
1167<$M1T-Up> Scroll commit list up one line
1168<$M1T-Down> Scroll commit list down one line
1169<$M1T-PageUp> Scroll commit list up one page
1170<$M1T-PageDown> Scroll commit list down one page
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001171<Shift-Up> Move to previous highlighted line
1172<Shift-Down> Move to next highlighted line
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001173<Delete>, b Scroll diff view up one page
1174<Backspace> Scroll diff view up one page
1175<Space> Scroll diff view down one page
1176u Scroll diff view up 18 lines
1177d Scroll diff view down 18 lines
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001178<$M1T-F> Find
1179<$M1T-G> Move to next find hit
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001180<Return> Move to next find hit
1181/ Move to next find hit, or redo find
1182? Move to previous find hit
1183f Scroll diff view to next file
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001184<$M1T-S> Search for next hit in diff view
1185<$M1T-R> Search for previous hit in diff view
1186<$M1T-KP+> Increase font size
1187<$M1T-plus> Increase font size
1188<$M1T-KP-> Decrease font size
1189<$M1T-minus> Decrease font size
Eric Wonge7a09192007-02-23 12:36:34 -08001190<F5> Update
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04001191" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001192 -justify left -bg white -border 2 -relief groove
1193 pack $w.m -side top -fill both -padx 2 -pady 2
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001194 $w.m configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001195 button $w.ok -text Close -command "destroy $w" -default active
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001196 pack $w.ok -side bottom
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001197 $w.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04001198 bind $w <Visibility> "focus $w.ok"
1199 bind $w <Key-Escape> "destroy $w"
1200 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10001201}
1202
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001203# Procedures for manipulating the file list window at the
1204# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001205
1206proc treeview {w l openlevs} {
1207 global treecontents treediropen treeheight treeparent treeindex
1208
1209 set ix 0
1210 set treeindex() 0
1211 set lev 0
1212 set prefix {}
1213 set prefixend -1
1214 set prefendstack {}
1215 set htstack {}
1216 set ht 0
1217 set treecontents() {}
1218 $w conf -state normal
1219 foreach f $l {
1220 while {[string range $f 0 $prefixend] ne $prefix} {
1221 if {$lev <= $openlevs} {
1222 $w mark set e:$treeindex($prefix) "end -1c"
1223 $w mark gravity e:$treeindex($prefix) left
1224 }
1225 set treeheight($prefix) $ht
1226 incr ht [lindex $htstack end]
1227 set htstack [lreplace $htstack end end]
1228 set prefixend [lindex $prefendstack end]
1229 set prefendstack [lreplace $prefendstack end end]
1230 set prefix [string range $prefix 0 $prefixend]
1231 incr lev -1
1232 }
1233 set tail [string range $f [expr {$prefixend+1}] end]
1234 while {[set slash [string first "/" $tail]] >= 0} {
1235 lappend htstack $ht
1236 set ht 0
1237 lappend prefendstack $prefixend
1238 incr prefixend [expr {$slash + 1}]
1239 set d [string range $tail 0 $slash]
1240 lappend treecontents($prefix) $d
1241 set oldprefix $prefix
1242 append prefix $d
1243 set treecontents($prefix) {}
1244 set treeindex($prefix) [incr ix]
1245 set treeparent($prefix) $oldprefix
1246 set tail [string range $tail [expr {$slash+1}] end]
1247 if {$lev <= $openlevs} {
1248 set ht 1
1249 set treediropen($prefix) [expr {$lev < $openlevs}]
1250 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
1251 $w mark set d:$ix "end -1c"
1252 $w mark gravity d:$ix left
1253 set str "\n"
1254 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1255 $w insert end $str
1256 $w image create end -align center -image $bm -padx 1 \
1257 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10001258 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001259 $w mark set s:$ix "end -1c"
1260 $w mark gravity s:$ix left
1261 }
1262 incr lev
1263 }
1264 if {$tail ne {}} {
1265 if {$lev <= $openlevs} {
1266 incr ht
1267 set str "\n"
1268 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
1269 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001270 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001271 }
1272 lappend treecontents($prefix) $tail
1273 }
1274 }
1275 while {$htstack ne {}} {
1276 set treeheight($prefix) $ht
1277 incr ht [lindex $htstack end]
1278 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05001279 set prefixend [lindex $prefendstack end]
1280 set prefendstack [lreplace $prefendstack end end]
1281 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001282 }
1283 $w conf -state disabled
1284}
1285
1286proc linetoelt {l} {
1287 global treeheight treecontents
1288
1289 set y 2
1290 set prefix {}
1291 while {1} {
1292 foreach e $treecontents($prefix) {
1293 if {$y == $l} {
1294 return "$prefix$e"
1295 }
1296 set n 1
1297 if {[string index $e end] eq "/"} {
1298 set n $treeheight($prefix$e)
1299 if {$y + $n > $l} {
1300 append prefix $e
1301 incr y
1302 break
1303 }
1304 }
1305 incr y $n
1306 }
1307 }
1308}
1309
Paul Mackerras45a9d502006-05-20 22:56:27 +10001310proc highlight_tree {y prefix} {
1311 global treeheight treecontents cflist
1312
1313 foreach e $treecontents($prefix) {
1314 set path $prefix$e
1315 if {[highlight_tag $path] ne {}} {
1316 $cflist tag add bold $y.0 "$y.0 lineend"
1317 }
1318 incr y
1319 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
1320 set y [highlight_tree $y $path]
1321 }
1322 }
1323 return $y
1324}
1325
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001326proc treeclosedir {w dir} {
1327 global treediropen treeheight treeparent treeindex
1328
1329 set ix $treeindex($dir)
1330 $w conf -state normal
1331 $w delete s:$ix e:$ix
1332 set treediropen($dir) 0
1333 $w image configure a:$ix -image tri-rt
1334 $w conf -state disabled
1335 set n [expr {1 - $treeheight($dir)}]
1336 while {$dir ne {}} {
1337 incr treeheight($dir) $n
1338 set dir $treeparent($dir)
1339 }
1340}
1341
1342proc treeopendir {w dir} {
1343 global treediropen treeheight treeparent treecontents treeindex
1344
1345 set ix $treeindex($dir)
1346 $w conf -state normal
1347 $w image configure a:$ix -image tri-dn
1348 $w mark set e:$ix s:$ix
1349 $w mark gravity e:$ix right
1350 set lev 0
1351 set str "\n"
1352 set n [llength $treecontents($dir)]
1353 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
1354 incr lev
1355 append str "\t"
1356 incr treeheight($x) $n
1357 }
1358 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001359 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001360 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001361 set iy $treeindex($de)
1362 $w mark set d:$iy e:$ix
1363 $w mark gravity d:$iy left
1364 $w insert e:$ix $str
1365 set treediropen($de) 0
1366 $w image create e:$ix -align center -image tri-rt -padx 1 \
1367 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10001368 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001369 $w mark set s:$iy e:$ix
1370 $w mark gravity s:$iy left
1371 set treeheight($de) 1
1372 } else {
1373 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10001374 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001375 }
1376 }
1377 $w mark gravity e:$ix left
1378 $w conf -state disabled
1379 set treediropen($dir) 1
1380 set top [lindex [split [$w index @0,0] .] 0]
1381 set ht [$w cget -height]
1382 set l [lindex [split [$w index s:$ix] .] 0]
1383 if {$l < $top} {
1384 $w yview $l.0
1385 } elseif {$l + $n + 1 > $top + $ht} {
1386 set top [expr {$l + $n + 2 - $ht}]
1387 if {$l < $top} {
1388 set top $l
1389 }
1390 $w yview $top.0
1391 }
1392}
1393
1394proc treeclick {w x y} {
1395 global treediropen cmitmode ctext cflist cflist_top
1396
1397 if {$cmitmode ne "tree"} return
1398 if {![info exists cflist_top]} return
1399 set l [lindex [split [$w index "@$x,$y"] "."] 0]
1400 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1401 $cflist tag add highlight $l.0 "$l.0 lineend"
1402 set cflist_top $l
1403 if {$l == 1} {
1404 $ctext yview 1.0
1405 return
1406 }
1407 set e [linetoelt $l]
1408 if {[string index $e end] ne "/"} {
1409 showfile $e
1410 } elseif {$treediropen($e)} {
1411 treeclosedir $w $e
1412 } else {
1413 treeopendir $w $e
1414 }
1415}
1416
1417proc setfilelist {id} {
1418 global treefilelist cflist
1419
1420 treeview $cflist $treefilelist($id) 0
1421}
1422
1423image create bitmap tri-rt -background black -foreground blue -data {
1424 #define tri-rt_width 13
1425 #define tri-rt_height 13
1426 static unsigned char tri-rt_bits[] = {
1427 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
1428 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
1429 0x00, 0x00};
1430} -maskdata {
1431 #define tri-rt-mask_width 13
1432 #define tri-rt-mask_height 13
1433 static unsigned char tri-rt-mask_bits[] = {
1434 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
1435 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
1436 0x08, 0x00};
1437}
1438image create bitmap tri-dn -background black -foreground blue -data {
1439 #define tri-dn_width 13
1440 #define tri-dn_height 13
1441 static unsigned char tri-dn_bits[] = {
1442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
1443 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1444 0x00, 0x00};
1445} -maskdata {
1446 #define tri-dn-mask_width 13
1447 #define tri-dn-mask_height 13
1448 static unsigned char tri-dn-mask_bits[] = {
1449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
1450 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
1451 0x00, 0x00};
1452}
1453
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001454proc init_flist {first} {
Paul Mackerras89b11d32006-05-02 19:55:31 +10001455 global cflist cflist_top selectedline difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001456
1457 $cflist conf -state normal
1458 $cflist delete 0.0 end
1459 if {$first ne {}} {
1460 $cflist insert end $first
1461 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001462 $cflist tag add highlight 1.0 "1.0 lineend"
1463 } else {
1464 catch {unset cflist_top}
1465 }
1466 $cflist conf -state disabled
1467 set difffilestart {}
1468}
1469
Paul Mackerras63b79192006-05-20 21:31:52 +10001470proc highlight_tag {f} {
1471 global highlight_paths
1472
1473 foreach p $highlight_paths {
1474 if {[string match $p $f]} {
1475 return "bold"
1476 }
1477 }
1478 return {}
1479}
1480
1481proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001482 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001483
Paul Mackerras45a9d502006-05-20 22:56:27 +10001484 $cflist conf -state normal
1485 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10001486 set end [lindex [split [$cflist index end] .] 0]
1487 for {set l 2} {$l < $end} {incr l} {
1488 set line [$cflist get $l.0 "$l.0 lineend"]
1489 if {[highlight_tag $line] ne {}} {
1490 $cflist tag add bold $l.0 "$l.0 lineend"
1491 }
1492 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001493 } else {
1494 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10001495 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001496 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001497}
1498
1499proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001500 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10001501
Paul Mackerras45a9d502006-05-20 22:56:27 +10001502 $cflist conf -state normal
1503 $cflist tag remove bold 1.0 end
1504 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10001505}
1506
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001507proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001508 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001509
Paul Mackerras45a9d502006-05-20 22:56:27 +10001510 $cflist conf -state normal
1511 foreach f $fl {
1512 $cflist insert end "\n"
1513 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001514 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10001515 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001516}
1517
1518proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10001519 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001520
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001521 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001522 if {![info exists cflist_top]} return
1523 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10001524 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
1525 $cflist tag add highlight $l.0 "$l.0 lineend"
1526 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10001527 if {$l == 1} {
1528 $ctext yview 1.0
1529 } else {
1530 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001531 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001532}
1533
Paul Mackerras32447292007-07-27 22:30:15 +10001534proc pop_flist_menu {w X Y x y} {
1535 global ctext cflist cmitmode flist_menu flist_menu_file
1536 global treediffs diffids
1537
1538 set l [lindex [split [$w index "@$x,$y"] "."] 0]
1539 if {$l <= 1} return
1540 if {$cmitmode eq "tree"} {
1541 set e [linetoelt $l]
1542 if {[string index $e end] eq "/"} return
1543 } else {
1544 set e [lindex $treediffs($diffids) [expr {$l-2}]]
1545 }
1546 set flist_menu_file $e
1547 tk_popup $flist_menu $X $Y
1548}
1549
1550proc flist_hl {only} {
1551 global flist_menu_file highlight_files
1552
1553 set x [shellquote $flist_menu_file]
1554 if {$only || $highlight_files eq {}} {
1555 set highlight_files $x
1556 } else {
1557 append highlight_files " " $x
1558 }
1559}
1560
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001561# Functions for adding and removing shell-type quoting
1562
1563proc shellquote {str} {
1564 if {![string match "*\['\"\\ \t]*" $str]} {
1565 return $str
1566 }
1567 if {![string match "*\['\"\\]*" $str]} {
1568 return "\"$str\""
1569 }
1570 if {![string match "*'*" $str]} {
1571 return "'$str'"
1572 }
1573 return "\"[string map {\" \\\" \\ \\\\} $str]\""
1574}
1575
1576proc shellarglist {l} {
1577 set str {}
1578 foreach a $l {
1579 if {$str ne {}} {
1580 append str " "
1581 }
1582 append str [shellquote $a]
1583 }
1584 return $str
1585}
1586
1587proc shelldequote {str} {
1588 set ret {}
1589 set used -1
1590 while {1} {
1591 incr used
1592 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
1593 append ret [string range $str $used end]
1594 set used [string length $str]
1595 break
1596 }
1597 set first [lindex $first 0]
1598 set ch [string index $str $first]
1599 if {$first > $used} {
1600 append ret [string range $str $used [expr {$first - 1}]]
1601 set used $first
1602 }
1603 if {$ch eq " " || $ch eq "\t"} break
1604 incr used
1605 if {$ch eq "'"} {
1606 set first [string first "'" $str $used]
1607 if {$first < 0} {
1608 error "unmatched single-quote"
1609 }
1610 append ret [string range $str $used [expr {$first - 1}]]
1611 set used $first
1612 continue
1613 }
1614 if {$ch eq "\\"} {
1615 if {$used >= [string length $str]} {
1616 error "trailing backslash"
1617 }
1618 append ret [string index $str $used]
1619 continue
1620 }
1621 # here ch == "\""
1622 while {1} {
1623 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
1624 error "unmatched double-quote"
1625 }
1626 set first [lindex $first 0]
1627 set ch [string index $str $first]
1628 if {$first > $used} {
1629 append ret [string range $str $used [expr {$first - 1}]]
1630 set used $first
1631 }
1632 if {$ch eq "\""} break
1633 incr used
1634 append ret [string index $str $used]
1635 incr used
1636 }
1637 }
1638 return [list $used $ret]
1639}
1640
1641proc shellsplit {str} {
1642 set l {}
1643 while {1} {
1644 set str [string trimleft $str]
1645 if {$str eq {}} break
1646 set dq [shelldequote $str]
1647 set n [lindex $dq 0]
1648 set word [lindex $dq 1]
1649 set str [string range $str $n end]
1650 lappend l $word
1651 }
1652 return $l
1653}
1654
Paul Mackerras7fcceed2006-04-27 19:21:49 +10001655# Code to implement multiple views
1656
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001657proc newview {ishighlight} {
1658 global nextviewnum newviewname newviewperm uifont newishighlight
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001659 global newviewargs revtreeargs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001660
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001661 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001662 set top .gitkview
1663 if {[winfo exists $top]} {
1664 raise $top
1665 return
1666 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001667 set newviewname($nextviewnum) "View $nextviewnum"
1668 set newviewperm($nextviewnum) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001669 set newviewargs($nextviewnum) [shellarglist $revtreeargs]
Mark Levedahl40b87ff2007-02-01 08:44:46 -05001670 vieweditor $top $nextviewnum "Gitk view definition"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001671}
1672
1673proc editview {} {
1674 global curview
1675 global viewname viewperm newviewname newviewperm
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001676 global viewargs newviewargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001677
1678 set top .gitkvedit-$curview
1679 if {[winfo exists $top]} {
1680 raise $top
1681 return
1682 }
1683 set newviewname($curview) $viewname($curview)
1684 set newviewperm($curview) $viewperm($curview)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001685 set newviewargs($curview) [shellarglist $viewargs($curview)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001686 vieweditor $top $curview "Gitk: edit view $viewname($curview)"
1687}
1688
1689proc vieweditor {top n title} {
1690 global newviewname newviewperm viewfiles
1691 global uifont
1692
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001693 toplevel $top
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001694 wm title $top $title
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001695 label $top.nl -text "Name" -font $uifont
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001696 entry $top.name -width 20 -textvariable newviewname($n) -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001697 grid $top.nl $top.name -sticky w -pady 5
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001698 checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) \
1699 -font $uifont
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001700 grid $top.perm - -pady 5 -sticky w
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001701 message $top.al -aspect 1000 -font $uifont \
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001702 -text "Commits to include (arguments to git rev-list):"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001703 grid $top.al - -sticky w -pady 5
1704 entry $top.args -width 50 -textvariable newviewargs($n) \
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001705 -background white -font $uifont
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001706 grid $top.args - -sticky ew -padx 5
1707 message $top.l -aspect 1000 -font $uifont \
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001708 -text "Enter files and directories to include, one per line:"
1709 grid $top.l - -sticky w
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001710 text $top.t -width 40 -height 10 -background white -font $uifont
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001711 if {[info exists viewfiles($n)]} {
1712 foreach f $viewfiles($n) {
1713 $top.t insert end $f
1714 $top.t insert end "\n"
1715 }
1716 $top.t delete {end - 1c} end
1717 $top.t mark set insert 0.0
1718 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001719 grid $top.t - -sticky ew -padx 5
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001720 frame $top.buts
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04001721 button $top.buts.ok -text "OK" -command [list newviewok $top $n] \
1722 -font $uifont
1723 button $top.buts.can -text "Cancel" -command [list destroy $top] \
1724 -font $uifont
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001725 grid $top.buts.ok $top.buts.can
1726 grid columnconfigure $top.buts 0 -weight 1 -uniform a
1727 grid columnconfigure $top.buts 1 -weight 1 -uniform a
1728 grid $top.buts - -pady 10 -sticky ew
1729 focus $top.t
1730}
1731
Paul Mackerras908c3582006-05-20 09:38:11 +10001732proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001733 set nmenu [$m index end]
1734 for {set i $first} {$i <= $nmenu} {incr i} {
1735 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001736 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001737 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001738 }
1739 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001740}
1741
1742proc allviewmenus {n op args} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001743 global viewhlmenu
1744
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001745 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras908c3582006-05-20 09:38:11 +10001746 doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001747}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001748
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001749proc newviewok {top n} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001750 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001751 global viewname viewfiles viewperm selectedview curview
Paul Mackerras908c3582006-05-20 09:38:11 +10001752 global viewargs newviewargs viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001753
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001754 if {[catch {
1755 set newargs [shellsplit $newviewargs($n)]
1756 } err]} {
1757 error_popup "Error in commit selection arguments: $err"
1758 wm raise $top
1759 focus $top
1760 return
1761 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001762 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001763 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001764 set ft [string trim $f]
1765 if {$ft ne {}} {
1766 lappend files $ft
1767 }
1768 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001769 if {![info exists viewfiles($n)]} {
1770 # creating a new view
1771 incr nextviewnum
1772 set viewname($n) $newviewname($n)
1773 set viewperm($n) $newviewperm($n)
1774 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001775 set viewargs($n) $newargs
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001776 addviewmenu $n
1777 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001778 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001779 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001780 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001781 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001782 } else {
1783 # editing an existing view
1784 set viewperm($n) $newviewperm($n)
1785 if {$newviewname($n) ne $viewname($n)} {
1786 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001787 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10001788 entryconf [list -label $viewname($n)]
1789 doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
1790 entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001791 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001792 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001793 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001794 set viewargs($n) $newargs
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001795 if {$curview == $n} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001796 run updatecommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001797 }
1798 }
1799 }
1800 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001801}
1802
1803proc delview {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001804 global curview viewdata viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001805
1806 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10001807 if {[info exists hlview] && $hlview == $curview} {
1808 set selectedhlview None
1809 unset hlview
1810 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001811 allviewmenus $curview delete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001812 set viewdata($curview) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001813 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001814 showview 0
1815}
1816
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001817proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10001818 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001819
1820 .bar.view add radiobutton -label $viewname($n) \
1821 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras908c3582006-05-20 09:38:11 +10001822 $viewhlmenu add radiobutton -label $viewname($n) \
1823 -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001824}
1825
Paul Mackerras22626ef2006-04-17 09:56:02 +10001826proc flatten {var} {
1827 global $var
1828
1829 set ret {}
1830 foreach i [array names $var] {
1831 lappend ret $i [set $var\($i\)]
1832 }
1833 return $ret
1834}
1835
1836proc unflatten {var l} {
1837 global $var
1838
1839 catch {unset $var}
1840 foreach {i v} $l {
1841 set $var\($i\) $v
1842 }
1843}
1844
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001845proc showview {n} {
1846 global curview viewdata viewfiles
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001847 global displayorder parentlist rowidlist rowoffsets
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001848 global colormap rowtextx commitrow nextcolor canvxmax
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001849 global numcommits rowrangelist commitlisted idrowranges rowchk
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001850 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10001851 global treediffs
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001852 global pending_select phase
Paul Mackerras322a8cc2006-10-15 18:03:46 +10001853 global commitidx rowlaidout rowoptim
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001854 global commfd
Paul Mackerrase507fd42007-06-16 21:51:08 +10001855 global selectedview selectfirst
Paul Mackerras6a90bff2007-06-18 09:48:23 +10001856 global vparentlist vdisporder vcmitlisted
Paul Mackerras908c3582006-05-20 09:38:11 +10001857 global hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001858
1859 if {$n == $curview} return
1860 set selid {}
1861 if {[info exists selectedline]} {
1862 set selid $currentid
1863 set y [yc $selectedline]
1864 set ymax [lindex [$canv cget -scrollregion] 3]
1865 set span [$canv yview]
1866 set ytop [expr {[lindex $span 0] * $ymax}]
1867 set ybot [expr {[lindex $span 1] * $ymax}]
1868 if {$ytop < $y && $y < $ybot} {
1869 set yscreen [expr {$y - $ytop}]
1870 } else {
1871 set yscreen [expr {($ybot - $ytop) / 2}]
1872 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10001873 } elseif {[info exists pending_select]} {
1874 set selid $pending_select
1875 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001876 }
1877 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10001878 normalline
Paul Mackerras22626ef2006-04-17 09:56:02 +10001879 if {$curview >= 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001880 set vparentlist($curview) $parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001881 set vdisporder($curview) $displayorder
1882 set vcmitlisted($curview) $commitlisted
Paul Mackerras22626ef2006-04-17 09:56:02 +10001883 if {$phase ne {}} {
1884 set viewdata($curview) \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001885 [list $phase $rowidlist $rowoffsets $rowrangelist \
1886 [flatten idrowranges] [flatten idinlist] \
Paul Mackerras322a8cc2006-10-15 18:03:46 +10001887 $rowlaidout $rowoptim $numcommits]
Paul Mackerras2516dae2006-04-21 10:35:31 +10001888 } elseif {![info exists viewdata($curview)]
1889 || [lindex $viewdata($curview) 0] ne {}} {
Paul Mackerras22626ef2006-04-17 09:56:02 +10001890 set viewdata($curview) \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001891 [list {} $rowidlist $rowoffsets $rowrangelist]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001892 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001893 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001894 catch {unset treediffs}
1895 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10001896 if {[info exists hlview] && $hlview == $n} {
1897 unset hlview
1898 set selectedhlview None
1899 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001900
1901 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001902 set selectedview $n
Paul Mackerras3cd204e2006-11-23 21:06:16 +11001903 .bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}]
1904 .bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001905
1906 if {![info exists viewdata($n)]} {
Paul Mackerrase507fd42007-06-16 21:51:08 +10001907 if {$selid ne {}} {
1908 set pending_select $selid
1909 }
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10001910 getcommits
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001911 return
1912 }
1913
Paul Mackerras22626ef2006-04-17 09:56:02 +10001914 set v $viewdata($n)
1915 set phase [lindex $v 0]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001916 set displayorder $vdisporder($n)
1917 set parentlist $vparentlist($n)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001918 set commitlisted $vcmitlisted($n)
1919 set rowidlist [lindex $v 1]
1920 set rowoffsets [lindex $v 2]
1921 set rowrangelist [lindex $v 3]
Paul Mackerras22626ef2006-04-17 09:56:02 +10001922 if {$phase eq {}} {
1923 set numcommits [llength $displayorder]
1924 catch {unset idrowranges}
Paul Mackerras22626ef2006-04-17 09:56:02 +10001925 } else {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001926 unflatten idrowranges [lindex $v 4]
1927 unflatten idinlist [lindex $v 5]
1928 set rowlaidout [lindex $v 6]
1929 set rowoptim [lindex $v 7]
1930 set numcommits [lindex $v 8]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001931 catch {unset rowchk}
Paul Mackerras22626ef2006-04-17 09:56:02 +10001932 }
1933
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001934 catch {unset colormap}
1935 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001936 set nextcolor 0
1937 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001938 set curview $n
1939 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001940 setcanvscroll
1941 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10001942 set row {}
1943 set selectfirst 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001944 if {$selid ne {} && [info exists commitrow($n,$selid)]} {
1945 set row $commitrow($n,$selid)
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001946 # try to get the selected row in the same position on the screen
1947 set ymax [lindex [$canv cget -scrollregion] 3]
1948 set ytop [expr {[yc $row] - $yscreen}]
1949 if {$ytop < 0} {
1950 set ytop 0
1951 }
1952 set yf [expr {$ytop * 1.0 / $ymax}]
1953 }
1954 allcanvs yview moveto $yf
1955 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10001956 if {$row ne {}} {
1957 selectline $row 0
1958 } elseif {$selid ne {}} {
1959 set pending_select $selid
1960 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10001961 set row [first_real_row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001962 if {$row < $numcommits} {
1963 selectline $row 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10001964 } else {
1965 set selectfirst 1
1966 }
1967 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001968 if {$phase ne {}} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001969 if {$phase eq "getcommits"} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001970 show_status "Reading commits..."
Paul Mackerrasd16c0812006-04-25 21:21:10 +10001971 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001972 run chewcommits $n
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001973 } elseif {$numcommits == 0} {
1974 show_status "No commits selected"
Paul Mackerras2516dae2006-04-21 10:35:31 +10001975 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001976}
1977
Paul Mackerras908c3582006-05-20 09:38:11 +10001978# Stuff relating to the highlighting facility
1979
1980proc ishighlighted {row} {
Paul Mackerras164ff272006-05-29 19:50:02 +10001981 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10001982
1983 if {[info exists nhighlights($row)] && $nhighlights($row) > 0} {
1984 return $nhighlights($row)
1985 }
1986 if {[info exists vhighlights($row)] && $vhighlights($row) > 0} {
1987 return $vhighlights($row)
1988 }
1989 if {[info exists fhighlights($row)] && $fhighlights($row) > 0} {
1990 return $fhighlights($row)
1991 }
Paul Mackerras164ff272006-05-29 19:50:02 +10001992 if {[info exists rhighlights($row)] && $rhighlights($row) > 0} {
1993 return $rhighlights($row)
1994 }
Paul Mackerras908c3582006-05-20 09:38:11 +10001995 return 0
1996}
1997
1998proc bolden {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10001999 global canv linehtag selectedline boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10002000
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002001 lappend boldrows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10002002 $canv itemconf $linehtag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10002003 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10002004 $canv delete secsel
2005 set t [eval $canv create rect [$canv bbox $linehtag($row)] \
2006 -outline {{}} -tags secsel \
2007 -fill [$canv cget -selectbackground]]
2008 $canv lower $t
2009 }
2010}
2011
2012proc bolden_name {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002013 global canv2 linentag selectedline boldnamerows
Paul Mackerras908c3582006-05-20 09:38:11 +10002014
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002015 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10002016 $canv2 itemconf $linentag($row) -font $font
Paul Mackerras5864c082006-05-26 22:22:48 +10002017 if {[info exists selectedline] && $row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10002018 $canv2 delete secsel
2019 set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
2020 -outline {{}} -tags secsel \
2021 -fill [$canv2 cget -selectbackground]]
2022 $canv2 lower $t
2023 }
2024}
2025
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002026proc unbolden {} {
2027 global mainfont boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10002028
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002029 set stillbold {}
2030 foreach row $boldrows {
Paul Mackerras908c3582006-05-20 09:38:11 +10002031 if {![ishighlighted $row]} {
2032 bolden $row $mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002033 } else {
2034 lappend stillbold $row
Paul Mackerras908c3582006-05-20 09:38:11 +10002035 }
2036 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002037 set boldrows $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10002038}
2039
2040proc addvhighlight {n} {
2041 global hlview curview viewdata vhl_done vhighlights commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002042
2043 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10002044 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002045 }
2046 set hlview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002047 if {$n != $curview && ![info exists viewdata($n)]} {
2048 set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}]
2049 set vparentlist($n) {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002050 set vdisporder($n) {}
2051 set vcmitlisted($n) {}
2052 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10002053 }
2054 set vhl_done $commitidx($hlview)
2055 if {$vhl_done > 0} {
2056 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002057 }
2058}
2059
Paul Mackerras908c3582006-05-20 09:38:11 +10002060proc delvhighlight {} {
2061 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002062
2063 if {![info exists hlview]} return
2064 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002065 catch {unset vhighlights}
2066 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002067}
2068
Paul Mackerras908c3582006-05-20 09:38:11 +10002069proc vhighlightmore {} {
2070 global hlview vhl_done commitidx vhighlights
2071 global displayorder vdisporder curview mainfont
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002072
2073 set font [concat $mainfont bold]
2074 set max $commitidx($hlview)
2075 if {$hlview == $curview} {
2076 set disp $displayorder
2077 } else {
2078 set disp $vdisporder($hlview)
2079 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002080 set vr [visiblerows]
2081 set r0 [lindex $vr 0]
2082 set r1 [lindex $vr 1]
2083 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002084 set id [lindex $disp $i]
2085 if {[info exists commitrow($curview,$id)]} {
2086 set row $commitrow($curview,$id)
Paul Mackerras908c3582006-05-20 09:38:11 +10002087 if {$r0 <= $row && $row <= $r1} {
2088 if {![highlighted $row]} {
2089 bolden $row $font
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002090 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002091 set vhighlights($row) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002092 }
2093 }
2094 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002095 set vhl_done $max
2096}
2097
2098proc askvhighlight {row id} {
2099 global hlview vhighlights commitrow iddrawn mainfont
2100
2101 if {[info exists commitrow($hlview,$id)]} {
2102 if {[info exists iddrawn($id)] && ![ishighlighted $row]} {
2103 bolden $row [concat $mainfont bold]
2104 }
2105 set vhighlights($row) 1
2106 } else {
2107 set vhighlights($row) 0
2108 }
2109}
2110
2111proc hfiles_change {name ix op} {
2112 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras63b79192006-05-20 21:31:52 +10002113 global mainfont highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10002114
2115 if {[info exists filehighlight]} {
2116 # delete previous highlights
2117 catch {close $filehighlight}
2118 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002119 catch {unset fhighlights}
2120 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10002121 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10002122 }
Paul Mackerras63b79192006-05-20 21:31:52 +10002123 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002124 after cancel do_file_hl $fh_serial
2125 incr fh_serial
2126 if {$highlight_files ne {}} {
2127 after 300 do_file_hl $fh_serial
2128 }
2129}
2130
Paul Mackerras63b79192006-05-20 21:31:52 +10002131proc makepatterns {l} {
2132 set ret {}
2133 foreach e $l {
2134 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
2135 if {[string index $ee end] eq "/"} {
2136 lappend ret "$ee*"
2137 } else {
2138 lappend ret $ee
2139 lappend ret "$ee/*"
2140 }
2141 }
2142 return $ret
2143}
2144
Paul Mackerras908c3582006-05-20 09:38:11 +10002145proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002146 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002147
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002148 if {$gdttype eq "touching paths:"} {
2149 if {[catch {set paths [shellsplit $highlight_files]}]} return
2150 set highlight_paths [makepatterns $paths]
2151 highlight_filelist
2152 set gdtargs [concat -- $paths]
2153 } else {
2154 set gdtargs [list "-S$highlight_files"]
2155 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002156 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10002157 set filehighlight [open $cmd r+]
2158 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002159 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002160 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002161 drawvisible
2162 flushhighlights
2163}
2164
2165proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002166 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002167
2168 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002169 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10002170 puts $filehighlight ""
2171 flush $filehighlight
2172 }
2173}
2174
2175proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002176 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002177
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002178 lappend fhl_list $id
2179 set fhighlights($row) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10002180 puts $filehighlight $id
2181}
2182
2183proc readfhighlight {} {
2184 global filehighlight fhighlights commitrow curview mainfont iddrawn
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002185 global fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10002186
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002187 if {![info exists filehighlight]} {
2188 return 0
2189 }
2190 set nr 0
2191 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002192 set line [string trim $line]
2193 set i [lsearch -exact $fhl_list $line]
2194 if {$i < 0} continue
2195 for {set j 0} {$j < $i} {incr j} {
2196 set id [lindex $fhl_list $j]
2197 if {[info exists commitrow($curview,$id)]} {
2198 set fhighlights($commitrow($curview,$id)) 0
2199 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002200 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002201 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
2202 if {$line eq {}} continue
2203 if {![info exists commitrow($curview,$line)]} continue
2204 set row $commitrow($curview,$line)
2205 if {[info exists iddrawn($line)] && ![ishighlighted $row]} {
2206 bolden $row [concat $mainfont bold]
2207 }
2208 set fhighlights($row) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002209 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002210 if {[eof $filehighlight]} {
2211 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05002212 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002213 catch {close $filehighlight}
2214 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002215 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10002216 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002217 next_hlcont
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002218 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002219}
2220
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002221proc find_change {name ix op} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002222 global nhighlights mainfont boldnamerows
Paul Mackerras005a2f42007-07-26 22:36:39 +10002223 global findstring findpattern findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10002224
2225 # delete previous highlights, if any
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002226 foreach row $boldnamerows {
2227 bolden_name $row $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10002228 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002229 set boldnamerows {}
2230 catch {unset nhighlights}
2231 unbolden
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002232 unmarkmatches
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002233 if {$findtype ne "Regexp"} {
2234 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
2235 $findstring]
2236 set findpattern "*$e*"
Paul Mackerras908c3582006-05-20 09:38:11 +10002237 }
2238 drawvisible
2239}
2240
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002241proc doesmatch {f} {
2242 global findtype findstring findpattern
2243
2244 if {$findtype eq "Regexp"} {
2245 return [regexp $findstring $f]
2246 } elseif {$findtype eq "IgnCase"} {
2247 return [string match -nocase $findpattern $f]
2248 } else {
2249 return [string match $findpattern $f]
2250 }
2251}
2252
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002253proc askfindhighlight {row id} {
2254 global nhighlights commitinfo iddrawn mainfont
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002255 global findloc
2256 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10002257
2258 if {![info exists commitinfo($id)]} {
2259 getcommit $id
2260 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002261 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10002262 set isbold 0
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002263 set fldtypes {Headline Author Date Committer CDate Comments}
2264 foreach f $info ty $fldtypes {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002265 if {($findloc eq "All fields" || $findloc eq $ty) &&
2266 [doesmatch $f]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002267 if {$ty eq "Author"} {
2268 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002269 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002270 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002271 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10002272 }
2273 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002274 if {$isbold && [info exists iddrawn($id)]} {
2275 set f [concat $mainfont bold]
2276 if {![ishighlighted $row]} {
2277 bolden $row $f
2278 if {$isbold > 1} {
2279 bolden_name $row $f
2280 }
Paul Mackerras908c3582006-05-20 09:38:11 +10002281 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002282 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10002283 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10002284 }
2285 }
2286 set nhighlights($row) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002287}
2288
Paul Mackerras005a2f42007-07-26 22:36:39 +10002289proc markrowmatches {row id} {
2290 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002291
Paul Mackerras005a2f42007-07-26 22:36:39 +10002292 set headline [lindex $commitinfo($id) 0]
2293 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002294 $canv delete match$row
2295 $canv2 delete match$row
Paul Mackerras005a2f42007-07-26 22:36:39 +10002296 if {$findloc eq "All fields" || $findloc eq "Headline"} {
2297 set m [findmatches $headline]
2298 if {$m ne {}} {
2299 markmatches $canv $row $headline $linehtag($row) $m \
2300 [$canv itemcget $linehtag($row) -font] $row
2301 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002302 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10002303 if {$findloc eq "All fields" || $findloc eq "Author"} {
2304 set m [findmatches $author]
2305 if {$m ne {}} {
2306 markmatches $canv2 $row $author $linentag($row) $m \
2307 [$canv2 itemcget $linentag($row) -font] $row
2308 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10002309 }
2310}
2311
Paul Mackerras164ff272006-05-29 19:50:02 +10002312proc vrel_change {name ix op} {
2313 global highlight_related
2314
2315 rhighlight_none
2316 if {$highlight_related ne "None"} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002317 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002318 }
2319}
2320
2321# prepare for testing whether commits are descendents or ancestors of a
2322proc rhighlight_sel {a} {
2323 global descendent desc_todo ancestor anc_todo
2324 global highlight_related rhighlights
2325
2326 catch {unset descendent}
2327 set desc_todo [list $a]
2328 catch {unset ancestor}
2329 set anc_todo [list $a]
2330 if {$highlight_related ne "None"} {
2331 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002332 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10002333 }
2334}
2335
2336proc rhighlight_none {} {
2337 global rhighlights
2338
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002339 catch {unset rhighlights}
2340 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10002341}
2342
2343proc is_descendent {a} {
2344 global curview children commitrow descendent desc_todo
2345
2346 set v $curview
2347 set la $commitrow($v,$a)
2348 set todo $desc_todo
2349 set leftover {}
2350 set done 0
2351 for {set i 0} {$i < [llength $todo]} {incr i} {
2352 set do [lindex $todo $i]
2353 if {$commitrow($v,$do) < $la} {
2354 lappend leftover $do
2355 continue
2356 }
2357 foreach nk $children($v,$do) {
2358 if {![info exists descendent($nk)]} {
2359 set descendent($nk) 1
2360 lappend todo $nk
2361 if {$nk eq $a} {
2362 set done 1
2363 }
2364 }
2365 }
2366 if {$done} {
2367 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2368 return
2369 }
2370 }
2371 set descendent($a) 0
2372 set desc_todo $leftover
2373}
2374
2375proc is_ancestor {a} {
2376 global curview parentlist commitrow ancestor anc_todo
2377
2378 set v $curview
2379 set la $commitrow($v,$a)
2380 set todo $anc_todo
2381 set leftover {}
2382 set done 0
2383 for {set i 0} {$i < [llength $todo]} {incr i} {
2384 set do [lindex $todo $i]
2385 if {![info exists commitrow($v,$do)] || $commitrow($v,$do) > $la} {
2386 lappend leftover $do
2387 continue
2388 }
2389 foreach np [lindex $parentlist $commitrow($v,$do)] {
2390 if {![info exists ancestor($np)]} {
2391 set ancestor($np) 1
2392 lappend todo $np
2393 if {$np eq $a} {
2394 set done 1
2395 }
2396 }
2397 }
2398 if {$done} {
2399 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
2400 return
2401 }
2402 }
2403 set ancestor($a) 0
2404 set anc_todo $leftover
2405}
2406
2407proc askrelhighlight {row id} {
2408 global descendent highlight_related iddrawn mainfont rhighlights
2409 global selectedline ancestor
2410
2411 if {![info exists selectedline]} return
2412 set isbold 0
2413 if {$highlight_related eq "Descendent" ||
2414 $highlight_related eq "Not descendent"} {
2415 if {![info exists descendent($id)]} {
2416 is_descendent $id
2417 }
2418 if {$descendent($id) == ($highlight_related eq "Descendent")} {
2419 set isbold 1
2420 }
2421 } elseif {$highlight_related eq "Ancestor" ||
2422 $highlight_related eq "Not ancestor"} {
2423 if {![info exists ancestor($id)]} {
2424 is_ancestor $id
2425 }
2426 if {$ancestor($id) == ($highlight_related eq "Ancestor")} {
2427 set isbold 1
2428 }
2429 }
2430 if {[info exists iddrawn($id)]} {
2431 if {$isbold && ![ishighlighted $row]} {
2432 bolden $row [concat $mainfont bold]
2433 }
2434 }
2435 set rhighlights($row) $isbold
2436}
2437
Paul Mackerras4e7d6772006-05-30 21:33:07 +10002438proc next_hlcont {} {
2439 global fhl_row fhl_dirn displayorder numcommits
2440 global vhighlights fhighlights nhighlights rhighlights
2441 global hlview filehighlight findstring highlight_related
2442
2443 if {![info exists fhl_dirn] || $fhl_dirn == 0} return
2444 set row $fhl_row
2445 while {1} {
2446 if {$row < 0 || $row >= $numcommits} {
2447 bell
2448 set fhl_dirn 0
2449 return
2450 }
2451 set id [lindex $displayorder $row]
2452 if {[info exists hlview]} {
2453 if {![info exists vhighlights($row)]} {
2454 askvhighlight $row $id
2455 }
2456 if {$vhighlights($row) > 0} break
2457 }
2458 if {$findstring ne {}} {
2459 if {![info exists nhighlights($row)]} {
2460 askfindhighlight $row $id
2461 }
2462 if {$nhighlights($row) > 0} break
2463 }
2464 if {$highlight_related ne "None"} {
2465 if {![info exists rhighlights($row)]} {
2466 askrelhighlight $row $id
2467 }
2468 if {$rhighlights($row) > 0} break
2469 }
2470 if {[info exists filehighlight]} {
2471 if {![info exists fhighlights($row)]} {
2472 # ask for a few more while we're at it...
2473 set r $row
2474 for {set n 0} {$n < 100} {incr n} {
2475 if {![info exists fhighlights($r)]} {
2476 askfilehighlight $r [lindex $displayorder $r]
2477 }
2478 incr r $fhl_dirn
2479 if {$r < 0 || $r >= $numcommits} break
2480 }
2481 flushhighlights
2482 }
2483 if {$fhighlights($row) < 0} {
2484 set fhl_row $row
2485 return
2486 }
2487 if {$fhighlights($row) > 0} break
2488 }
2489 incr row $fhl_dirn
2490 }
2491 set fhl_dirn 0
2492 selectline $row 1
2493}
2494
2495proc next_highlight {dirn} {
2496 global selectedline fhl_row fhl_dirn
2497 global hlview filehighlight findstring highlight_related
2498
2499 if {![info exists selectedline]} return
2500 if {!([info exists hlview] || $findstring ne {} ||
2501 $highlight_related ne "None" || [info exists filehighlight])} return
2502 set fhl_row [expr {$selectedline + $dirn}]
2503 set fhl_dirn $dirn
2504 next_hlcont
2505}
2506
2507proc cancel_next_highlight {} {
2508 global fhl_dirn
2509
2510 set fhl_dirn 0
2511}
2512
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002513# Graph layout functions
2514
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002515proc shortids {ids} {
2516 set res {}
2517 foreach id $ids {
2518 if {[llength $id] > 1} {
2519 lappend res [shortids $id]
2520 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
2521 lappend res [string range $id 0 7]
2522 } else {
2523 lappend res $id
2524 }
2525 }
2526 return $res
2527}
2528
2529proc incrange {l x o} {
2530 set n [llength $l]
2531 while {$x < $n} {
2532 set e [lindex $l $x]
2533 if {$e ne {}} {
2534 lset l $x [expr {$e + $o}]
2535 }
2536 incr x
2537 }
2538 return $l
2539}
2540
2541proc ntimes {n o} {
2542 set ret {}
2543 for {} {$n > 0} {incr n -1} {
2544 lappend ret $o
2545 }
2546 return $ret
2547}
2548
2549proc usedinrange {id l1 l2} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002550 global children commitrow curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002551
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002552 if {[info exists commitrow($curview,$id)]} {
2553 set r $commitrow($curview,$id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002554 if {$l1 <= $r && $r <= $l2} {
2555 return [expr {$r - $l1 + 1}]
2556 }
2557 }
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002558 set kids $children($curview,$id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002559 foreach c $kids {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002560 set r $commitrow($curview,$c)
Paul Mackerras22626ef2006-04-17 09:56:02 +10002561 if {$l1 <= $r && $r <= $l2} {
2562 return [expr {$r - $l1 + 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002563 }
2564 }
2565 return 0
2566}
2567
2568proc sanity {row {full 0}} {
2569 global rowidlist rowoffsets
2570
2571 set col -1
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002572 set ids [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002573 foreach id $ids {
2574 incr col
2575 if {$id eq {}} continue
2576 if {$col < [llength $ids] - 1 &&
2577 [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002578 puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}"
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002579 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002580 set o [lindex $rowoffsets $row $col]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002581 set y $row
2582 set x $col
2583 while {$o ne {}} {
2584 incr y -1
2585 incr x $o
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002586 if {[lindex $rowidlist $y $x] != $id} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002587 puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]"
2588 puts " id=[shortids $id] check started at row $row"
2589 for {set i $row} {$i >= $y} {incr i -1} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002590 puts " row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}"
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002591 }
2592 break
2593 }
2594 if {!$full} break
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002595 set o [lindex $rowoffsets $y $x]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002596 }
2597 }
2598}
2599
2600proc makeuparrow {oid x y z} {
Paul Mackerras66e46f32006-10-14 19:21:02 +10002601 global rowidlist rowoffsets uparrowlen idrowranges displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002602
2603 for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
2604 incr y -1
2605 incr x $z
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002606 set off0 [lindex $rowoffsets $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002607 for {set x0 $x} {1} {incr x0} {
2608 if {$x0 >= [llength $off0]} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002609 set x0 [llength [lindex $rowoffsets [expr {$y-1}]]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002610 break
2611 }
2612 set z [lindex $off0 $x0]
2613 if {$z ne {}} {
2614 incr x0 $z
2615 break
2616 }
2617 }
2618 set z [expr {$x0 - $x}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002619 lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid]
2620 lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002621 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002622 set tmp [lreplace [lindex $rowoffsets $y] $x $x {}]
2623 lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1]
Paul Mackerras66e46f32006-10-14 19:21:02 +10002624 lappend idrowranges($oid) [lindex $displayorder $y]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002625}
2626
2627proc initlayout {} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10002628 global rowidlist rowoffsets displayorder commitlisted
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002629 global rowlaidout rowoptim
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002630 global idinlist rowchk rowrangelist idrowranges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002631 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002632 global nextcolor
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002633 global parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002634 global colormap rowtextx
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002635 global selectfirst
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002636
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002637 set numcommits 0
2638 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10002639 set commitlisted {}
2640 set parentlist {}
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002641 set rowrangelist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002642 set nextcolor 0
2643 set rowidlist {{}}
2644 set rowoffsets {{}}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002645 catch {unset idinlist}
2646 catch {unset rowchk}
2647 set rowlaidout 0
2648 set rowoptim 0
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002649 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002650 catch {unset colormap}
2651 catch {unset rowtextx}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002652 catch {unset idrowranges}
Paul Mackerrase507fd42007-06-16 21:51:08 +10002653 set selectfirst 1
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002654}
2655
2656proc setcanvscroll {} {
2657 global canv canv2 canv3 numcommits linespc canvxmax canvy0
2658
2659 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
2660 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
2661 $canv2 conf -scrollregion [list 0 0 0 $ymax]
2662 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002663}
2664
2665proc visiblerows {} {
2666 global canv numcommits linespc
2667
2668 set ymax [lindex [$canv cget -scrollregion] 3]
2669 if {$ymax eq {} || $ymax == 0} return
2670 set f [$canv yview]
2671 set y0 [expr {int([lindex $f 0] * $ymax)}]
2672 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
2673 if {$r0 < 0} {
2674 set r0 0
2675 }
2676 set y1 [expr {int([lindex $f 1] * $ymax)}]
2677 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
2678 if {$r1 >= $numcommits} {
2679 set r1 [expr {$numcommits - 1}]
2680 }
2681 return [list $r0 $r1]
2682}
2683
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002684proc layoutmore {tmax allread} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002685 global rowlaidout rowoptim commitidx numcommits optim_delay
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002686 global uparrowlen curview rowidlist idinlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002687
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002688 set showlast 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002689 set showdelay $optim_delay
2690 set optdelay [expr {$uparrowlen + 1}]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002691 while {1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002692 if {$rowoptim - $showdelay > $numcommits} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002693 showstuff [expr {$rowoptim - $showdelay}] $showlast
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002694 } elseif {$rowlaidout - $optdelay > $rowoptim} {
2695 set nr [expr {$rowlaidout - $optdelay - $rowoptim}]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002696 if {$nr > 100} {
2697 set nr 100
2698 }
2699 optimize_rows $rowoptim 0 [expr {$rowoptim + $nr}]
2700 incr rowoptim $nr
2701 } elseif {$commitidx($curview) > $rowlaidout} {
2702 set nr [expr {$commitidx($curview) - $rowlaidout}]
2703 # may need to increase this threshold if uparrowlen or
2704 # mingaplen are increased...
2705 if {$nr > 150} {
2706 set nr 150
2707 }
2708 set row $rowlaidout
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002709 set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread]
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002710 if {$rowlaidout == $row} {
2711 return 0
2712 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002713 } elseif {$allread} {
2714 set optdelay 0
2715 set nrows $commitidx($curview)
2716 if {[lindex $rowidlist $nrows] ne {} ||
2717 [array names idinlist] ne {}} {
2718 layouttail
2719 set rowlaidout $commitidx($curview)
2720 } elseif {$rowoptim == $nrows} {
2721 set showdelay 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002722 set showlast 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10002723 if {$numcommits == $nrows} {
2724 return 0
2725 }
2726 }
Paul Mackerrasd1e46752006-08-16 20:02:32 +10002727 } else {
2728 return 0
2729 }
2730 if {$tmax ne {} && [clock clicks -milliseconds] >= $tmax} {
2731 return 1
2732 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002733 }
2734}
2735
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002736proc showstuff {canshow last} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002737 global numcommits commitrow pending_select selectedline curview
Paul Mackerras8f489362007-07-13 19:49:37 +10002738 global lookingforhead mainheadid displayorder selectfirst
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002739 global lastscrollset
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002740
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002741 if {$numcommits == 0} {
2742 global phase
2743 set phase "incrdraw"
2744 allcanvs delete all
2745 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002746 set r0 $numcommits
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002747 set prev $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002748 set numcommits $canshow
Paul Mackerrasa2c22362006-10-31 15:00:53 +11002749 set t [clock clicks -milliseconds]
2750 if {$prev < 100 || $last || $t - $lastscrollset > 500} {
2751 set lastscrollset $t
2752 setcanvscroll
2753 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002754 set rows [visiblerows]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002755 set r1 [lindex $rows 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002756 if {$r1 >= $canshow} {
2757 set r1 [expr {$canshow - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002758 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002759 if {$r0 <= $r1} {
2760 drawcommits $r0 $r1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002761 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002762 if {[info exists pending_select] &&
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002763 [info exists commitrow($curview,$pending_select)] &&
2764 $commitrow($curview,$pending_select) < $numcommits} {
2765 selectline $commitrow($curview,$pending_select) 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002766 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10002767 if {$selectfirst} {
2768 if {[info exists selectedline] || [info exists pending_select]} {
2769 set selectfirst 0
2770 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10002771 set l [first_real_row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002772 selectline $l 1
Paul Mackerrase507fd42007-06-16 21:51:08 +10002773 set selectfirst 0
2774 }
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10002775 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002776 if {$lookingforhead && [info exists commitrow($curview,$mainheadid)]
2777 && ($last || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2778 set lookingforhead 0
2779 dodiffindex
2780 }
2781}
2782
2783proc doshowlocalchanges {} {
2784 global lookingforhead curview mainheadid phase commitrow
2785
2786 if {[info exists commitrow($curview,$mainheadid)] &&
2787 ($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
2788 dodiffindex
2789 } elseif {$phase ne {}} {
2790 set lookingforhead 1
2791 }
2792}
2793
2794proc dohidelocalchanges {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002795 global lookingforhead localfrow localirow lserial
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002796
2797 set lookingforhead 0
Paul Mackerras8f489362007-07-13 19:49:37 +10002798 if {$localfrow >= 0} {
2799 removerow $localfrow
2800 set localfrow -1
2801 if {$localirow > 0} {
2802 incr localirow -1
2803 }
2804 }
2805 if {$localirow >= 0} {
2806 removerow $localirow
2807 set localirow -1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002808 }
2809 incr lserial
2810}
2811
Paul Mackerras8f489362007-07-13 19:49:37 +10002812# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002813proc dodiffindex {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002814 global localirow localfrow lserial
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002815
2816 incr lserial
Paul Mackerras8f489362007-07-13 19:49:37 +10002817 set localfrow -1
2818 set localirow -1
2819 set fd [open "|git diff-index --cached HEAD" r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002820 fconfigure $fd -blocking 0
2821 filerun $fd [list readdiffindex $fd $lserial]
2822}
2823
2824proc readdiffindex {fd serial} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002825 global localirow commitrow mainheadid nullid2 curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002826 global commitinfo commitdata lserial
2827
Paul Mackerras8f489362007-07-13 19:49:37 +10002828 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002829 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10002830 if {![eof $fd]} {
2831 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002832 }
Paul Mackerras8f489362007-07-13 19:49:37 +10002833 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002834 }
2835 # we only need to see one line and we don't really care what it says...
2836 close $fd
2837
Paul Mackerras8f489362007-07-13 19:49:37 +10002838 # now see if there are any local changes not checked in to the index
2839 if {$serial == $lserial} {
2840 set fd [open "|git diff-files" r]
2841 fconfigure $fd -blocking 0
2842 filerun $fd [list readdifffiles $fd $serial]
2843 }
2844
2845 if {$isdiff && $serial == $lserial && $localirow == -1} {
2846 # add the line for the changes in the index to the graph
2847 set localirow $commitrow($curview,$mainheadid)
2848 set hl "Local changes checked in to index but not committed"
2849 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
2850 set commitdata($nullid2) "\n $hl\n"
2851 insertrow $localirow $nullid2
2852 }
2853 return 0
2854}
2855
2856proc readdifffiles {fd serial} {
2857 global localirow localfrow commitrow mainheadid nullid curview
2858 global commitinfo commitdata lserial
2859
2860 set isdiff 1
2861 if {[gets $fd line] < 0} {
2862 if {![eof $fd]} {
2863 return 1
2864 }
2865 set isdiff 0
2866 }
2867 # we only need to see one line and we don't really care what it says...
2868 close $fd
2869
2870 if {$isdiff && $serial == $lserial && $localfrow == -1} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002871 # add the line for the local diff to the graph
Paul Mackerras8f489362007-07-13 19:49:37 +10002872 if {$localirow >= 0} {
2873 set localfrow $localirow
2874 incr localirow
2875 } else {
2876 set localfrow $commitrow($curview,$mainheadid)
2877 }
2878 set hl "Local uncommitted changes, not checked in to index"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002879 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
2880 set commitdata($nullid) "\n $hl\n"
Paul Mackerras8f489362007-07-13 19:49:37 +10002881 insertrow $localfrow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002882 }
2883 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002884}
2885
2886proc layoutrows {row endrow last} {
2887 global rowidlist rowoffsets displayorder
2888 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002889 global children parentlist
Paul Mackerras322a8cc2006-10-15 18:03:46 +10002890 global idrowranges
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002891 global commitidx curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10002892 global idinlist rowchk rowrangelist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002893
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002894 set idlist [lindex $rowidlist $row]
2895 set offs [lindex $rowoffsets $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002896 while {$row < $endrow} {
2897 set id [lindex $displayorder $row]
Paul Mackerras7b459a12007-08-13 14:52:00 +10002898 set nev [expr {[llength $idlist] - $maxwidth + 1}]
Paul Mackerras79b2c752006-04-02 20:47:40 +10002899 foreach p [lindex $parentlist $row] {
Paul Mackerras7b459a12007-08-13 14:52:00 +10002900 if {![info exists idinlist($p)] || !$idinlist($p)} {
2901 incr nev
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002902 }
2903 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002904 if {$nev > 0} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10002905 if {!$last &&
2906 $row + $uparrowlen + $mingaplen >= $commitidx($curview)} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002907 for {set x [llength $idlist]} {[incr x -1] >= 0} {} {
2908 set i [lindex $idlist $x]
2909 if {![info exists rowchk($i)] || $row >= $rowchk($i)} {
2910 set r [usedinrange $i [expr {$row - $downarrowlen}] \
2911 [expr {$row + $uparrowlen + $mingaplen}]]
2912 if {$r == 0} {
2913 set idlist [lreplace $idlist $x $x]
2914 set offs [lreplace $offs $x $x]
2915 set offs [incrange $offs $x 1]
2916 set idinlist($i) 0
Paul Mackerrasd8d2df02006-03-18 20:42:46 +11002917 set rm1 [expr {$row - 1}]
Paul Mackerras66e46f32006-10-14 19:21:02 +10002918 lappend idrowranges($i) [lindex $displayorder $rm1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002919 if {[incr nev -1] <= 0} break
2920 continue
2921 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10002922 set rowchk($i) [expr {$row + $r}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002923 }
2924 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002925 lset rowidlist $row $idlist
2926 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002927 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10002928 set oldolds {}
2929 set newolds {}
2930 foreach p [lindex $parentlist $row] {
2931 if {![info exists idinlist($p)]} {
2932 lappend newolds $p
2933 } elseif {!$idinlist($p)} {
2934 lappend oldolds $p
2935 }
2936 set idinlist($p) 1
2937 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002938 set col [lsearch -exact $idlist $id]
2939 if {$col < 0} {
2940 set col [llength $idlist]
2941 lappend idlist $id
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002942 lset rowidlist $row $idlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002943 set z {}
Paul Mackerras6a90bff2007-06-18 09:48:23 +10002944 if {$children($curview,$id) ne {}} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002945 set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002946 unset idinlist($id)
2947 }
2948 lappend offs $z
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002949 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002950 if {$z ne {}} {
2951 makeuparrow $id $col $row $z
2952 }
2953 } else {
2954 unset idinlist($id)
2955 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002956 set ranges {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002957 if {[info exists idrowranges($id)]} {
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002958 set ranges $idrowranges($id)
Paul Mackerras66e46f32006-10-14 19:21:02 +10002959 lappend ranges $id
Paul Mackerras22626ef2006-04-17 09:56:02 +10002960 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002961 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002962 lappend rowrangelist $ranges
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002963 incr row
2964 set offs [ntimes [llength $idlist] 0]
2965 set l [llength $newolds]
2966 set idlist [eval lreplace \$idlist $col $col $newolds]
2967 set o 0
2968 if {$l != 1} {
2969 set offs [lrange $offs 0 [expr {$col - 1}]]
2970 foreach x $newolds {
2971 lappend offs {}
2972 incr o -1
2973 }
2974 incr o
2975 set tmp [expr {[llength $idlist] - [llength $offs]}]
2976 if {$tmp > 0} {
2977 set offs [concat $offs [ntimes $tmp $o]]
2978 }
2979 } else {
2980 lset offs $col {}
2981 }
2982 foreach i $newolds {
Paul Mackerras66e46f32006-10-14 19:21:02 +10002983 set idrowranges($i) $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002984 }
2985 incr col $l
2986 foreach oid $oldolds {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002987 set idlist [linsert $idlist $col $oid]
2988 set offs [linsert $offs $col $o]
2989 makeuparrow $oid $col $row $o
2990 incr col
2991 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11002992 lappend rowidlist $idlist
2993 lappend rowoffsets $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002994 }
2995 return $row
2996}
2997
2998proc addextraid {id row} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10002999 global displayorder commitrow commitinfo
Paul Mackerrase7da3472006-04-17 10:27:59 +10003000 global commitidx commitlisted
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003001 global parentlist children curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003002
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003003 incr commitidx($curview)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003004 lappend displayorder $id
Paul Mackerrase7da3472006-04-17 10:27:59 +10003005 lappend commitlisted 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10003006 lappend parentlist {}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003007 set commitrow($curview,$id) $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003008 readcommit $id
3009 if {![info exists commitinfo($id)]} {
3010 set commitinfo($id) {"No commit information available"}
Paul Mackerras79b2c752006-04-02 20:47:40 +10003011 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003012 if {![info exists children($curview,$id)]} {
3013 set children($curview,$id) {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003014 }
3015}
3016
3017proc layouttail {} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003018 global rowidlist rowoffsets idinlist commitidx curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003019 global idrowranges rowrangelist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003020
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003021 set row $commitidx($curview)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003022 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003023 while {$idlist ne {}} {
3024 set col [expr {[llength $idlist] - 1}]
3025 set id [lindex $idlist $col]
3026 addextraid $id $row
Paul Mackerras67a4f1a2007-08-12 17:23:47 +10003027 catch {unset idinlist($id)}
Paul Mackerras8c939172007-07-09 22:29:24 +10003028 lappend idrowranges($id) $id
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003029 lappend rowrangelist $idrowranges($id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10003030 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003031 incr row
3032 set offs [ntimes $col 0]
3033 set idlist [lreplace $idlist $col $col]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003034 lappend rowidlist $idlist
3035 lappend rowoffsets $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003036 }
3037
3038 foreach id [array names idinlist] {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003039 unset idinlist($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003040 addextraid $id $row
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003041 lset rowidlist $row [list $id]
3042 lset rowoffsets $row 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003043 makeuparrow $id 0 $row 0
Paul Mackerras8c939172007-07-09 22:29:24 +10003044 lappend idrowranges($id) $id
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003045 lappend rowrangelist $idrowranges($id)
Paul Mackerras22626ef2006-04-17 09:56:02 +10003046 unset idrowranges($id)
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003047 incr row
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003048 lappend rowidlist {}
3049 lappend rowoffsets {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003050 }
3051}
3052
3053proc insert_pad {row col npad} {
3054 global rowidlist rowoffsets
3055
3056 set pad [ntimes $npad {}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003057 lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad]
3058 set tmp [eval linsert [list [lindex $rowoffsets $row]] $col $pad]
3059 lset rowoffsets $row [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003060}
3061
3062proc optimize_rows {row col endrow} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003063 global rowidlist rowoffsets displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003064
3065 for {} {$row < $endrow} {incr row} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003066 set idlist [lindex $rowidlist $row]
3067 set offs [lindex $rowoffsets $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003068 set haspad 0
3069 for {} {$col < [llength $offs]} {incr col} {
3070 if {[lindex $idlist $col] eq {}} {
3071 set haspad 1
3072 continue
3073 }
3074 set z [lindex $offs $col]
3075 if {$z eq {}} continue
3076 set isarrow 0
3077 set x0 [expr {$col + $z}]
3078 set y0 [expr {$row - 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003079 set z0 [lindex $rowoffsets $y0 $x0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003080 if {$z0 eq {}} {
3081 set id [lindex $idlist $col]
Paul Mackerras22626ef2006-04-17 09:56:02 +10003082 set ranges [rowranges $id]
3083 if {$ranges ne {} && $y0 > [lindex $ranges 0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003084 set isarrow 1
3085 }
3086 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10003087 # Looking at lines from this row to the previous row,
3088 # make them go straight up if they end in an arrow on
3089 # the previous row; otherwise make them go straight up
3090 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003091 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10003092 # Line currently goes left too much;
3093 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003094 set npad [expr {-1 - $z + $isarrow}]
3095 set offs [incrange $offs $col $npad]
3096 insert_pad $y0 $x0 $npad
3097 if {$y0 > 0} {
3098 optimize_rows $y0 $x0 $row
3099 }
3100 set z [lindex $offs $col]
3101 set x0 [expr {$col + $z}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003102 set z0 [lindex $rowoffsets $y0 $x0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003103 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10003104 # Line currently goes right too much;
3105 # insert pads in this line and adjust the next's rowoffsets
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003106 set npad [expr {$z - 1 + $isarrow}]
3107 set y1 [expr {$row + 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003108 set offs2 [lindex $rowoffsets $y1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003109 set x1 -1
3110 foreach z $offs2 {
3111 incr x1
3112 if {$z eq {} || $x1 + $z < $col} continue
3113 if {$x1 + $z > $col} {
3114 incr npad
3115 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003116 lset rowoffsets $y1 [incrange $offs2 $x1 $npad]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003117 break
3118 }
3119 set pad [ntimes $npad {}]
3120 set idlist [eval linsert \$idlist $col $pad]
3121 set tmp [eval linsert \$offs $col $pad]
3122 incr col $npad
3123 set offs [incrange $tmp $col [expr {-$npad}]]
3124 set z [lindex $offs $col]
3125 set haspad 1
3126 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11003127 if {$z0 eq {} && !$isarrow} {
3128 # this line links to its first child on row $row-2
3129 set rm2 [expr {$row - 2}]
3130 set id [lindex $displayorder $rm2]
3131 set xc [lsearch -exact [lindex $rowidlist $rm2] $id]
3132 if {$xc >= 0} {
3133 set z0 [expr {$xc - $x0}]
3134 }
3135 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10003136 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003137 if {$z0 ne {} && $z < 0 && $z0 > 0} {
3138 insert_pad $y0 $x0 1
3139 set offs [incrange $offs $col 1]
3140 optimize_rows $y0 [expr {$x0 + 1}] $row
3141 }
3142 }
3143 if {!$haspad} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003144 set o {}
Paul Mackerras3fc42792006-09-15 09:45:23 +10003145 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003146 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
3147 set o [lindex $offs $col]
Paul Mackerraseb447a12006-03-18 23:11:37 +11003148 if {$o eq {}} {
3149 # check if this is the link to the first child
3150 set id [lindex $idlist $col]
Paul Mackerras22626ef2006-04-17 09:56:02 +10003151 set ranges [rowranges $id]
3152 if {$ranges ne {} && $row == [lindex $ranges 0]} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003153 # it is, work out offset to child
3154 set y0 [expr {$row - 1}]
3155 set id [lindex $displayorder $y0]
3156 set x0 [lsearch -exact [lindex $rowidlist $y0] $id]
3157 if {$x0 >= 0} {
3158 set o [expr {$x0 - $col}]
3159 }
3160 }
3161 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003162 if {$o eq {} || $o <= 0} break
3163 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10003164 # Insert a pad at that column as long as it has a line and
3165 # isn't the last column, and adjust the next row' offsets
Paul Mackerraseb447a12006-03-18 23:11:37 +11003166 if {$o ne {} && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003167 set y1 [expr {$row + 1}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003168 set offs2 [lindex $rowoffsets $y1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003169 set x1 -1
3170 foreach z $offs2 {
3171 incr x1
3172 if {$z eq {} || $x1 + $z < $col} continue
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003173 lset rowoffsets $y1 [incrange $offs2 $x1 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003174 break
3175 }
3176 set idlist [linsert $idlist $col {}]
3177 set tmp [linsert $offs $col {}]
3178 incr col
3179 set offs [incrange $tmp $col -1]
3180 }
3181 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003182 lset rowidlist $row $idlist
3183 lset rowoffsets $row $offs
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003184 set col 0
3185 }
3186}
3187
3188proc xc {row col} {
3189 global canvx0 linespc
3190 return [expr {$canvx0 + $col * $linespc}]
3191}
3192
3193proc yc {row} {
3194 global canvy0 linespc
3195 return [expr {$canvy0 + $row * $linespc}]
3196}
3197
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003198proc linewidth {id} {
3199 global thickerline lthickness
3200
3201 set wid $lthickness
3202 if {[info exists thickerline] && $id eq $thickerline} {
3203 set wid [expr {2 * $lthickness}]
3204 }
3205 return $wid
3206}
3207
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003208proc rowranges {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003209 global phase idrowranges commitrow rowlaidout rowrangelist curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003210
3211 set ranges {}
Paul Mackerras22626ef2006-04-17 09:56:02 +10003212 if {$phase eq {} ||
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003213 ([info exists commitrow($curview,$id)]
3214 && $commitrow($curview,$id) < $rowlaidout)} {
3215 set ranges [lindex $rowrangelist $commitrow($curview,$id)]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003216 } elseif {[info exists idrowranges($id)]} {
3217 set ranges $idrowranges($id)
3218 }
Paul Mackerras66e46f32006-10-14 19:21:02 +10003219 set linenos {}
3220 foreach rid $ranges {
3221 lappend linenos $commitrow($curview,$rid)
3222 }
3223 if {$linenos ne {}} {
3224 lset linenos 0 [expr {[lindex $linenos 0] + 1}]
3225 }
3226 return $linenos
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003227}
3228
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003229# work around tk8.4 refusal to draw arrows on diagonal segments
3230proc adjarrowhigh {coords} {
3231 global linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003232
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003233 set x0 [lindex $coords 0]
3234 set x1 [lindex $coords 2]
3235 if {$x0 != $x1} {
3236 set y0 [lindex $coords 1]
3237 set y1 [lindex $coords 3]
3238 if {$y0 - $y1 <= 2 * $linespc && $x1 == [lindex $coords 4]} {
3239 # we have a nearby vertical segment, just trim off the diag bit
3240 set coords [lrange $coords 2 end]
3241 } else {
3242 set slope [expr {($x0 - $x1) / ($y0 - $y1)}]
3243 set xi [expr {$x0 - $slope * $linespc / 2}]
3244 set yi [expr {$y0 - $linespc / 2}]
3245 set coords [lreplace $coords 0 1 $xi $y0 $xi $yi]
Paul Mackerraseb447a12006-03-18 23:11:37 +11003246 }
3247 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003248 return $coords
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003249}
3250
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003251proc drawlineseg {id row endrow arrowlow} {
3252 global rowidlist displayorder iddrawn linesegs
3253 global canv colormap linespc curview maxlinelen
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003254
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003255 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
3256 set le [expr {$row + 1}]
3257 set arrowhigh 1
3258 while {1} {
3259 set c [lsearch -exact [lindex $rowidlist $le] $id]
3260 if {$c < 0} {
3261 incr le -1
3262 break
3263 }
3264 lappend cols $c
3265 set x [lindex $displayorder $le]
3266 if {$x eq $id} {
3267 set arrowhigh 0
3268 break
3269 }
3270 if {[info exists iddrawn($x)] || $le == $endrow} {
3271 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
3272 if {$c >= 0} {
3273 lappend cols $c
3274 set arrowhigh 0
3275 }
3276 break
3277 }
3278 incr le
3279 }
3280 if {$le <= $row} {
3281 return $row
3282 }
3283
3284 set lines {}
3285 set i 0
3286 set joinhigh 0
3287 if {[info exists linesegs($id)]} {
3288 set lines $linesegs($id)
3289 foreach li $lines {
3290 set r0 [lindex $li 0]
3291 if {$r0 > $row} {
3292 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
3293 set joinhigh 1
3294 }
3295 break
3296 }
3297 incr i
3298 }
3299 }
3300 set joinlow 0
3301 if {$i > 0} {
3302 set li [lindex $lines [expr {$i-1}]]
3303 set r1 [lindex $li 1]
3304 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
3305 set joinlow 1
3306 }
3307 }
3308
3309 set x [lindex $cols [expr {$le - $row}]]
3310 set xp [lindex $cols [expr {$le - 1 - $row}]]
3311 set dir [expr {$xp - $x}]
3312 if {$joinhigh} {
3313 set ith [lindex $lines $i 2]
3314 set coords [$canv coords $ith]
3315 set ah [$canv itemcget $ith -arrow]
3316 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
3317 set x2 [lindex $cols [expr {$le + 1 - $row}]]
3318 if {$x2 ne {} && $x - $x2 == $dir} {
3319 set coords [lrange $coords 0 end-2]
3320 }
3321 } else {
3322 set coords [list [xc $le $x] [yc $le]]
3323 }
3324 if {$joinlow} {
3325 set itl [lindex $lines [expr {$i-1}] 2]
3326 set al [$canv itemcget $itl -arrow]
3327 set arrowlow [expr {$al eq "last" || $al eq "both"}]
3328 } elseif {$arrowlow &&
3329 [lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0} {
3330 set arrowlow 0
3331 }
3332 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
3333 for {set y $le} {[incr y -1] > $row} {} {
3334 set x $xp
3335 set xp [lindex $cols [expr {$y - 1 - $row}]]
3336 set ndir [expr {$xp - $x}]
3337 if {$dir != $ndir || $xp < 0} {
3338 lappend coords [xc $y $x] [yc $y]
3339 }
3340 set dir $ndir
3341 }
3342 if {!$joinlow} {
3343 if {$xp < 0} {
3344 # join parent line to first child
3345 set ch [lindex $displayorder $row]
3346 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
3347 if {$xc < 0} {
3348 puts "oops: drawlineseg: child $ch not on row $row"
3349 } else {
3350 if {$xc < $x - 1} {
3351 lappend coords [xc $row [expr {$x-1}]] [yc $row]
3352 } elseif {$xc > $x + 1} {
3353 lappend coords [xc $row [expr {$x+1}]] [yc $row]
3354 }
3355 set x $xc
3356 }
3357 lappend coords [xc $row $x] [yc $row]
3358 } else {
3359 set xn [xc $row $xp]
3360 set yn [yc $row]
3361 # work around tk8.4 refusal to draw arrows on diagonal segments
3362 if {$arrowlow && $xn != [lindex $coords end-1]} {
3363 if {[llength $coords] < 4 ||
3364 [lindex $coords end-3] != [lindex $coords end-1] ||
3365 [lindex $coords end] - $yn > 2 * $linespc} {
3366 set xn [xc $row [expr {$xp - 0.5 * $dir}]]
3367 set yo [yc [expr {$row + 0.5}]]
3368 lappend coords $xn $yo $xn $yn
3369 }
3370 } else {
3371 lappend coords $xn $yn
3372 }
3373 }
3374 if {!$joinhigh} {
3375 if {$arrowhigh} {
3376 set coords [adjarrowhigh $coords]
3377 }
3378 assigncolor $id
3379 set t [$canv create line $coords -width [linewidth $id] \
3380 -fill $colormap($id) -tags lines.$id -arrow $arrow]
3381 $canv lower $t
3382 bindline $t $id
3383 set lines [linsert $lines $i [list $row $le $t]]
3384 } else {
3385 $canv coords $ith $coords
3386 if {$arrow ne $ah} {
3387 $canv itemconf $ith -arrow $arrow
3388 }
3389 lset lines $i 0 $row
3390 }
3391 } else {
3392 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
3393 set ndir [expr {$xo - $xp}]
3394 set clow [$canv coords $itl]
3395 if {$dir == $ndir} {
3396 set clow [lrange $clow 2 end]
3397 }
3398 set coords [concat $coords $clow]
3399 if {!$joinhigh} {
3400 lset lines [expr {$i-1}] 1 $le
3401 if {$arrowhigh} {
3402 set coords [adjarrowhigh $coords]
3403 }
3404 } else {
3405 # coalesce two pieces
3406 $canv delete $ith
3407 set b [lindex $lines [expr {$i-1}] 0]
3408 set e [lindex $lines $i 1]
3409 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
3410 }
3411 $canv coords $itl $coords
3412 if {$arrow ne $al} {
3413 $canv itemconf $itl -arrow $arrow
3414 }
3415 }
3416
3417 set linesegs($id) $lines
3418 return $le
3419}
3420
3421proc drawparentlinks {id row} {
3422 global rowidlist canv colormap curview parentlist
3423 global idpos
3424
3425 set rowids [lindex $rowidlist $row]
3426 set col [lsearch -exact $rowids $id]
3427 if {$col < 0} return
3428 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003429 set row2 [expr {$row + 1}]
3430 set x [xc $row $col]
3431 set y [yc $row]
3432 set y2 [yc $row2]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003433 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003434 # rmx = right-most X coord used
3435 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003436 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11003437 set i [lsearch -exact $ids $p]
3438 if {$i < 0} {
3439 puts "oops, parent $p of $id not in list"
3440 continue
3441 }
3442 set x2 [xc $row2 $i]
3443 if {$x2 > $rmx} {
3444 set rmx $x2
3445 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003446 if {[lsearch -exact $rowids $p] < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11003447 # drawlineseg will do this one for us
3448 continue
3449 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003450 assigncolor $p
3451 # should handle duplicated parents here...
3452 set coords [list $x $y]
3453 if {$i < $col - 1} {
3454 lappend coords [xc $row [expr {$i + 1}]] $y
3455 } elseif {$i > $col + 1} {
3456 lappend coords [xc $row [expr {$i - 1}]] $y
3457 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003458 lappend coords $x2 $y2
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003459 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003460 -fill $colormap($p) -tags lines.$p]
3461 $canv lower $t
3462 bindline $t $p
3463 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003464 if {$rmx > [lindex $idpos($id) 1]} {
3465 lset idpos($id) 1 $rmx
3466 redrawtags $id
3467 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003468}
3469
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11003470proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003471 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003472
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003473 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003474}
3475
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003476proc drawcmittext {id row col} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10003477 global linespc canv canv2 canv3 canvy0 fgcolor curview
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003478 global commitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003479 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras005a2f42007-07-26 22:36:39 +10003480 global linehtag linentag linedtag
Paul Mackerras8f489362007-07-13 19:49:37 +10003481 global mainfont canvxmax boldrows boldnamerows fgcolor nullid nullid2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003482
Paul Mackerrasc961b222007-07-09 22:45:47 +10003483 # listed is 0 for boundary, 1 for normal, 2 for left, 3 for right
3484 set listed [lindex $commitlisted $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003485 if {$id eq $nullid} {
3486 set ofill red
Paul Mackerras8f489362007-07-13 19:49:37 +10003487 } elseif {$id eq $nullid2} {
Paul Mackerrasef3192b2007-07-22 22:05:30 +10003488 set ofill green
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003489 } else {
Paul Mackerrasc961b222007-07-09 22:45:47 +10003490 set ofill [expr {$listed != 0? "blue": "white"}]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003491 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003492 set x [xc $row $col]
3493 set y [yc $row]
3494 set orad [expr {$linespc / 3}]
Paul Mackerrasc961b222007-07-09 22:45:47 +10003495 if {$listed <= 1} {
3496 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
3497 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
3498 -fill $ofill -outline $fgcolor -width 1 -tags circle]
3499 } elseif {$listed == 2} {
3500 # triangle pointing left for left-side commits
3501 set t [$canv create polygon \
3502 [expr {$x - $orad}] $y \
3503 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
3504 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
3505 -fill $ofill -outline $fgcolor -width 1 -tags circle]
3506 } else {
3507 # triangle pointing right for right-side commits
3508 set t [$canv create polygon \
3509 [expr {$x + $orad - 1}] $y \
3510 [expr {$x - $orad}] [expr {$y - $orad}] \
3511 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
3512 -fill $ofill -outline $fgcolor -width 1 -tags circle]
3513 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003514 $canv raise $t
3515 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003516 set rmx [llength [lindex $rowidlist $row]]
3517 set olds [lindex $parentlist $row]
3518 if {$olds ne {}} {
3519 set nextids [lindex $rowidlist [expr {$row + 1}]]
3520 foreach p $olds {
3521 set i [lsearch -exact $nextids $p]
3522 if {$i > $rmx} {
3523 set rmx $i
3524 }
3525 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003526 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003527 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003528 set rowtextx($row) $xt
3529 set idpos($id) [list $x $xt $y]
3530 if {[info exists idtags($id)] || [info exists idheads($id)]
3531 || [info exists idotherrefs($id)]} {
3532 set xt [drawtags $id $x $xt $y]
3533 }
3534 set headline [lindex $commitinfo($id) 0]
3535 set name [lindex $commitinfo($id) 1]
3536 set date [lindex $commitinfo($id) 2]
3537 set date [formatdate $date]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003538 set font $mainfont
Paul Mackerras908c3582006-05-20 09:38:11 +10003539 set nfont $mainfont
3540 set isbold [ishighlighted $row]
3541 if {$isbold > 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003542 lappend boldrows $row
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003543 lappend font bold
Paul Mackerras908c3582006-05-20 09:38:11 +10003544 if {$isbold > 1} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003545 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003546 lappend nfont bold
3547 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003548 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003549 set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
3550 -text $headline -font $font -tags text]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003551 $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003552 set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
3553 -text $name -font $nfont -tags text]
3554 set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
3555 -text $date -font $mainfont -tags text]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11003556 set xr [expr {$xt + [font measure $mainfont $headline]}]
3557 if {$xr > $canvxmax} {
3558 set canvxmax $xr
3559 setcanvscroll
3560 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003561}
3562
3563proc drawcmitrow {row} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003564 global displayorder rowidlist
Paul Mackerras005a2f42007-07-26 22:36:39 +10003565 global iddrawn markingmatches
Paul Mackerrase7da3472006-04-17 10:27:59 +10003566 global commitinfo parentlist numcommits
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003567 global filehighlight fhighlights findstring nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10003568 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10003569 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003570
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11003571 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003572
3573 set id [lindex $displayorder $row]
Paul Mackerras908c3582006-05-20 09:38:11 +10003574 if {[info exists hlview] && ![info exists vhighlights($row)]} {
3575 askvhighlight $row $id
3576 }
3577 if {[info exists filehighlight] && ![info exists fhighlights($row)]} {
3578 askfilehighlight $row $id
3579 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003580 if {$findstring ne {} && ![info exists nhighlights($row)]} {
3581 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10003582 }
Paul Mackerras164ff272006-05-29 19:50:02 +10003583 if {$highlight_related ne "None" && ![info exists rhighlights($row)]} {
3584 askrelhighlight $row $id
3585 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10003586 if {![info exists iddrawn($id)]} {
3587 set col [lsearch -exact [lindex $rowidlist $row] $id]
3588 if {$col < 0} {
3589 puts "oops, row $row id $id not in list"
3590 return
3591 }
3592 if {![info exists commitinfo($id)]} {
3593 getcommit $id
3594 }
3595 assigncolor $id
3596 drawcmittext $id $row $col
3597 set iddrawn($id) 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003598 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10003599 if {$markingmatches} {
3600 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003601 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003602}
3603
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003604proc drawcommits {row {endrow {}}} {
3605 global numcommits iddrawn displayorder curview
3606 global parentlist rowidlist
3607
3608 if {$row < 0} {
3609 set row 0
3610 }
3611 if {$endrow eq {}} {
3612 set endrow $row
3613 }
3614 if {$endrow >= $numcommits} {
3615 set endrow [expr {$numcommits - 1}]
3616 }
3617
3618 # make the lines join to already-drawn rows either side
3619 set r [expr {$row - 1}]
3620 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
3621 set r $row
3622 }
3623 set er [expr {$endrow + 1}]
3624 if {$er >= $numcommits ||
3625 ![info exists iddrawn([lindex $displayorder $er])]} {
3626 set er $endrow
3627 }
3628 for {} {$r <= $er} {incr r} {
3629 set id [lindex $displayorder $r]
3630 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003631 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003632 if {$r == $er} break
3633 set nextid [lindex $displayorder [expr {$r + 1}]]
3634 if {$wasdrawn && [info exists iddrawn($nextid)]} {
3635 catch {unset prevlines}
3636 continue
3637 }
3638 drawparentlinks $id $r
3639
3640 if {[info exists lineends($r)]} {
3641 foreach lid $lineends($r) {
3642 unset prevlines($lid)
3643 }
3644 }
3645 set rowids [lindex $rowidlist $r]
3646 foreach lid $rowids {
3647 if {$lid eq {}} continue
3648 if {$lid eq $id} {
3649 # see if this is the first child of any of its parents
3650 foreach p [lindex $parentlist $r] {
3651 if {[lsearch -exact $rowids $p] < 0} {
3652 # make this line extend up to the child
3653 set le [drawlineseg $p $r $er 0]
3654 lappend lineends($le) $p
3655 set prevlines($p) 1
3656 }
3657 }
3658 } elseif {![info exists prevlines($lid)]} {
3659 set le [drawlineseg $lid $r $er 1]
3660 lappend lineends($le) $lid
3661 set prevlines($lid) 1
3662 }
3663 }
3664 }
3665}
3666
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003667proc drawfrac {f0 f1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003668 global canv linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003669
3670 set ymax [lindex [$canv cget -scrollregion] 3]
3671 if {$ymax eq {} || $ymax == 0} return
3672 set y0 [expr {int($f0 * $ymax)}]
3673 set row [expr {int(($y0 - 3) / $linespc) - 1}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003674 set y1 [expr {int($f1 * $ymax)}]
3675 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003676 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003677}
3678
3679proc drawvisible {} {
3680 global canv
3681 eval drawfrac [$canv yview]
3682}
3683
3684proc clear_display {} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003685 global iddrawn linesegs
Paul Mackerras164ff272006-05-29 19:50:02 +10003686 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003687
3688 allcanvs delete all
3689 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10003690 catch {unset linesegs}
Paul Mackerras908c3582006-05-20 09:38:11 +10003691 catch {unset vhighlights}
3692 catch {unset fhighlights}
3693 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10003694 catch {unset rhighlights}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003695}
3696
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003697proc findcrossings {id} {
3698 global rowidlist parentlist numcommits rowoffsets displayorder
3699
3700 set cross {}
3701 set ccross {}
3702 foreach {s e} [rowranges $id] {
3703 if {$e >= $numcommits} {
3704 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003705 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10003706 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003707 set x [lsearch -exact [lindex $rowidlist $e] $id]
3708 if {$x < 0} {
3709 puts "findcrossings: oops, no [shortids $id] in row $e"
3710 continue
3711 }
3712 for {set row $e} {[incr row -1] >= $s} {} {
3713 set olds [lindex $parentlist $row]
3714 set kid [lindex $displayorder $row]
3715 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
3716 if {$kidx < 0} continue
3717 set nextrow [lindex $rowidlist [expr {$row + 1}]]
3718 foreach p $olds {
3719 set px [lsearch -exact $nextrow $p]
3720 if {$px < 0} continue
3721 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
3722 if {[lsearch -exact $ccross $p] >= 0} continue
3723 if {$x == $px + ($kidx < $px? -1: 1)} {
3724 lappend ccross $p
3725 } elseif {[lsearch -exact $cross $p] < 0} {
3726 lappend cross $p
3727 }
3728 }
3729 }
3730 set inc [lindex $rowoffsets $row $x]
3731 if {$inc eq {}} break
3732 incr x $inc
3733 }
3734 }
3735 return [concat $ccross {{}} $cross]
3736}
3737
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003738proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11003739 global colormap colors nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003740 global commitrow parentlist children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003741
Paul Mackerras418c4c72006-02-07 09:10:18 +11003742 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003743 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003744 if {[info exists children($curview,$id)]} {
3745 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10003746 } else {
3747 set kids {}
3748 }
3749 if {[llength $kids] == 1} {
3750 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003751 if {[info exists colormap($child)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003752 && [llength [lindex $parentlist $commitrow($curview,$child)]] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003753 set colormap($id) $colormap($child)
3754 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003755 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003756 }
3757 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003758 set origbad {}
3759 foreach x [findcrossings $id] {
3760 if {$x eq {}} {
3761 # delimiter between corner crossings and other crossings
3762 if {[llength $badcolors] >= $ncolors - 1} break
3763 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003764 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003765 if {[info exists colormap($x)]
3766 && [lsearch -exact $badcolors $colormap($x)] < 0} {
3767 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003768 }
3769 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003770 if {[llength $badcolors] >= $ncolors} {
3771 set badcolors $origbad
3772 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003773 set origbad $badcolors
3774 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003775 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003776 if {[info exists colormap($child)]
3777 && [lsearch -exact $badcolors $colormap($child)] < 0} {
3778 lappend badcolors $colormap($child)
3779 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003780 foreach p [lindex $parentlist $commitrow($curview,$child)] {
Paul Mackerras79b2c752006-04-02 20:47:40 +10003781 if {[info exists colormap($p)]
3782 && [lsearch -exact $badcolors $colormap($p)] < 0} {
3783 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003784 }
3785 }
3786 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10003787 if {[llength $badcolors] >= $ncolors} {
3788 set badcolors $origbad
3789 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003790 }
3791 for {set i 0} {$i <= $ncolors} {incr i} {
3792 set c [lindex $colors $nextcolor]
3793 if {[incr nextcolor] >= $ncolors} {
3794 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00003795 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003796 if {[lsearch -exact $badcolors $c]} break
3797 }
3798 set colormap($id) $c
3799}
3800
Paul Mackerrasa823a912005-06-21 10:01:38 +10003801proc bindline {t id} {
3802 global canv
3803
Paul Mackerrasa823a912005-06-21 10:01:38 +10003804 $canv bind $t <Enter> "lineenter %x %y $id"
3805 $canv bind $t <Motion> "linemotion %x %y $id"
3806 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10003807 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10003808}
3809
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003810proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10003811 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003812 global linespc lthickness
Paul Mackerras8a485712006-07-06 10:21:23 +10003813 global canv mainfont commitrow rowtextx curview fgcolor bgcolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003814
3815 set marks {}
3816 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003817 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003818 if {[info exists idtags($id)]} {
3819 set marks $idtags($id)
3820 set ntags [llength $marks]
3821 }
3822 if {[info exists idheads($id)]} {
3823 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003824 set nheads [llength $idheads($id)]
3825 }
3826 if {[info exists idotherrefs($id)]} {
3827 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003828 }
3829 if {$marks eq {}} {
3830 return $xt
3831 }
3832
3833 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003834 set yt [expr {$y1 - 0.5 * $linespc}]
3835 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003836 set xvals {}
3837 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10003838 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003839 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10003840 incr i
3841 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
3842 set wid [font measure [concat $mainfont bold] $tag]
3843 } else {
3844 set wid [font measure $mainfont $tag]
3845 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003846 lappend xvals $xt
3847 lappend wvals $wid
3848 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
3849 }
3850 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
3851 -width $lthickness -fill black -tags tag.$id]
3852 $canv lower $t
3853 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003854 set xl [expr {$x + $delta}]
3855 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras8a485712006-07-06 10:21:23 +10003856 set font $mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003857 if {[incr ntags -1] >= 0} {
3858 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003859 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
3860 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10003861 -width 1 -outline black -fill yellow -tags tag.$id]
3862 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003863 set rowtextx($commitrow($curview,$id)) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003864 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003865 # draw a head or other ref
3866 if {[incr nheads -1] >= 0} {
3867 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10003868 if {$tag eq $mainhead} {
3869 lappend font bold
3870 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003871 } else {
3872 set col "#ddddff"
3873 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003874 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003875 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10003876 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02003877 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
3878 set rwid [font measure $mainfont $remoteprefix]
3879 set xi [expr {$x + 1}]
3880 set yti [expr {$yt + 1}]
3881 set xri [expr {$x + $rwid}]
3882 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
3883 -width 0 -fill "#ffddaa" -tags tag.$id
3884 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003885 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003886 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10003887 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10003888 if {$ntags >= 0} {
3889 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10003890 } elseif {$nheads >= 0} {
3891 $canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10003892 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10003893 }
3894 return $xt
3895}
3896
Paul Mackerras8d858d12005-08-05 09:52:16 +10003897proc xcoord {i level ln} {
3898 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00003899
Paul Mackerras8d858d12005-08-05 09:52:16 +10003900 set x [expr {$canvx0 + $i * $xspc1($ln)}]
3901 if {$i > 0 && $i == $level} {
3902 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
3903 } elseif {$i > $level} {
3904 set x [expr {$x + $xspc2 - $xspc1($ln)}]
3905 }
3906 return $x
3907}
3908
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003909proc show_status {msg} {
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003910 global canv mainfont fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003911
3912 clear_display
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10003913 $canv create text 3 3 -anchor nw -text $msg -font $mainfont \
3914 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003915}
3916
Paul Mackerras561d0382006-08-28 22:41:09 +10003917# Insert a new commit as the child of the commit on row $row.
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003918# The new commit will be displayed on row $row and the commits
3919# on that row and below will move down one row.
3920proc insertrow {row newcmit} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003921 global displayorder parentlist commitlisted children
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003922 global commitrow curview rowidlist rowoffsets numcommits
Paul Mackerras66e46f32006-10-14 19:21:02 +10003923 global rowrangelist rowlaidout rowoptim numcommits
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003924 global selectedline rowchk commitidx
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003925
3926 if {$row >= $numcommits} {
3927 puts "oops, inserting new row $row but only have $numcommits rows"
3928 return
3929 }
3930 set p [lindex $displayorder $row]
3931 set displayorder [linsert $displayorder $row $newcmit]
3932 set parentlist [linsert $parentlist $row $p]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003933 set kids $children($curview,$p)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003934 lappend kids $newcmit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003935 set children($curview,$p) $kids
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003936 set children($curview,$newcmit) {}
Paul Mackerras561d0382006-08-28 22:41:09 +10003937 set commitlisted [linsert $commitlisted $row 1]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003938 set l [llength $displayorder]
3939 for {set r $row} {$r < $l} {incr r} {
3940 set id [lindex $displayorder $r]
3941 set commitrow($curview,$id) $r
3942 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003943 incr commitidx($curview)
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003944
3945 set idlist [lindex $rowidlist $row]
3946 set offs [lindex $rowoffsets $row]
3947 set newoffs {}
3948 foreach x $idlist {
3949 if {$x eq {} || ($x eq $p && [llength $kids] == 1)} {
3950 lappend newoffs {}
3951 } else {
3952 lappend newoffs 0
3953 }
3954 }
3955 if {[llength $kids] == 1} {
3956 set col [lsearch -exact $idlist $p]
3957 lset idlist $col $newcmit
3958 } else {
3959 set col [llength $idlist]
3960 lappend idlist $newcmit
3961 lappend offs {}
3962 lset rowoffsets $row $offs
3963 }
3964 set rowidlist [linsert $rowidlist $row $idlist]
3965 set rowoffsets [linsert $rowoffsets [expr {$row+1}] $newoffs]
3966
3967 set rowrangelist [linsert $rowrangelist $row {}]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003968 if {[llength $kids] > 1} {
3969 set rp1 [expr {$row + 1}]
3970 set ranges [lindex $rowrangelist $rp1]
3971 if {$ranges eq {}} {
Paul Mackerras66e46f32006-10-14 19:21:02 +10003972 set ranges [list $newcmit $p]
3973 } elseif {[lindex $ranges end-1] eq $p} {
3974 lset ranges end-1 $newcmit
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003975 }
3976 lset rowrangelist $rp1 $ranges
3977 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003978
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003979 catch {unset rowchk}
3980
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003981 incr rowlaidout
3982 incr rowoptim
3983 incr numcommits
3984
Paul Mackerras561d0382006-08-28 22:41:09 +10003985 if {[info exists selectedline] && $selectedline >= $row} {
3986 incr selectedline
3987 }
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10003988 redisplay
3989}
3990
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003991# Remove a commit that was inserted with insertrow on row $row.
3992proc removerow {row} {
Paul Mackerras6a90bff2007-06-18 09:48:23 +10003993 global displayorder parentlist commitlisted children
Paul Mackerras219ea3a2006-09-07 10:21:39 +10003994 global commitrow curview rowidlist rowoffsets numcommits
3995 global rowrangelist idrowranges rowlaidout rowoptim numcommits
3996 global linesegends selectedline rowchk commitidx
3997
3998 if {$row >= $numcommits} {
3999 puts "oops, removing row $row but only have $numcommits rows"
4000 return
4001 }
4002 set rp1 [expr {$row + 1}]
4003 set id [lindex $displayorder $row]
4004 set p [lindex $parentlist $row]
4005 set displayorder [lreplace $displayorder $row $row]
4006 set parentlist [lreplace $parentlist $row $row]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004007 set commitlisted [lreplace $commitlisted $row $row]
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004008 set kids $children($curview,$p)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004009 set i [lsearch -exact $kids $id]
4010 if {$i >= 0} {
4011 set kids [lreplace $kids $i $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004012 set children($curview,$p) $kids
4013 }
4014 set l [llength $displayorder]
4015 for {set r $row} {$r < $l} {incr r} {
4016 set id [lindex $displayorder $r]
4017 set commitrow($curview,$id) $r
4018 }
4019 incr commitidx($curview) -1
4020
4021 set rowidlist [lreplace $rowidlist $row $row]
4022 set rowoffsets [lreplace $rowoffsets $rp1 $rp1]
4023 if {$kids ne {}} {
4024 set offs [lindex $rowoffsets $row]
4025 set offs [lreplace $offs end end]
4026 lset rowoffsets $row $offs
4027 }
4028
4029 set rowrangelist [lreplace $rowrangelist $row $row]
4030 if {[llength $kids] > 0} {
4031 set ranges [lindex $rowrangelist $row]
4032 if {[lindex $ranges end-1] eq $id} {
4033 set ranges [lreplace $ranges end-1 end]
4034 lset rowrangelist $row $ranges
4035 }
4036 }
4037
4038 catch {unset rowchk}
4039
4040 incr rowlaidout -1
4041 incr rowoptim -1
4042 incr numcommits -1
4043
4044 if {[info exists selectedline] && $selectedline > $row} {
4045 incr selectedline -1
4046 }
4047 redisplay
4048}
4049
Paul Mackerras94a2eed2005-08-07 15:27:57 +10004050# Don't change the text pane cursor if it is currently the hand cursor,
4051# showing that we are over a sha1 ID link.
4052proc settextcursor {c} {
4053 global ctext curtextcursor
4054
4055 if {[$ctext cget -cursor] == $curtextcursor} {
4056 $ctext config -cursor $c
4057 }
4058 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00004059}
4060
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004061proc nowbusy {what} {
4062 global isbusy
4063
4064 if {[array names isbusy] eq {}} {
4065 . config -cursor watch
4066 settextcursor watch
4067 }
4068 set isbusy($what) 1
4069}
4070
4071proc notbusy {what} {
4072 global isbusy maincursor textcursor
4073
4074 catch {unset isbusy($what)}
4075 if {[array names isbusy] eq {}} {
4076 . config -cursor $maincursor
4077 settextcursor $textcursor
4078 }
4079}
4080
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004081proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004082 global findtype findstring
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004083 if {$findtype == "Regexp"} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004084 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004085 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004086 set fs $findstring
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004087 if {$findtype == "IgnCase"} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004088 set f [string tolower $f]
4089 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004090 }
4091 set matches {}
4092 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004093 set l [string length $fs]
4094 while {[set j [string first $fs $f $i]] >= 0} {
4095 lappend matches [list $j [expr {$j+$l-1}]]
4096 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004097 }
4098 }
4099 return $matches
4100}
4101
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004102proc dofind {{rev 0}} {
4103 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004104
Paul Mackerras98f350e2005-05-15 05:56:51 +00004105 unmarkmatches
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004106 cancel_next_highlight
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004107 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004108 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras98f350e2005-05-15 05:56:51 +00004109 if {![info exists selectedline]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004110 set findstartline [lindex [visiblerows] $rev]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004111 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004112 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00004113 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004114 set findcurline $findstartline
4115 nowbusy finding
4116 if {!$rev} {
4117 run findmore
4118 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004119 if {$findcurline == 0} {
4120 set findcurline $numcommits
Paul Mackerras8ed16482006-03-02 22:56:44 +11004121 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004122 incr findcurline -1
4123 run findmorerev
4124 }
4125}
4126
4127proc findnext {restart} {
4128 global findcurline
4129 if {![info exists findcurline]} {
4130 if {$restart} {
4131 dofind
4132 } else {
4133 bell
4134 }
4135 } else {
4136 run findmore
4137 nowbusy finding
4138 }
4139}
4140
4141proc findprev {} {
4142 global findcurline
4143 if {![info exists findcurline]} {
4144 dofind 1
4145 } else {
4146 run findmorerev
4147 nowbusy finding
4148 }
4149}
4150
4151proc findmore {} {
4152 global commitdata commitinfo numcommits findstring findpattern findloc
Paul Mackerras005a2f42007-07-26 22:36:39 +10004153 global findstartline findcurline displayorder
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004154
4155 set fldtypes {Headline Author Date Committer CDate Comments}
4156 set l [expr {$findcurline + 1}]
4157 if {$l >= $numcommits} {
4158 set l 0
4159 }
4160 if {$l <= $findstartline} {
4161 set lim [expr {$findstartline + 1}]
4162 } else {
4163 set lim $numcommits
4164 }
4165 if {$lim - $l > 500} {
4166 set lim [expr {$l + 500}]
4167 }
4168 set last 0
4169 for {} {$l < $lim} {incr l} {
4170 set id [lindex $displayorder $l]
Paul Mackerras005a2f42007-07-26 22:36:39 +10004171 # shouldn't happen unless git log doesn't give all the commits...
4172 if {![info exists commitdata($id)]} continue
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004173 if {![doesmatch $commitdata($id)]} continue
Paul Mackerras8ed16482006-03-02 22:56:44 +11004174 if {![info exists commitinfo($id)]} {
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11004175 getcommit $id
Paul Mackerras8ed16482006-03-02 22:56:44 +11004176 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004177 set info $commitinfo($id)
Paul Mackerras98f350e2005-05-15 05:56:51 +00004178 foreach f $info ty $fldtypes {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004179 if {($findloc eq "All fields" || $findloc eq $ty) &&
4180 [doesmatch $f]} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004181 findselectline $l
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004182 notbusy finding
4183 return 0
Paul Mackerras98f350e2005-05-15 05:56:51 +00004184 }
4185 }
4186 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004187 if {$l == $findstartline + 1} {
Paul Mackerras98f350e2005-05-15 05:56:51 +00004188 bell
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004189 unset findcurline
4190 notbusy finding
4191 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004192 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004193 set findcurline [expr {$l - 1}]
4194 return 1
4195}
4196
4197proc findmorerev {} {
4198 global commitdata commitinfo numcommits findstring findpattern findloc
Paul Mackerras005a2f42007-07-26 22:36:39 +10004199 global findstartline findcurline displayorder
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004200
4201 set fldtypes {Headline Author Date Committer CDate Comments}
4202 set l $findcurline
4203 if {$l == 0} {
4204 set l $numcommits
4205 }
4206 incr l -1
4207 if {$l >= $findstartline} {
4208 set lim [expr {$findstartline - 1}]
4209 } else {
4210 set lim -1
4211 }
4212 if {$l - $lim > 500} {
4213 set lim [expr {$l - 500}]
4214 }
4215 set last 0
4216 for {} {$l > $lim} {incr l -1} {
4217 set id [lindex $displayorder $l]
4218 if {![doesmatch $commitdata($id)]} continue
4219 if {![info exists commitinfo($id)]} {
4220 getcommit $id
4221 }
4222 set info $commitinfo($id)
4223 foreach f $info ty $fldtypes {
4224 if {($findloc eq "All fields" || $findloc eq $ty) &&
4225 [doesmatch $f]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004226 findselectline $l
4227 notbusy finding
4228 return 0
4229 }
4230 }
4231 }
4232 if {$l == -1} {
4233 bell
4234 unset findcurline
4235 notbusy finding
4236 return 0
4237 }
4238 set findcurline [expr {$l + 1}]
4239 return 1
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004240}
4241
4242proc findselectline {l} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004243 global findloc commentend ctext findcurline markingmatches
4244
4245 set markingmatches 1
4246 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10004247 selectline $l 1
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004248 if {$findloc == "All fields" || $findloc == "Comments"} {
4249 # highlight the matches in the comments
4250 set f [$ctext get 1.0 $commentend]
4251 set matches [findmatches $f]
4252 foreach match $matches {
4253 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004254 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004255 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
4256 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004257 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10004258 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00004259}
4260
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004261# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10004262proc markmatches {canv l str tag matches font row} {
4263 global selectedline
4264
Paul Mackerras98f350e2005-05-15 05:56:51 +00004265 set bbox [$canv bbox $tag]
4266 set x0 [lindex $bbox 0]
4267 set y0 [lindex $bbox 1]
4268 set y1 [lindex $bbox 3]
4269 foreach match $matches {
4270 set start [lindex $match 0]
4271 set end [lindex $match 1]
4272 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004273 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
4274 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
4275 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
4276 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004277 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004278 $canv lower $t
Paul Mackerras005a2f42007-07-26 22:36:39 +10004279 if {[info exists selectedline] && $row == $selectedline} {
4280 $canv raise $t secsel
4281 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004282 }
4283}
4284
4285proc unmarkmatches {} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004286 global findids markingmatches findcurline
4287
Paul Mackerras98f350e2005-05-15 05:56:51 +00004288 allcanvs delete matches
Paul Mackerrasb74fd572005-07-16 07:46:13 -04004289 catch {unset findids}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004290 set markingmatches 0
4291 catch {unset findcurline}
Paul Mackerras98f350e2005-05-15 05:56:51 +00004292}
4293
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004294proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004295 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004296 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00004297 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00004298 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00004299 set yfrac [lindex [$canv yview] 0]
4300 set y [expr {$y + $yfrac * $ymax}]
4301 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
4302 if {$l < 0} {
4303 set l 0
4304 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004305 if {$w eq $canv} {
4306 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
4307 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00004308 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004309 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004310}
4311
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004312proc commit_descriptor {p} {
4313 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10004314 if {![info exists commitinfo($p)]} {
4315 getcommit $p
4316 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004317 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10004318 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004319 set l [lindex $commitinfo($p) 0]
4320 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004321 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004322}
4323
Paul Mackerras106288c2005-08-19 23:11:39 +10004324# append some text to the ctext widget, and make any SHA1 ID
4325# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004326proc appendwithlinks {text tags} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004327 global ctext commitrow linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10004328
4329 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004330 $ctext insert end $text $tags
Paul Mackerras106288c2005-08-19 23:11:39 +10004331 set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
4332 foreach l $links {
4333 set s [lindex $l 0]
4334 set e [lindex $l 1]
4335 set linkid [string range $text $s $e]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004336 if {![info exists commitrow($curview,$linkid)]} continue
Paul Mackerras106288c2005-08-19 23:11:39 +10004337 incr e
4338 $ctext tag add link "$start + $s c" "$start + $e c"
4339 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004340 $ctext tag bind link$linknum <1> \
4341 [list selectline $commitrow($curview,$linkid) 1]
Paul Mackerras106288c2005-08-19 23:11:39 +10004342 incr linknum
4343 }
4344 $ctext tag conf link -foreground blue -underline 1
4345 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
4346 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
4347}
4348
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004349proc viewnextline {dir} {
4350 global canv linespc
4351
4352 $canv delete hover
4353 set ymax [lindex [$canv cget -scrollregion] 3]
4354 set wnow [$canv yview]
4355 set wtop [expr {[lindex $wnow 0] * $ymax}]
4356 set newtop [expr {$wtop + $dir * $linespc}]
4357 if {$newtop < 0} {
4358 set newtop 0
4359 } elseif {$newtop > $ymax} {
4360 set newtop $ymax
4361 }
4362 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
4363}
4364
Paul Mackerrasef030b82006-06-04 11:50:38 +10004365# add a list of tag or branch names at position pos
4366# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10004367proc appendrefs {pos ids var} {
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004368 global ctext commitrow linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004369
Paul Mackerrasef030b82006-06-04 11:50:38 +10004370 if {[catch {$ctext index $pos}]} {
4371 return 0
4372 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004373 $ctext conf -state normal
4374 $ctext delete $pos "$pos lineend"
4375 set tags {}
4376 foreach id $ids {
4377 foreach tag [set $var\($id\)] {
4378 lappend tags [list $tag $id]
4379 }
4380 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10004381 if {[llength $tags] > $maxrefs} {
4382 $ctext insert $pos "many ([llength $tags])"
4383 } else {
4384 set tags [lsort -index 0 -decreasing $tags]
4385 set sep {}
4386 foreach ti $tags {
4387 set id [lindex $ti 1]
4388 set lk link$linknum
4389 incr linknum
4390 $ctext tag delete $lk
4391 $ctext insert $pos $sep
4392 $ctext insert $pos [lindex $ti 0] $lk
4393 if {[info exists commitrow($curview,$id)]} {
4394 $ctext tag conf $lk -foreground blue
4395 $ctext tag bind $lk <1> \
4396 [list selectline $commitrow($curview,$id) 1]
4397 $ctext tag conf $lk -underline 1
4398 $ctext tag bind $lk <Enter> { %W configure -cursor hand2 }
4399 $ctext tag bind $lk <Leave> \
4400 { %W configure -cursor $curtextcursor }
4401 }
4402 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004403 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004404 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004405 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10004406 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004407}
4408
4409# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10004410proc dispneartags {delay} {
4411 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004412
4413 if {![info exists selectedline] || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10004414 after cancel dispnexttag
4415 if {$delay} {
4416 after 200 dispnexttag
4417 set tagphase -1
4418 } else {
4419 after idle dispnexttag
4420 set tagphase 0
4421 }
4422}
4423
4424proc dispnexttag {} {
4425 global selectedline currentid showneartags tagphase ctext
4426
4427 if {![info exists selectedline] || !$showneartags} return
4428 switch -- $tagphase {
4429 0 {
4430 set dtags [desctags $currentid]
4431 if {$dtags ne {}} {
4432 appendrefs precedes $dtags idtags
4433 }
4434 }
4435 1 {
4436 set atags [anctags $currentid]
4437 if {$atags ne {}} {
4438 appendrefs follows $atags idtags
4439 }
4440 }
4441 2 {
4442 set dheads [descheads $currentid]
4443 if {$dheads ne {}} {
4444 if {[appendrefs branch $dheads idheads] > 1
4445 && [$ctext get "branch -3c"] eq "h"} {
4446 # turn "Branch" into "Branches"
4447 $ctext conf -state normal
4448 $ctext insert "branch -2c" "es"
4449 $ctext conf -state disabled
4450 }
4451 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004452 }
4453 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10004454 if {[incr tagphase] <= 2} {
4455 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004456 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004457}
4458
Paul Mackerrasd6982062005-08-06 22:06:06 +10004459proc selectline {l isnew} {
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004460 global canv canv2 canv3 ctext commitinfo selectedline
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004461 global displayorder linehtag linentag linedtag
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004462 global canvy0 linespc parentlist children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004463 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004464 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004465 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10004466 global cmitmode showneartags allcommits
Paul Mackerrasd6982062005-08-06 22:06:06 +10004467
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004468 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00004469 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10004470 normalline
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004471 cancel_next_highlight
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004472 if {$l < 0 || $l >= $numcommits} return
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004473 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00004474 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00004475 set ytop [expr {$y - $linespc - 1}]
4476 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004477 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004478 set wtop [expr {[lindex $wnow 0] * $ymax}]
4479 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00004480 set wh [expr {$wbot - $wtop}]
4481 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00004482 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00004483 if {$ybot < $wtop} {
4484 set newtop [expr {$y - $wh / 2.0}]
4485 } else {
4486 set newtop $ytop
4487 if {$newtop > $wtop - $linespc} {
4488 set newtop [expr {$wtop - $linespc}]
4489 }
Paul Mackerras17386062005-05-18 22:51:00 +00004490 }
Paul Mackerras58422152005-05-19 10:56:42 +00004491 } elseif {$ybot > $wbot} {
4492 if {$ytop > $wbot} {
4493 set newtop [expr {$y - $wh / 2.0}]
4494 } else {
4495 set newtop [expr {$ybot - $wh}]
4496 if {$newtop < $wtop + $linespc} {
4497 set newtop [expr {$wtop + $linespc}]
4498 }
Paul Mackerras17386062005-05-18 22:51:00 +00004499 }
Paul Mackerras58422152005-05-19 10:56:42 +00004500 }
4501 if {$newtop != $wtop} {
4502 if {$newtop < 0} {
4503 set newtop 0
4504 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004505 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004506 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004507 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004508
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004509 if {![info exists linehtag($l)]} return
4510 $canv delete secsel
4511 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
4512 -tags secsel -fill [$canv cget -selectbackground]]
4513 $canv lower $t
4514 $canv2 delete secsel
4515 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
4516 -tags secsel -fill [$canv2 cget -selectbackground]]
4517 $canv2 lower $t
4518 $canv3 delete secsel
4519 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
4520 -tags secsel -fill [$canv3 cget -selectbackground]]
4521 $canv3 lower $t
4522
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004523 if {$isnew} {
4524 addtohistory [list selectline $l 0]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004525 }
4526
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004527 set selectedline $l
4528
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004529 set id [lindex $displayorder $l]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004530 set currentid $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004531 $sha1entry delete 0 end
4532 $sha1entry insert 0 $id
4533 $sha1entry selection from 0
4534 $sha1entry selection to end
Paul Mackerras164ff272006-05-29 19:50:02 +10004535 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00004536
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004537 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004538 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10004539 set linknum 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00004540 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11004541 set date [formatdate [lindex $info 2]]
4542 $ctext insert end "Author: [lindex $info 1] $date\n"
4543 set date [formatdate [lindex $info 4]]
4544 $ctext insert end "Committer: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00004545 if {[info exists idtags($id)]} {
4546 $ctext insert end "Tags:"
4547 foreach tag $idtags($id) {
4548 $ctext insert end " $tag"
4549 }
4550 $ctext insert end "\n"
4551 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004552
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004553 set headers {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004554 set olds [lindex $parentlist $l]
4555 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004556 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10004557 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004558 if {$np >= $mergemax} {
4559 set tag mmax
4560 } else {
4561 set tag m$np
4562 }
4563 $ctext insert end "Parent: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004564 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004565 incr np
4566 }
4567 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004568 foreach p $olds {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004569 append headers "Parent: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004570 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07004571 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004572
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004573 foreach c $children($curview,$id) {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004574 append headers "Child: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07004575 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10004576
4577 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04004578 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004579 if {$showneartags} {
4580 if {![info exists allcommits]} {
4581 getallcommits
4582 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10004583 $ctext insert end "Branch: "
4584 $ctext mark set branch "end -1c"
4585 $ctext mark gravity branch left
Paul Mackerrasef030b82006-06-04 11:50:38 +10004586 $ctext insert end "\nFollows: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004587 $ctext mark set follows "end -1c"
4588 $ctext mark gravity follows left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004589 $ctext insert end "\nPrecedes: "
4590 $ctext mark set precedes "end -1c"
4591 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004592 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10004593 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10004594 }
4595 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10004596 set comment [lindex $info 5]
4597 if {[string first "\r" $comment] >= 0} {
4598 set comment [string map {"\r" "\n "} $comment]
4599 }
4600 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10004601
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004602 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004603 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00004604 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004605
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004606 init_flist "Comments"
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004607 if {$cmitmode eq "tree"} {
4608 gettree $id
4609 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11004610 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11004611 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10004612 mergediff $id $l
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004613 }
4614}
4615
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004616proc selfirstline {} {
4617 unmarkmatches
4618 selectline 0 1
4619}
4620
4621proc sellastline {} {
4622 global numcommits
4623 unmarkmatches
4624 set l [expr {$numcommits - 1}]
4625 selectline $l 1
4626}
4627
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004628proc selnextline {dir} {
4629 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04004630 focus .
Paul Mackerrase5c2d852005-05-11 23:44:54 +00004631 if {![info exists selectedline]} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08004632 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00004633 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10004634 selectline $l 1
4635}
4636
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004637proc selnextpage {dir} {
4638 global canv linespc selectedline numcommits
4639
4640 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
4641 if {$lpp < 1} {
4642 set lpp 1
4643 }
4644 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10004645 drawvisible
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004646 if {![info exists selectedline]} return
4647 set l [expr {$selectedline + $dir * $lpp}]
4648 if {$l < 0} {
4649 set l 0
4650 } elseif {$l >= $numcommits} {
4651 set l [expr $numcommits - 1]
4652 }
4653 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05004654 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10004655}
4656
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004657proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004658 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004659
4660 catch {unset selectedline}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004661 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004662 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10004663 rhighlight_none
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004664 cancel_next_highlight
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004665}
4666
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004667proc reselectline {} {
4668 global selectedline
4669
4670 if {[info exists selectedline]} {
4671 selectline $selectedline 0
4672 }
4673}
4674
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004675proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004676 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004677
Paul Mackerras2516dae2006-04-21 10:35:31 +10004678 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004679 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10004680 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004681 return
4682 }
4683
4684 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004685 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004686 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10004687 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004688 }
4689 incr historyindex
4690 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004691 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004692 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004693 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004694 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004695 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004696}
4697
Paul Mackerras2516dae2006-04-21 10:35:31 +10004698proc godo {elt} {
4699 global curview
4700
4701 set view [lindex $elt 0]
4702 set cmd [lindex $elt 1]
4703 if {$curview != $view} {
4704 showview $view
4705 }
4706 eval $cmd
4707}
4708
Paul Mackerrasd6982062005-08-06 22:06:06 +10004709proc goback {} {
4710 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04004711 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10004712
4713 if {$historyindex > 1} {
4714 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10004715 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004716 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004717 }
4718 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004719 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004720 }
4721}
4722
4723proc goforw {} {
4724 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04004725 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10004726
4727 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10004728 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10004729 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10004730 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004731 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10004732 }
4733 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05004734 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10004735 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00004736}
4737
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004738proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004739 global treefilelist treeidlist diffids diffmergeid treepending
4740 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004741
4742 set diffids $id
4743 catch {unset diffmergeid}
4744 if {![info exists treefilelist($id)]} {
4745 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004746 if {$id eq $nullid} {
4747 set cmd [list | git ls-files]
4748 } elseif {$id eq $nullid2} {
4749 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004750 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10004751 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004752 }
4753 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004754 return
4755 }
4756 set treepending $id
4757 set treefilelist($id) {}
4758 set treeidlist($id) {}
4759 fconfigure $gtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004760 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004761 }
4762 } else {
4763 setfilelist $id
4764 }
4765}
4766
4767proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004768 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004769
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004770 set nl 0
4771 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004772 if {$diffids eq $nullid} {
4773 set fname $line
4774 } else {
4775 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10004776 set i [string first "\t" $line]
4777 if {$i < 0} continue
4778 set sha1 [lindex $line 2]
4779 set fname [string range $line [expr {$i+1}] end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004780 if {[string index $fname 0] eq "\""} {
4781 set fname [lindex $fname 0]
4782 }
4783 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004784 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004785 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004786 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004787 if {![eof $gtf]} {
4788 return [expr {$nl >= 1000? 2: 1}]
4789 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004790 close $gtf
4791 unset treepending
4792 if {$cmitmode ne "tree"} {
4793 if {![info exists diffmergeid]} {
4794 gettreediffs $diffids
4795 }
4796 } elseif {$id ne $diffids} {
4797 gettree $diffids
4798 } else {
4799 setfilelist $id
4800 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004801 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004802}
4803
4804proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004805 global treefilelist treeidlist diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004806 global ctext commentend
4807
4808 set i [lsearch -exact $treefilelist($diffids) $f]
4809 if {$i < 0} {
4810 puts "oops, $f not in list for id $diffids"
4811 return
4812 }
Paul Mackerras8f489362007-07-13 19:49:37 +10004813 if {$diffids eq $nullid} {
4814 if {[catch {set bf [open $f r]} err]} {
4815 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004816 return
4817 }
4818 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10004819 set blob [lindex $treeidlist($diffids) $i]
4820 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
4821 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004822 return
4823 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004824 }
4825 fconfigure $bf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004826 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004827 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10004828 clear_ctext $commentend
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004829 $ctext insert end "\n"
4830 $ctext insert end "$f\n" filesep
4831 $ctext config -state disabled
4832 $ctext yview $commentend
4833}
4834
4835proc getblobline {bf id} {
4836 global diffids cmitmode ctext
4837
4838 if {$id ne $diffids || $cmitmode ne "tree"} {
4839 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004840 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004841 }
4842 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004843 set nl 0
4844 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004845 $ctext insert end "$line\n"
4846 }
4847 if {[eof $bf]} {
4848 # delete last newline
4849 $ctext delete "end - 2c" "end - 1c"
4850 close $bf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004851 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004852 }
4853 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004854 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004855}
4856
Paul Mackerras79b2c752006-04-02 20:47:40 +10004857proc mergediff {id l} {
4858 global diffmergeid diffopts mdifffd
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004859 global diffids
Paul Mackerras79b2c752006-04-02 20:47:40 +10004860 global parentlist
Paul Mackerrase2ed4322005-07-17 03:39:44 -04004861
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004862 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004863 set diffids $id
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004864 # this doesn't seem to actually affect anything...
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004865 set env(GIT_DIFF_OPTS) $diffopts
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03004866 set cmd [concat | git diff-tree --no-commit-id --cc $id]
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004867 if {[catch {set mdf [open $cmd r]} err]} {
4868 error_popup "Error getting merge diffs: $err"
4869 return
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004870 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11004871 fconfigure $mdf -blocking 0
4872 set mdifffd($id) $mdf
Paul Mackerras79b2c752006-04-02 20:47:40 +10004873 set np [llength [lindex $parentlist $l]]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004874 filerun $mdf [list getmergediffline $mdf $id $np]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004875}
4876
Paul Mackerras79b2c752006-04-02 20:47:40 +10004877proc getmergediffline {mdf id np} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004878 global diffmergeid ctext cflist mergemax
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11004879 global difffilestart mdifffd
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004880
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004881 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004882 set nr 0
4883 while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
4884 if {![info exists diffmergeid] || $id != $diffmergeid
4885 || $mdf != $mdifffd($id)} {
4886 close $mdf
4887 return 0
4888 }
4889 if {[regexp {^diff --cc (.*)} $line match fname]} {
4890 # start of a new file
4891 $ctext insert end "\n"
4892 set here [$ctext index "end - 1c"]
4893 lappend difffilestart $here
4894 add_flist [list $fname]
4895 set l [expr {(78 - [string length $fname]) / 2}]
4896 set pad [string range "----------------------------------------" 1 $l]
4897 $ctext insert end "$pad $fname $pad\n" filesep
4898 } elseif {[regexp {^@@} $line]} {
4899 $ctext insert end "$line\n" hunksep
4900 } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
4901 # do nothing
4902 } else {
4903 # parse the prefix - one ' ', '-' or '+' for each parent
4904 set spaces {}
4905 set minuses {}
4906 set pluses {}
4907 set isbad 0
4908 for {set j 0} {$j < $np} {incr j} {
4909 set c [string range $line $j $j]
4910 if {$c == " "} {
4911 lappend spaces $j
4912 } elseif {$c == "-"} {
4913 lappend minuses $j
4914 } elseif {$c == "+"} {
4915 lappend pluses $j
4916 } else {
4917 set isbad 1
4918 break
4919 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004920 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004921 set tags {}
4922 set num {}
4923 if {!$isbad && $minuses ne {} && $pluses eq {}} {
4924 # line doesn't appear in result, parents in $minuses have the line
4925 set num [lindex $minuses 0]
4926 } elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
4927 # line appears in result, parents in $pluses don't have the line
4928 lappend tags mresult
4929 set num [lindex $spaces 0]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004930 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004931 if {$num ne {}} {
4932 if {$num >= $mergemax} {
4933 set num "max"
4934 }
4935 lappend tags m$num
4936 }
4937 $ctext insert end "$line\n" $tags
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004938 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05004939 }
4940 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004941 if {[eof $mdf]} {
4942 close $mdf
4943 return 0
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05004944 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004945 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05004946}
4947
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004948proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004949 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004950
4951 set diffids $ids
4952 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10004953 if {![info exists treediffs($ids)] ||
4954 [lsearch -exact $ids $nullid] >= 0 ||
4955 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04004956 if {![info exists treepending]} {
4957 gettreediffs $ids
4958 }
4959 } else {
4960 addtocflist $ids
4961 }
4962}
4963
4964proc addtocflist {ids} {
4965 global treediffs cflist
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10004966 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10004967 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00004968}
4969
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004970proc diffcmd {ids flags} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004971 global nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004972
4973 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10004974 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004975 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004976 if {[llength $ids] > 1 && $j < 0} {
4977 # comparing working directory with some specific revision
4978 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004979 if {$i == 0} {
4980 lappend cmd -R [lindex $ids 1]
4981 } else {
4982 lappend cmd [lindex $ids 0]
4983 }
4984 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10004985 # comparing working directory with index
4986 set cmd [concat | git diff-files $flags]
4987 if {$j == 1} {
4988 lappend cmd -R
4989 }
4990 }
4991 } elseif {$j >= 0} {
4992 set cmd [concat | git diff-index --cached $flags]
4993 if {[llength $ids] > 1} {
4994 # comparing index with specific revision
4995 if {$i == 0} {
4996 lappend cmd -R [lindex $ids 1]
4997 } else {
4998 lappend cmd [lindex $ids 0]
4999 }
5000 } else {
5001 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005002 lappend cmd HEAD
5003 }
5004 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10005005 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005006 }
5007 return $cmd
5008}
5009
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005010proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10005011 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005012
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005013 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005014 set treediff {}
Paul Mackerras8f489362007-07-13 19:49:37 +10005015 if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005016 fconfigure $gdtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005017 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005018}
5019
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005020proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005021 global treediff treediffs treepending diffids diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10005022 global cmitmode
Paul Mackerras3c461ff2005-07-20 09:13:46 -04005023
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005024 set nr 0
5025 while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005026 set i [string first "\t" $line]
5027 if {$i >= 0} {
5028 set file [string range $line [expr {$i+1}] end]
5029 if {[string index $file 0] eq "\""} {
5030 set file [lindex $file 0]
5031 }
5032 lappend treediff $file
5033 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005034 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005035 if {![eof $gdtf]} {
5036 return [expr {$nr >= 1000? 2: 1}]
5037 }
5038 close $gdtf
5039 set treediffs($ids) $treediff
5040 unset treepending
5041 if {$cmitmode eq "tree"} {
5042 gettree $diffids
5043 } elseif {$ids != $diffids} {
5044 if {![info exists diffmergeid]} {
5045 gettreediffs $diffids
5046 }
5047 } else {
5048 addtocflist $ids
5049 }
5050 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00005051}
5052
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005053proc getblobdiffs {ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005054 global diffopts blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005055 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005056
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005057 set env(GIT_DIFF_OPTS) $diffopts
Paul Mackerras8f489362007-07-13 19:49:37 +10005058 if {[catch {set bdf [open [diffcmd $ids {-p -C --no-commit-id}] r]} err]} {
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005059 puts "error getting diffs: $err"
5060 return
5061 }
Paul Mackerras4f2c2642005-07-17 11:11:44 -04005062 set diffinhdr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005063 fconfigure $bdf -blocking 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005064 set blobdifffd($ids) $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005065 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005066}
5067
Paul Mackerras89b11d32006-05-02 19:55:31 +10005068proc setinlist {var i val} {
5069 global $var
5070
5071 while {[llength [set $var]] < $i} {
5072 lappend $var {}
5073 }
5074 if {[llength [set $var]] == $i} {
5075 lappend $var $val
5076 } else {
5077 lset $var $i $val
5078 }
5079}
5080
Paul Mackerras9396cd32007-06-23 20:28:15 +10005081proc makediffhdr {fname ids} {
5082 global ctext curdiffstart treediffs
5083
5084 set i [lsearch -exact $treediffs($ids) $fname]
5085 if {$i >= 0} {
5086 setinlist difffilestart $i $curdiffstart
5087 }
5088 set l [expr {(78 - [string length $fname]) / 2}]
5089 set pad [string range "----------------------------------------" 1 $l]
5090 $ctext insert $curdiffstart "$pad $fname $pad" filesep
5091}
5092
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005093proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005094 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04005095 global diffnexthead diffnextnote difffilestart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005096 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005097
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005098 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005099 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005100 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
5101 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
5102 close $bdf
5103 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10005104 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10005105 if {![string compare -length 11 "diff --git " $line]} {
5106 # trim off "diff --git "
5107 set line [string range $line 11 end]
5108 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005109 # start of a new file
5110 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10005111 set curdiffstart [$ctext index "end - 1c"]
5112 $ctext insert end "\n" filesep
5113 # If the name hasn't changed the length will be odd,
5114 # the middle char will be a space, and the two bits either
5115 # side will be a/name and b/name, or "a/name" and "b/name".
5116 # If the name has changed we'll get "rename from" and
5117 # "rename to" lines following this, and we'll use them
5118 # to get the filenames.
5119 # This complexity is necessary because spaces in the filename(s)
5120 # don't get escaped.
5121 set l [string length $line]
5122 set i [expr {$l / 2}]
5123 if {!(($l & 1) && [string index $line $i] eq " " &&
5124 [string range $line 2 [expr {$i - 1}]] eq \
5125 [string range $line [expr {$i + 3}] end])} {
5126 continue
Paul Mackerras89b11d32006-05-02 19:55:31 +10005127 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10005128 # unescape if quoted and chop off the a/ from the front
5129 if {[string index $line 0] eq "\""} {
5130 set fname [string range [lindex $line 0] 2 end]
5131 } else {
5132 set fname [string range $line 2 [expr {$i - 1}]]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005133 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10005134 makediffhdr $fname $ids
5135
5136 } elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005137 $line match f1l f1c f2l f2c rest]} {
5138 $ctext insert end "$line\n" hunksep
5139 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10005140
5141 } elseif {$diffinhdr} {
5142 if {![string compare -length 12 "rename from " $line]} {
5143 set fname [string range $line 12 end]
5144 if {[string index $fname 0] eq "\""} {
5145 set fname [lindex $fname 0]
5146 }
5147 set i [lsearch -exact $treediffs($ids) $fname]
5148 if {$i >= 0} {
5149 setinlist difffilestart $i $curdiffstart
5150 }
5151 } elseif {![string compare -length 10 $line "rename to "]} {
5152 set fname [string range $line 10 end]
5153 if {[string index $fname 0] eq "\""} {
5154 set fname [lindex $fname 0]
5155 }
5156 makediffhdr $fname $ids
5157 } elseif {[string compare -length 3 $line "---"] == 0} {
5158 # do nothing
5159 continue
5160 } elseif {[string compare -length 3 $line "+++"] == 0} {
5161 set diffinhdr 0
5162 continue
5163 }
5164 $ctext insert end "$line\n" filesep
5165
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005166 } else {
5167 set x [string range $line 0 0]
5168 if {$x == "-" || $x == "+"} {
5169 set tag [expr {$x == "+"}]
5170 $ctext insert end "$line\n" d$tag
5171 } elseif {$x == " "} {
5172 $ctext insert end "$line\n"
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005173 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10005174 # "\ No newline at end of file",
5175 # or something else we don't recognize
5176 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005177 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005178 }
5179 }
5180 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005181 if {[eof $bdf]} {
5182 close $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005183 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005184 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10005185 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005186}
5187
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10005188proc changediffdisp {} {
5189 global ctext diffelide
5190
5191 $ctext tag conf d0 -elide [lindex $diffelide 0]
5192 $ctext tag conf d1 -elide [lindex $diffelide 1]
5193}
5194
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09005195proc prevfile {} {
5196 global difffilestart ctext
5197 set prev [lindex $difffilestart 0]
5198 set here [$ctext index @0,0]
5199 foreach loc $difffilestart {
5200 if {[$ctext compare $loc >= $here]} {
5201 $ctext yview $prev
5202 return
5203 }
5204 set prev $loc
5205 }
5206 $ctext yview $prev
5207}
5208
Paul Mackerras39ad8572005-05-19 12:35:53 +00005209proc nextfile {} {
5210 global difffilestart ctext
5211 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005212 foreach loc $difffilestart {
5213 if {[$ctext compare $loc > $here]} {
5214 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09005215 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00005216 }
5217 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00005218}
5219
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005220proc clear_ctext {{first 1.0}} {
5221 global ctext smarktop smarkbot
5222
Paul Mackerras1902c272006-05-25 21:25:13 +10005223 set l [lindex [split $first .] 0]
5224 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
5225 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005226 }
Paul Mackerras1902c272006-05-25 21:25:13 +10005227 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
5228 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005229 }
5230 $ctext delete $first end
5231}
5232
5233proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005234 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005235
5236 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10005237 if {[catch {$ctext index anchor}]} {
5238 # no anchor set, use start of selection, or of visible area
5239 set sel [$ctext tag ranges sel]
5240 if {$sel ne {}} {
5241 $ctext mark set anchor [lindex $sel 0]
5242 } elseif {$searchdirn eq "-forwards"} {
5243 $ctext mark set anchor @0,0
5244 } else {
5245 $ctext mark set anchor @0,[winfo height $ctext]
5246 }
5247 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005248 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005249 set here [$ctext search $searchdirn -- $searchstring anchor]
5250 if {$here ne {}} {
5251 $ctext see $here
5252 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005253 searchmarkvisible 1
5254 }
5255}
5256
5257proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005258 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005259
5260 focus $sstring
5261 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10005262 set searchdirn -forwards
5263 if {$searchstring ne {}} {
5264 set sel [$ctext tag ranges sel]
5265 if {$sel ne {}} {
5266 set start "[lindex $sel 0] + 1c"
5267 } elseif {[catch {set start [$ctext index anchor]}]} {
5268 set start "@0,0"
5269 }
5270 set match [$ctext search -count mlen -- $searchstring $start]
5271 $ctext tag remove sel 1.0 end
5272 if {$match eq {}} {
5273 bell
5274 return
5275 }
5276 $ctext see $match
5277 set mend "$match + $mlen c"
5278 $ctext tag add sel $match $mend
5279 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005280 }
Paul Mackerras1902c272006-05-25 21:25:13 +10005281}
5282
5283proc dosearchback {} {
5284 global sstring ctext searchstring searchdirn
5285
5286 focus $sstring
5287 $sstring icursor end
5288 set searchdirn -backwards
5289 if {$searchstring ne {}} {
5290 set sel [$ctext tag ranges sel]
5291 if {$sel ne {}} {
5292 set start [lindex $sel 0]
5293 } elseif {[catch {set start [$ctext index anchor]}]} {
5294 set start @0,[winfo height $ctext]
5295 }
5296 set match [$ctext search -backwards -count ml -- $searchstring $start]
5297 $ctext tag remove sel 1.0 end
5298 if {$match eq {}} {
5299 bell
5300 return
5301 }
5302 $ctext see $match
5303 set mend "$match + $ml c"
5304 $ctext tag add sel $match $mend
5305 $ctext mark unset anchor
5306 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005307}
5308
5309proc searchmark {first last} {
5310 global ctext searchstring
5311
5312 set mend $first.0
5313 while {1} {
5314 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
5315 if {$match eq {}} break
5316 set mend "$match + $mlen c"
5317 $ctext tag add found $match $mend
5318 }
5319}
5320
5321proc searchmarkvisible {doall} {
5322 global ctext smarktop smarkbot
5323
5324 set topline [lindex [split [$ctext index @0,0] .] 0]
5325 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
5326 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
5327 # no overlap with previous
5328 searchmark $topline $botline
5329 set smarktop $topline
5330 set smarkbot $botline
5331 } else {
5332 if {$topline < $smarktop} {
5333 searchmark $topline [expr {$smarktop-1}]
5334 set smarktop $topline
5335 }
5336 if {$botline > $smarkbot} {
5337 searchmark [expr {$smarkbot+1}] $botline
5338 set smarkbot $botline
5339 }
5340 }
5341}
5342
5343proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10005344 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005345
Junio C Hamanoe9937d22007-02-01 08:46:38 -05005346 .bleft.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005347 if {$searchstring ne {}} {
5348 searchmarkvisible 0
5349 }
5350}
5351
Paul Mackerras1d10f362005-05-15 12:55:47 +00005352proc setcoords {} {
5353 global linespc charspc canvx0 canvy0 mainfont
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005354 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10005355
Paul Mackerras1d10f362005-05-15 12:55:47 +00005356 set linespc [font metrics $mainfont -linespace]
5357 set charspc [font measure $mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005358 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
5359 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10005360 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10005361 set xspc1(0) $linespc
5362 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00005363}
Paul Mackerras1db95b02005-05-09 04:08:39 +00005364
Paul Mackerras1d10f362005-05-15 12:55:47 +00005365proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005366 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005367 global selectedline
5368
5369 set ymax [lindex [$canv cget -scrollregion] 3]
5370 if {$ymax eq {} || $ymax == 0} return
5371 set span [$canv yview]
5372 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005373 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005374 allcanvs yview moveto [lindex $span 0]
5375 drawvisible
5376 if {[info exists selectedline]} {
5377 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005378 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00005379 }
5380}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005381
5382proc incrfont {inc} {
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005383 global mainfont textfont ctext canv phase cflist
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005384 global charspc tabstop
Paul Mackerrascfb45632005-05-31 12:14:42 +00005385 global stopped entries
Paul Mackerras1d10f362005-05-15 12:55:47 +00005386 unmarkmatches
5387 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
Paul Mackerras1d10f362005-05-15 12:55:47 +00005388 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
5389 setcoords
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04005390 $ctext conf -font $textfont -tabs "[expr {$tabstop * $charspc}]"
Mark Levedahl59ddaf32007-05-20 11:45:49 -04005391 $cflist conf -font $textfont
Paul Mackerras1d10f362005-05-15 12:55:47 +00005392 $ctext tag conf filesep -font [concat $textfont bold]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005393 foreach e $entries {
5394 $e conf -font $mainfont
5395 }
Paul Mackerras22626ef2006-04-17 09:56:02 +10005396 if {$phase eq "getcommits"} {
Paul Mackerras1d10f362005-05-15 12:55:47 +00005397 $canv itemconf textitems -font $mainfont
5398 }
5399 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00005400}
Paul Mackerras1d10f362005-05-15 12:55:47 +00005401
Paul Mackerrasee3dc722005-06-25 16:37:13 +10005402proc clearsha1 {} {
5403 global sha1entry sha1string
5404 if {[string length $sha1string] == 40} {
5405 $sha1entry delete 0 end
5406 }
5407}
5408
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005409proc sha1change {n1 n2 op} {
5410 global sha1string currentid sha1but
5411 if {$sha1string == {}
5412 || ([info exists currentid] && $sha1string == $currentid)} {
5413 set state disabled
5414 } else {
5415 set state normal
5416 }
5417 if {[$sha1but cget -state] == $state} return
5418 if {$state == "normal"} {
5419 $sha1but conf -state normal -relief raised -text "Goto: "
5420 } else {
5421 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
5422 }
5423}
5424
5425proc gotocommit {} {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005426 global sha1string currentid commitrow tagids headids
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005427 global displayorder numcommits curview
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005428
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005429 if {$sha1string == {}
5430 || ([info exists currentid] && $sha1string == $currentid)} return
5431 if {[info exists tagids($sha1string)]} {
5432 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11005433 } elseif {[info exists headids($sha1string)]} {
5434 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005435 } else {
5436 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005437 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
5438 set matches {}
Paul Mackerras8ed16482006-03-02 22:56:44 +11005439 foreach i $displayorder {
5440 if {[string match $id* $i]} {
5441 lappend matches $i
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005442 }
5443 }
5444 if {$matches ne {}} {
5445 if {[llength $matches] > 1} {
5446 error_popup "Short SHA1 id $id is ambiguous"
5447 return
5448 }
5449 set id [lindex $matches 0]
5450 }
5451 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005452 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005453 if {[info exists commitrow($curview,$id)]} {
5454 selectline $commitrow($curview,$id) 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005455 return
5456 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04005457 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005458 set type "SHA1 id"
5459 } else {
Stephen Rothwelle1007122006-03-30 16:13:12 +11005460 set type "Tag/Head"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005461 }
5462 error_popup "$type $sha1string is not known"
5463}
5464
Paul Mackerras84ba7342005-06-17 00:12:26 +00005465proc lineenter {x y id} {
5466 global hoverx hovery hoverid hovertimer
5467 global commitinfo canv
5468
Paul Mackerras8ed16482006-03-02 22:56:44 +11005469 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00005470 set hoverx $x
5471 set hovery $y
5472 set hoverid $id
5473 if {[info exists hovertimer]} {
5474 after cancel $hovertimer
5475 }
5476 set hovertimer [after 500 linehover]
5477 $canv delete hover
5478}
5479
5480proc linemotion {x y id} {
5481 global hoverx hovery hoverid hovertimer
5482
5483 if {[info exists hoverid] && $id == $hoverid} {
5484 set hoverx $x
5485 set hovery $y
5486 if {[info exists hovertimer]} {
5487 after cancel $hovertimer
5488 }
5489 set hovertimer [after 500 linehover]
5490 }
5491}
5492
5493proc lineleave {id} {
5494 global hoverid hovertimer canv
5495
5496 if {[info exists hoverid] && $id == $hoverid} {
5497 $canv delete hover
5498 if {[info exists hovertimer]} {
5499 after cancel $hovertimer
5500 unset hovertimer
5501 }
5502 unset hoverid
5503 }
5504}
5505
5506proc linehover {} {
5507 global hoverx hovery hoverid hovertimer
5508 global canv linespc lthickness
5509 global commitinfo mainfont
5510
5511 set text [lindex $commitinfo($hoverid) 0]
5512 set ymax [lindex [$canv cget -scrollregion] 3]
5513 if {$ymax == {}} return
5514 set yfrac [lindex [$canv yview] 0]
5515 set x [expr {$hoverx + 2 * $linespc}]
5516 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
5517 set x0 [expr {$x - 2 * $lthickness}]
5518 set y0 [expr {$y - 2 * $lthickness}]
5519 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
5520 set y1 [expr {$y + $linespc + 2 * $lthickness}]
5521 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
5522 -fill \#ffff80 -outline black -width 1 -tags hover]
5523 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10005524 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
5525 -font $mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00005526 $canv raise $t
5527}
5528
Paul Mackerras9843c302005-08-30 10:57:11 +10005529proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005530 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10005531
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005532 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10005533 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005534 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005535 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005536 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005537 if {abs([yc $row] - $y) < $thresh} {
5538 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10005539 }
5540 }
5541 return {}
5542}
5543
Paul Mackerrasf6342482006-02-28 10:02:03 +11005544proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005545 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10005546
Paul Mackerrasf6342482006-02-28 10:02:03 +11005547 # 1 <-> 2, 3 <-> 4, etc...
5548 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005549 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11005550 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10005551 set ymax [lindex [$canv cget -scrollregion] 3]
5552 if {$ymax eq {} || $ymax <= 0} return
5553 set view [$canv yview]
5554 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
5555 set yfrac [expr {$yt / $ymax - $yspan / 2}]
5556 if {$yfrac < 0} {
5557 set yfrac 0
5558 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11005559 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10005560}
5561
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005562proc lineclick {x y id isnew} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005563 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005564
Paul Mackerras8ed16482006-03-02 22:56:44 +11005565 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005566 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005567 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10005568 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005569 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10005570 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10005571 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005572 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005573 if {$isnew} {
5574 set ymax [lindex [$canv cget -scrollregion] 3]
5575 if {$ymax eq {}} return
5576 set yfrac [lindex [$canv yview] 0]
5577 set y [expr {$y + $yfrac * $ymax}]
5578 }
5579 set dirn [clickisonarrow $id $y]
5580 if {$dirn ne {}} {
5581 arrowjump $id $dirn $y
5582 return
5583 }
5584
5585 if {$isnew} {
5586 addtohistory [list lineclick $x $y $id 0]
5587 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005588 # fill the details pane with info about this line
5589 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005590 clear_ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005591 $ctext tag conf link -foreground blue -underline 1
5592 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
5593 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
5594 $ctext insert end "Parent:\t"
5595 $ctext insert end $id [list link link0]
5596 $ctext tag bind link0 <1> [list selbyid $id]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005597 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005598 $ctext insert end "\n\t[lindex $info 0]\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005599 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11005600 set date [formatdate [lindex $info 2]]
5601 $ctext insert end "\tDate:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005602 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005603 if {$kids ne {}} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005604 $ctext insert end "\nChildren:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005605 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10005606 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005607 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11005608 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005609 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005610 $ctext insert end "\n\t"
5611 $ctext insert end $child [list link link$i]
5612 $ctext tag bind link$i <1> [list selbyid $child]
5613 $ctext insert end "\n\t[lindex $info 0]"
5614 $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11005615 set date [formatdate [lindex $info 2]]
5616 $ctext insert end "\n\tDate:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005617 }
5618 }
5619 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005620 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005621}
5622
Paul Mackerras9843c302005-08-30 10:57:11 +10005623proc normalline {} {
5624 global thickerline
5625 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005626 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10005627 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005628 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10005629 }
5630}
5631
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005632proc selbyid {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005633 global commitrow curview
5634 if {[info exists commitrow($curview,$id)]} {
5635 selectline $commitrow($curview,$id) 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005636 }
5637}
5638
5639proc mstime {} {
5640 global startmstime
5641 if {![info exists startmstime]} {
5642 set startmstime [clock clicks -milliseconds]
5643 }
5644 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
5645}
5646
5647proc rowmenu {x y id} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005648 global rowctxmenu commitrow selectedline rowmenuid curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005649 global nullid nullid2 fakerowmenu mainhead
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005650
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005651 set rowmenuid $id
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005652 if {![info exists selectedline]
5653 || $commitrow($curview,$id) eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005654 set state disabled
5655 } else {
5656 set state normal
5657 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005658 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005659 set menu $rowctxmenu
Paul Mackerras6fb735a2006-10-19 10:09:06 +10005660 $menu entryconfigure 7 -label "Reset $mainhead branch to here"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005661 } else {
5662 set menu $fakerowmenu
5663 }
5664 $menu entryconfigure "Diff this*" -state $state
5665 $menu entryconfigure "Diff selected*" -state $state
5666 $menu entryconfigure "Make patch" -state $state
5667 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005668}
5669
5670proc diffvssel {dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005671 global rowmenuid selectedline displayorder
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005672
5673 if {![info exists selectedline]} return
5674 if {$dirn} {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005675 set oldid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005676 set newid $rowmenuid
5677 } else {
5678 set oldid $rowmenuid
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005679 set newid [lindex $displayorder $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005680 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005681 addtohistory [list doseldiff $oldid $newid]
5682 doseldiff $oldid $newid
5683}
5684
5685proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005686 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005687 global commitinfo
5688
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005689 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005690 clear_ctext
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005691 init_flist "Top"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005692 $ctext insert end "From "
5693 $ctext tag conf link -foreground blue -underline 1
5694 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
5695 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
5696 $ctext tag bind link0 <1> [list selbyid $oldid]
5697 $ctext insert end $oldid [list link link0]
5698 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005699 $ctext insert end [lindex $commitinfo($oldid) 0]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005700 $ctext insert end "\n\nTo "
5701 $ctext tag bind link1 <1> [list selbyid $newid]
5702 $ctext insert end $newid [list link link1]
5703 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005704 $ctext insert end [lindex $commitinfo($newid) 0]
5705 $ctext insert end "\n"
5706 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005707 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11005708 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005709}
5710
Paul Mackerras74daedb2005-06-27 19:27:32 +10005711proc mkpatch {} {
5712 global rowmenuid currentid commitinfo patchtop patchnum
5713
5714 if {![info exists currentid]} return
5715 set oldid $currentid
5716 set oldhead [lindex $commitinfo($oldid) 0]
5717 set newid $rowmenuid
5718 set newhead [lindex $commitinfo($newid) 0]
5719 set top .patch
5720 set patchtop $top
5721 catch {destroy $top}
5722 toplevel $top
5723 label $top.title -text "Generate patch"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005724 grid $top.title - -pady 10
Paul Mackerras74daedb2005-06-27 19:27:32 +10005725 label $top.from -text "From:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005726 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005727 $top.fromsha1 insert 0 $oldid
5728 $top.fromsha1 conf -state readonly
5729 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005730 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005731 $top.fromhead insert 0 $oldhead
5732 $top.fromhead conf -state readonly
5733 grid x $top.fromhead -sticky w
5734 label $top.to -text "To:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005735 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005736 $top.tosha1 insert 0 $newid
5737 $top.tosha1 conf -state readonly
5738 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005739 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10005740 $top.tohead insert 0 $newhead
5741 $top.tohead conf -state readonly
5742 grid x $top.tohead -sticky w
5743 button $top.rev -text "Reverse" -command mkpatchrev -padx 5
5744 grid $top.rev x -pady 10
5745 label $top.flab -text "Output file:"
5746 entry $top.fname -width 60
5747 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
5748 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005749 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10005750 frame $top.buts
5751 button $top.buts.gen -text "Generate" -command mkpatchgo
5752 button $top.buts.can -text "Cancel" -command mkpatchcan
5753 grid $top.buts.gen $top.buts.can
5754 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5755 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5756 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005757 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10005758}
5759
5760proc mkpatchrev {} {
5761 global patchtop
5762
5763 set oldid [$patchtop.fromsha1 get]
5764 set oldhead [$patchtop.fromhead get]
5765 set newid [$patchtop.tosha1 get]
5766 set newhead [$patchtop.tohead get]
5767 foreach e [list fromsha1 fromhead tosha1 tohead] \
5768 v [list $newid $newhead $oldid $oldhead] {
5769 $patchtop.$e conf -state normal
5770 $patchtop.$e delete 0 end
5771 $patchtop.$e insert 0 $v
5772 $patchtop.$e conf -state readonly
5773 }
5774}
5775
5776proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005777 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10005778
5779 set oldid [$patchtop.fromsha1 get]
5780 set newid [$patchtop.tosha1 get]
5781 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10005782 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005783 lappend cmd >$fname &
5784 if {[catch {eval exec $cmd} err]} {
Paul Mackerras74daedb2005-06-27 19:27:32 +10005785 error_popup "Error creating patch: $err"
5786 }
5787 catch {destroy $patchtop}
5788 unset patchtop
5789}
5790
5791proc mkpatchcan {} {
5792 global patchtop
5793
5794 catch {destroy $patchtop}
5795 unset patchtop
5796}
5797
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005798proc mktag {} {
5799 global rowmenuid mktagtop commitinfo
5800
5801 set top .maketag
5802 set mktagtop $top
5803 catch {destroy $top}
5804 toplevel $top
5805 label $top.title -text "Create tag"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005806 grid $top.title - -pady 10
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005807 label $top.id -text "ID:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005808 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005809 $top.sha1 insert 0 $rowmenuid
5810 $top.sha1 conf -state readonly
5811 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005812 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005813 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5814 $top.head conf -state readonly
5815 grid x $top.head -sticky w
5816 label $top.tlab -text "Tag name:"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005817 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005818 grid $top.tlab $top.tag -sticky w
5819 frame $top.buts
5820 button $top.buts.gen -text "Create" -command mktaggo
5821 button $top.buts.can -text "Cancel" -command mktagcan
5822 grid $top.buts.gen $top.buts.can
5823 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5824 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5825 grid $top.buts - -pady 10 -sticky ew
5826 focus $top.tag
5827}
5828
5829proc domktag {} {
5830 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005831
5832 set id [$mktagtop.sha1 get]
5833 set tag [$mktagtop.tag get]
5834 if {$tag == {}} {
5835 error_popup "No tag name specified"
5836 return
5837 }
5838 if {[info exists tagids($tag)]} {
5839 error_popup "Tag \"$tag\" already exists"
5840 return
5841 }
5842 if {[catch {
Junio C Hamano73b6a6c2005-07-28 00:28:44 -07005843 set dir [gitdir]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005844 set fname [file join $dir "refs/tags" $tag]
5845 set f [open $fname w]
5846 puts $f $id
5847 close $f
5848 } err]} {
5849 error_popup "Error creating tag: $err"
5850 return
5851 }
5852
5853 set tagids($tag) $id
5854 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005855 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10005856 addedtag $id
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005857}
5858
5859proc redrawtags {id} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005860 global canv linehtag commitrow idpos selectedline curview
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005861 global mainfont canvxmax iddrawn
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005862
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005863 if {![info exists commitrow($curview,$id)]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005864 if {![info exists iddrawn($id)]} return
5865 drawcommits $commitrow($curview,$id)
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005866 $canv delete tag.$id
5867 set xt [eval drawtags $id $idpos($id)]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005868 $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005869 set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text]
5870 set xr [expr {$xt + [font measure $mainfont $text]}]
5871 if {$xr > $canvxmax} {
5872 set canvxmax $xr
5873 setcanvscroll
5874 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005875 if {[info exists selectedline]
5876 && $selectedline == $commitrow($curview,$id)} {
Paul Mackerrasd6982062005-08-06 22:06:06 +10005877 selectline $selectedline 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005878 }
5879}
5880
5881proc mktagcan {} {
5882 global mktagtop
5883
5884 catch {destroy $mktagtop}
5885 unset mktagtop
5886}
5887
5888proc mktaggo {} {
5889 domktag
5890 mktagcan
5891}
5892
Paul Mackerras4a2139f2005-06-29 09:47:48 +10005893proc writecommit {} {
5894 global rowmenuid wrcomtop commitinfo wrcomcmd
5895
5896 set top .writecommit
5897 set wrcomtop $top
5898 catch {destroy $top}
5899 toplevel $top
5900 label $top.title -text "Write commit to file"
5901 grid $top.title - -pady 10
5902 label $top.id -text "ID:"
5903 entry $top.sha1 -width 40 -relief flat
5904 $top.sha1 insert 0 $rowmenuid
5905 $top.sha1 conf -state readonly
5906 grid $top.id $top.sha1 -sticky w
5907 entry $top.head -width 60 -relief flat
5908 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
5909 $top.head conf -state readonly
5910 grid x $top.head -sticky w
5911 label $top.clab -text "Command:"
5912 entry $top.cmd -width 60 -textvariable wrcomcmd
5913 grid $top.clab $top.cmd -sticky w -pady 10
5914 label $top.flab -text "Output file:"
5915 entry $top.fname -width 60
5916 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
5917 grid $top.flab $top.fname -sticky w
5918 frame $top.buts
5919 button $top.buts.gen -text "Write" -command wrcomgo
5920 button $top.buts.can -text "Cancel" -command wrcomcan
5921 grid $top.buts.gen $top.buts.can
5922 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5923 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5924 grid $top.buts - -pady 10 -sticky ew
5925 focus $top.fname
5926}
5927
5928proc wrcomgo {} {
5929 global wrcomtop
5930
5931 set id [$wrcomtop.sha1 get]
5932 set cmd "echo $id | [$wrcomtop.cmd get]"
5933 set fname [$wrcomtop.fname get]
5934 if {[catch {exec sh -c $cmd >$fname &} err]} {
5935 error_popup "Error writing commit: $err"
5936 }
5937 catch {destroy $wrcomtop}
5938 unset wrcomtop
5939}
5940
5941proc wrcomcan {} {
5942 global wrcomtop
5943
5944 catch {destroy $wrcomtop}
5945 unset wrcomtop
5946}
5947
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005948proc mkbranch {} {
5949 global rowmenuid mkbrtop
5950
5951 set top .makebranch
5952 catch {destroy $top}
5953 toplevel $top
5954 label $top.title -text "Create new branch"
5955 grid $top.title - -pady 10
5956 label $top.id -text "ID:"
5957 entry $top.sha1 -width 40 -relief flat
5958 $top.sha1 insert 0 $rowmenuid
5959 $top.sha1 conf -state readonly
5960 grid $top.id $top.sha1 -sticky w
5961 label $top.nlab -text "Name:"
5962 entry $top.name -width 40
5963 grid $top.nlab $top.name -sticky w
5964 frame $top.buts
5965 button $top.buts.go -text "Create" -command [list mkbrgo $top]
5966 button $top.buts.can -text "Cancel" -command "catch {destroy $top}"
5967 grid $top.buts.go $top.buts.can
5968 grid columnconfigure $top.buts 0 -weight 1 -uniform a
5969 grid columnconfigure $top.buts 1 -weight 1 -uniform a
5970 grid $top.buts - -pady 10 -sticky ew
5971 focus $top.name
5972}
5973
5974proc mkbrgo {top} {
5975 global headids idheads
5976
5977 set name [$top.name get]
5978 set id [$top.sha1 get]
5979 if {$name eq {}} {
5980 error_popup "Please specify a name for the new branch"
5981 return
5982 }
5983 catch {destroy $top}
5984 nowbusy newbranch
5985 update
5986 if {[catch {
5987 exec git branch $name $id
5988 } err]} {
5989 notbusy newbranch
5990 error_popup $err
5991 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10005992 set headids($name) $id
5993 lappend idheads($id) $name
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10005994 addedhead $id $name
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005995 notbusy newbranch
5996 redrawtags $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10005997 dispneartags 0
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10005998 }
5999}
6000
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006001proc cherrypick {} {
6002 global rowmenuid curview commitrow
Paul Mackerrase11f1232007-06-16 20:29:25 +10006003 global mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006004
Paul Mackerrase11f1232007-06-16 20:29:25 +10006005 set oldhead [exec git rev-parse HEAD]
6006 set dheads [descheads $rowmenuid]
6007 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006008 set ok [confirm_popup "Commit [string range $rowmenuid 0 7] is already\
6009 included in branch $mainhead -- really re-apply it?"]
6010 if {!$ok} return
6011 }
6012 nowbusy cherrypick
6013 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006014 # Unfortunately git-cherry-pick writes stuff to stderr even when
6015 # no error occurs, and exec takes that as an indication of error...
6016 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
6017 notbusy cherrypick
6018 error_popup $err
6019 return
6020 }
6021 set newhead [exec git rev-parse HEAD]
6022 if {$newhead eq $oldhead} {
6023 notbusy cherrypick
6024 error_popup "No changes committed"
6025 return
6026 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006027 addnewchild $newhead $oldhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006028 if {[info exists commitrow($curview,$oldhead)]} {
6029 insertrow $commitrow($curview,$oldhead) $newhead
6030 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006031 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006032 movedhead $newhead $mainhead
6033 }
6034 redrawtags $oldhead
6035 redrawtags $newhead
6036 }
6037 notbusy cherrypick
6038}
6039
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006040proc resethead {} {
6041 global mainheadid mainhead rowmenuid confirm_ok resettype
6042 global showlocalchanges
6043
6044 set confirm_ok 0
6045 set w ".confirmreset"
6046 toplevel $w
6047 wm transient $w .
6048 wm title $w "Confirm reset"
6049 message $w.m -text \
6050 "Reset branch $mainhead to [string range $rowmenuid 0 7]?" \
6051 -justify center -aspect 1000
6052 pack $w.m -side top -fill x -padx 20 -pady 20
6053 frame $w.f -relief sunken -border 2
6054 message $w.f.rt -text "Reset type:" -aspect 1000
6055 grid $w.f.rt -sticky w
6056 set resettype mixed
6057 radiobutton $w.f.soft -value soft -variable resettype -justify left \
6058 -text "Soft: Leave working tree and index untouched"
6059 grid $w.f.soft -sticky w
6060 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
6061 -text "Mixed: Leave working tree untouched, reset index"
6062 grid $w.f.mixed -sticky w
6063 radiobutton $w.f.hard -value hard -variable resettype -justify left \
6064 -text "Hard: Reset working tree and index\n(discard ALL local changes)"
6065 grid $w.f.hard -sticky w
6066 pack $w.f -side top -fill x
6067 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
6068 pack $w.ok -side left -fill x -padx 20 -pady 20
6069 button $w.cancel -text Cancel -command "destroy $w"
6070 pack $w.cancel -side right -fill x -padx 20 -pady 20
6071 bind $w <Visibility> "grab $w; focus $w"
6072 tkwait window $w
6073 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10006074 if {[catch {set fd [open \
6075 [list | sh -c "git reset --$resettype $rowmenuid 2>&1"] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006076 error_popup $err
6077 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10006078 dohidelocalchanges
6079 set w ".resetprogress"
6080 filerun $fd [list readresetstat $fd $w]
6081 toplevel $w
6082 wm transient $w
6083 wm title $w "Reset progress"
6084 message $w.m -text "Reset in progress, please wait..." \
6085 -justify center -aspect 1000
6086 pack $w.m -side top -fill x -padx 20 -pady 5
6087 canvas $w.c -width 150 -height 20 -bg white
6088 $w.c create rect 0 0 0 20 -fill green -tags rect
6089 pack $w.c -side top -fill x -padx 20 -pady 5 -expand 1
6090 nowbusy reset
6091 }
6092}
6093
6094proc readresetstat {fd w} {
6095 global mainhead mainheadid showlocalchanges
6096
6097 if {[gets $fd line] >= 0} {
6098 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
6099 set x [expr {($m * 150) / $n}]
6100 $w.c coords rect 0 0 $x 20
6101 }
6102 return 1
6103 }
6104 destroy $w
6105 notbusy reset
6106 if {[catch {close $fd} err]} {
6107 error_popup $err
6108 }
6109 set oldhead $mainheadid
6110 set newhead [exec git rev-parse HEAD]
6111 if {$newhead ne $oldhead} {
6112 movehead $newhead $mainhead
6113 movedhead $newhead $mainhead
6114 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006115 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10006116 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006117 }
6118 if {$showlocalchanges} {
6119 doshowlocalchanges
6120 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10006121 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006122}
6123
Paul Mackerras10299152006-08-02 09:52:01 +10006124# context menu for a head
6125proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10006126 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10006127
6128 set headmenuid $id
6129 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10006130 set state normal
6131 if {$head eq $mainhead} {
6132 set state disabled
6133 }
6134 $headctxmenu entryconfigure 0 -state $state
6135 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10006136 tk_popup $headctxmenu $x $y
6137}
6138
6139proc cobranch {} {
6140 global headmenuid headmenuhead mainhead headids
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006141 global showlocalchanges mainheadid
Paul Mackerras10299152006-08-02 09:52:01 +10006142
6143 # check the tree is clean first??
6144 set oldmainhead $mainhead
6145 nowbusy checkout
6146 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006147 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10006148 if {[catch {
Paul Mackerras696cf492007-05-22 09:52:00 +10006149 exec git checkout -q $headmenuhead
Paul Mackerras10299152006-08-02 09:52:01 +10006150 } err]} {
6151 notbusy checkout
6152 error_popup $err
6153 } else {
6154 notbusy checkout
Paul Mackerras53cda8d2006-08-02 19:43:34 +10006155 set mainhead $headmenuhead
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006156 set mainheadid $headmenuid
Paul Mackerras10299152006-08-02 09:52:01 +10006157 if {[info exists headids($oldmainhead)]} {
6158 redrawtags $headids($oldmainhead)
6159 }
6160 redrawtags $headmenuid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10006161 }
6162 if {$showlocalchanges} {
6163 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10006164 }
6165}
6166
6167proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006168 global headmenuid headmenuhead mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10006169 global headids idheads
6170
6171 set head $headmenuhead
6172 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10006173 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10006174 if {$head eq $mainhead} {
6175 error_popup "Cannot delete the currently checked-out branch"
6176 return
6177 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006178 set dheads [descheads $id]
6179 if {$dheads eq $headids($head)} {
Paul Mackerras10299152006-08-02 09:52:01 +10006180 # the stuff on this branch isn't on any other branch
6181 if {![confirm_popup "The commits on branch $head aren't on any other\
6182 branch.\nReally delete branch $head?"]} return
6183 }
6184 nowbusy rmbranch
6185 update
6186 if {[catch {exec git branch -D $head} err]} {
6187 notbusy rmbranch
6188 error_popup $err
6189 return
6190 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006191 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006192 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10006193 redrawtags $id
6194 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10006195 dispneartags 0
Paul Mackerras10299152006-08-02 09:52:01 +10006196}
6197
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006198# Stuff for finding nearby tags
6199proc getallcommits {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006200 global allcommits allids nbmp nextarc seeds
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006201
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006202 set allids {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10006203 set nbmp 0
6204 set nextarc 0
6205 set allcommits 0
6206 set seeds {}
6207 regetallcommits
6208}
6209
6210# Called when the graph might have changed
6211proc regetallcommits {} {
6212 global allcommits seeds
6213
6214 set cmd [concat | git rev-list --all --parents]
6215 foreach id $seeds {
6216 lappend cmd "^$id"
6217 }
6218 set fd [open $cmd r]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006219 fconfigure $fd -blocking 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006220 incr allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006221 nowbusy allcommits
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006222 filerun $fd [list getallclines $fd]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006223}
6224
Paul Mackerrase11f1232007-06-16 20:29:25 +10006225# Since most commits have 1 parent and 1 child, we group strings of
6226# such commits into "arcs" joining branch/merge points (BMPs), which
6227# are commits that either don't have 1 parent or don't have 1 child.
6228#
6229# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
6230# arcout(id) - outgoing arcs for BMP
6231# arcids(a) - list of IDs on arc including end but not start
6232# arcstart(a) - BMP ID at start of arc
6233# arcend(a) - BMP ID at end of arc
6234# growing(a) - arc a is still growing
6235# arctags(a) - IDs out of arcids (excluding end) that have tags
6236# archeads(a) - IDs out of arcids (excluding end) that have heads
6237# The start of an arc is at the descendent end, so "incoming" means
6238# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10006239
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006240proc getallclines {fd} {
Paul Mackerrasf3326b62007-06-18 22:39:21 +10006241 global allids allparents allchildren idtags idheads nextarc nbmp
Paul Mackerrase11f1232007-06-16 20:29:25 +10006242 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006243 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006244
Paul Mackerrase11f1232007-06-16 20:29:25 +10006245 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006246 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006247 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10006248 if {[info exists allparents($id)]} {
6249 # seen it already
6250 continue
6251 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006252 lappend allids $id
6253 set olds [lrange $line 1 end]
6254 set allparents($id) $olds
6255 if {![info exists allchildren($id)]} {
6256 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10006257 set arcnos($id) {}
6258 lappend seeds $id
6259 } else {
6260 set a $arcnos($id)
6261 if {[llength $olds] == 1 && [llength $a] == 1} {
6262 lappend arcids($a) $id
6263 if {[info exists idtags($id)]} {
6264 lappend arctags($a) $id
6265 }
6266 if {[info exists idheads($id)]} {
6267 lappend archeads($a) $id
6268 }
6269 if {[info exists allparents($olds)]} {
6270 # seen parent already
6271 if {![info exists arcout($olds)]} {
6272 splitarc $olds
6273 }
6274 lappend arcids($a) $olds
6275 set arcend($a) $olds
6276 unset growing($a)
6277 }
6278 lappend allchildren($olds) $id
6279 lappend arcnos($olds) $a
6280 continue
6281 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006282 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006283 incr nbmp
6284 foreach a $arcnos($id) {
6285 lappend arcids($a) $id
6286 set arcend($a) $id
6287 unset growing($a)
6288 }
6289
6290 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006291 foreach p $olds {
6292 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10006293 set a [incr nextarc]
6294 set arcstart($a) $id
6295 set archeads($a) {}
6296 set arctags($a) {}
6297 set archeads($a) {}
6298 set arcids($a) {}
6299 lappend ao $a
6300 set growing($a) 1
6301 if {[info exists allparents($p)]} {
6302 # seen it already, may need to make a new branch
6303 if {![info exists arcout($p)]} {
6304 splitarc $p
6305 }
6306 lappend arcids($a) $p
6307 set arcend($a) $p
6308 unset growing($a)
6309 }
6310 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006311 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006312 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006313 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10006314 if {$nid > 0} {
6315 global cached_dheads cached_dtags cached_atags
6316 catch {unset cached_dheads}
6317 catch {unset cached_dtags}
6318 catch {unset cached_atags}
6319 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006320 if {![eof $fd]} {
6321 return [expr {$nid >= 1000? 2: 1}]
6322 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006323 close $fd
6324 if {[incr allcommits -1] == 0} {
6325 notbusy allcommits
6326 }
6327 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006328 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006329}
6330
6331proc recalcarc {a} {
6332 global arctags archeads arcids idtags idheads
6333
6334 set at {}
6335 set ah {}
6336 foreach id [lrange $arcids($a) 0 end-1] {
6337 if {[info exists idtags($id)]} {
6338 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006339 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006340 if {[info exists idheads($id)]} {
6341 lappend ah $id
6342 }
6343 }
6344 set arctags($a) $at
6345 set archeads($a) $ah
6346}
6347
6348proc splitarc {p} {
6349 global arcnos arcids nextarc nbmp arctags archeads idtags idheads
6350 global arcstart arcend arcout allparents growing
6351
6352 set a $arcnos($p)
6353 if {[llength $a] != 1} {
6354 puts "oops splitarc called but [llength $a] arcs already"
6355 return
6356 }
6357 set a [lindex $a 0]
6358 set i [lsearch -exact $arcids($a) $p]
6359 if {$i < 0} {
6360 puts "oops splitarc $p not in arc $a"
6361 return
6362 }
6363 set na [incr nextarc]
6364 if {[info exists arcend($a)]} {
6365 set arcend($na) $arcend($a)
6366 } else {
6367 set l [lindex $allparents([lindex $arcids($a) end]) 0]
6368 set j [lsearch -exact $arcnos($l) $a]
6369 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
6370 }
6371 set tail [lrange $arcids($a) [expr {$i+1}] end]
6372 set arcids($a) [lrange $arcids($a) 0 $i]
6373 set arcend($a) $p
6374 set arcstart($na) $p
6375 set arcout($p) $na
6376 set arcids($na) $tail
6377 if {[info exists growing($a)]} {
6378 set growing($na) 1
6379 unset growing($a)
6380 }
6381 incr nbmp
6382
6383 foreach id $tail {
6384 if {[llength $arcnos($id)] == 1} {
6385 set arcnos($id) $na
6386 } else {
6387 set j [lsearch -exact $arcnos($id) $a]
6388 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
6389 }
6390 }
6391
6392 # reconstruct tags and heads lists
6393 if {$arctags($a) ne {} || $archeads($a) ne {}} {
6394 recalcarc $a
6395 recalcarc $na
6396 } else {
6397 set arctags($na) {}
6398 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006399 }
6400}
6401
Paul Mackerrase11f1232007-06-16 20:29:25 +10006402# Update things for a new commit added that is a child of one
6403# existing commit. Used when cherry-picking.
6404proc addnewchild {id p} {
6405 global allids allparents allchildren idtags nextarc nbmp
6406 global arcnos arcids arctags arcout arcend arcstart archeads growing
6407 global seeds
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006408
Paul Mackerrase11f1232007-06-16 20:29:25 +10006409 lappend allids $id
6410 set allparents($id) [list $p]
6411 set allchildren($id) {}
6412 set arcnos($id) {}
6413 lappend seeds $id
6414 incr nbmp
6415 lappend allchildren($p) $id
6416 set a [incr nextarc]
6417 set arcstart($a) $id
6418 set archeads($a) {}
6419 set arctags($a) {}
6420 set arcids($a) [list $p]
6421 set arcend($a) $p
6422 if {![info exists arcout($p)]} {
6423 splitarc $p
6424 }
6425 lappend arcnos($p) $a
6426 set arcout($id) [list $a]
6427}
6428
6429# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
6430# or 0 if neither is true.
6431proc anc_or_desc {a b} {
6432 global arcout arcstart arcend arcnos cached_isanc
6433
6434 if {$arcnos($a) eq $arcnos($b)} {
6435 # Both are on the same arc(s); either both are the same BMP,
6436 # or if one is not a BMP, the other is also not a BMP or is
6437 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +10006438 # Or both can be BMPs with no incoming arcs.
6439 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006440 return 0
6441 }
6442 # assert {[llength $arcnos($a)] == 1}
6443 set arc [lindex $arcnos($a) 0]
6444 set i [lsearch -exact $arcids($arc) $a]
6445 set j [lsearch -exact $arcids($arc) $b]
6446 if {$i < 0 || $i > $j} {
6447 return 1
6448 } else {
6449 return -1
6450 }
6451 }
6452
6453 if {![info exists arcout($a)]} {
6454 set arc [lindex $arcnos($a) 0]
6455 if {[info exists arcend($arc)]} {
6456 set aend $arcend($arc)
6457 } else {
6458 set aend {}
6459 }
6460 set a $arcstart($arc)
6461 } else {
6462 set aend $a
6463 }
6464 if {![info exists arcout($b)]} {
6465 set arc [lindex $arcnos($b) 0]
6466 if {[info exists arcend($arc)]} {
6467 set bend $arcend($arc)
6468 } else {
6469 set bend {}
6470 }
6471 set b $arcstart($arc)
6472 } else {
6473 set bend $b
6474 }
6475 if {$a eq $bend} {
6476 return 1
6477 }
6478 if {$b eq $aend} {
6479 return -1
6480 }
6481 if {[info exists cached_isanc($a,$bend)]} {
6482 if {$cached_isanc($a,$bend)} {
6483 return 1
6484 }
6485 }
6486 if {[info exists cached_isanc($b,$aend)]} {
6487 if {$cached_isanc($b,$aend)} {
6488 return -1
6489 }
6490 if {[info exists cached_isanc($a,$bend)]} {
6491 return 0
6492 }
6493 }
6494
6495 set todo [list $a $b]
6496 set anc($a) a
6497 set anc($b) b
6498 for {set i 0} {$i < [llength $todo]} {incr i} {
6499 set x [lindex $todo $i]
6500 if {$anc($x) eq {}} {
6501 continue
6502 }
6503 foreach arc $arcnos($x) {
6504 set xd $arcstart($arc)
6505 if {$xd eq $bend} {
6506 set cached_isanc($a,$bend) 1
6507 set cached_isanc($b,$aend) 0
6508 return 1
6509 } elseif {$xd eq $aend} {
6510 set cached_isanc($b,$aend) 1
6511 set cached_isanc($a,$bend) 0
6512 return -1
6513 }
6514 if {![info exists anc($xd)]} {
6515 set anc($xd) $anc($x)
6516 lappend todo $xd
6517 } elseif {$anc($xd) ne $anc($x)} {
6518 set anc($xd) {}
6519 }
6520 }
6521 }
6522 set cached_isanc($a,$bend) 0
6523 set cached_isanc($b,$aend) 0
6524 return 0
6525}
6526
6527# This identifies whether $desc has an ancestor that is
6528# a growing tip of the graph and which is not an ancestor of $anc
6529# and returns 0 if so and 1 if not.
6530# If we subsequently discover a tag on such a growing tip, and that
6531# turns out to be a descendent of $anc (which it could, since we
6532# don't necessarily see children before parents), then $desc
6533# isn't a good choice to display as a descendent tag of
6534# $anc (since it is the descendent of another tag which is
6535# a descendent of $anc). Similarly, $anc isn't a good choice to
6536# display as a ancestor tag of $desc.
6537#
6538proc is_certain {desc anc} {
6539 global arcnos arcout arcstart arcend growing problems
6540
6541 set certain {}
6542 if {[llength $arcnos($anc)] == 1} {
6543 # tags on the same arc are certain
6544 if {$arcnos($desc) eq $arcnos($anc)} {
6545 return 1
6546 }
6547 if {![info exists arcout($anc)]} {
6548 # if $anc is partway along an arc, use the start of the arc instead
6549 set a [lindex $arcnos($anc) 0]
6550 set anc $arcstart($a)
6551 }
6552 }
6553 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
6554 set x $desc
6555 } else {
6556 set a [lindex $arcnos($desc) 0]
6557 set x $arcend($a)
6558 }
6559 if {$x == $anc} {
6560 return 1
6561 }
6562 set anclist [list $x]
6563 set dl($x) 1
6564 set nnh 1
6565 set ngrowanc 0
6566 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
6567 set x [lindex $anclist $i]
6568 if {$dl($x)} {
6569 incr nnh -1
6570 }
6571 set done($x) 1
6572 foreach a $arcout($x) {
6573 if {[info exists growing($a)]} {
6574 if {![info exists growanc($x)] && $dl($x)} {
6575 set growanc($x) 1
6576 incr ngrowanc
6577 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006578 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10006579 set y $arcend($a)
6580 if {[info exists dl($y)]} {
6581 if {$dl($y)} {
6582 if {!$dl($x)} {
6583 set dl($y) 0
6584 if {![info exists done($y)]} {
6585 incr nnh -1
6586 }
6587 if {[info exists growanc($x)]} {
6588 incr ngrowanc -1
6589 }
6590 set xl [list $y]
6591 for {set k 0} {$k < [llength $xl]} {incr k} {
6592 set z [lindex $xl $k]
6593 foreach c $arcout($z) {
6594 if {[info exists arcend($c)]} {
6595 set v $arcend($c)
6596 if {[info exists dl($v)] && $dl($v)} {
6597 set dl($v) 0
6598 if {![info exists done($v)]} {
6599 incr nnh -1
6600 }
6601 if {[info exists growanc($v)]} {
6602 incr ngrowanc -1
6603 }
6604 lappend xl $v
6605 }
6606 }
6607 }
6608 }
6609 }
6610 }
6611 } elseif {$y eq $anc || !$dl($x)} {
6612 set dl($y) 0
6613 lappend anclist $y
6614 } else {
6615 set dl($y) 1
6616 lappend anclist $y
6617 incr nnh
6618 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006619 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006620 }
6621 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006622 foreach x [array names growanc] {
6623 if {$dl($x)} {
6624 return 0
6625 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006626 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10006627 }
6628 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006629}
6630
Paul Mackerrase11f1232007-06-16 20:29:25 +10006631proc validate_arctags {a} {
6632 global arctags idtags
6633
6634 set i -1
6635 set na $arctags($a)
6636 foreach id $arctags($a) {
6637 incr i
6638 if {![info exists idtags($id)]} {
6639 set na [lreplace $na $i $i]
6640 incr i -1
6641 }
6642 }
6643 set arctags($a) $na
6644}
6645
6646proc validate_archeads {a} {
6647 global archeads idheads
6648
6649 set i -1
6650 set na $archeads($a)
6651 foreach id $archeads($a) {
6652 incr i
6653 if {![info exists idheads($id)]} {
6654 set na [lreplace $na $i $i]
6655 incr i -1
6656 }
6657 }
6658 set archeads($a) $na
6659}
6660
6661# Return the list of IDs that have tags that are descendents of id,
6662# ignoring IDs that are descendents of IDs already reported.
6663proc desctags {id} {
6664 global arcnos arcstart arcids arctags idtags allparents
6665 global growing cached_dtags
6666
6667 if {![info exists allparents($id)]} {
6668 return {}
6669 }
6670 set t1 [clock clicks -milliseconds]
6671 set argid $id
6672 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6673 # part-way along an arc; check that arc first
6674 set a [lindex $arcnos($id) 0]
6675 if {$arctags($a) ne {}} {
6676 validate_arctags $a
6677 set i [lsearch -exact $arcids($a) $id]
6678 set tid {}
6679 foreach t $arctags($a) {
6680 set j [lsearch -exact $arcids($a) $t]
6681 if {$j >= $i} break
6682 set tid $t
6683 }
6684 if {$tid ne {}} {
6685 return $tid
6686 }
6687 }
6688 set id $arcstart($a)
6689 if {[info exists idtags($id)]} {
6690 return $id
6691 }
6692 }
6693 if {[info exists cached_dtags($id)]} {
6694 return $cached_dtags($id)
6695 }
6696
6697 set origid $id
6698 set todo [list $id]
6699 set queued($id) 1
6700 set nc 1
6701 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
6702 set id [lindex $todo $i]
6703 set done($id) 1
6704 set ta [info exists hastaggedancestor($id)]
6705 if {!$ta} {
6706 incr nc -1
6707 }
6708 # ignore tags on starting node
6709 if {!$ta && $i > 0} {
6710 if {[info exists idtags($id)]} {
6711 set tagloc($id) $id
6712 set ta 1
6713 } elseif {[info exists cached_dtags($id)]} {
6714 set tagloc($id) $cached_dtags($id)
6715 set ta 1
6716 }
6717 }
6718 foreach a $arcnos($id) {
6719 set d $arcstart($a)
6720 if {!$ta && $arctags($a) ne {}} {
6721 validate_arctags $a
6722 if {$arctags($a) ne {}} {
6723 lappend tagloc($id) [lindex $arctags($a) end]
6724 }
6725 }
6726 if {$ta || $arctags($a) ne {}} {
6727 set tomark [list $d]
6728 for {set j 0} {$j < [llength $tomark]} {incr j} {
6729 set dd [lindex $tomark $j]
6730 if {![info exists hastaggedancestor($dd)]} {
6731 if {[info exists done($dd)]} {
6732 foreach b $arcnos($dd) {
6733 lappend tomark $arcstart($b)
6734 }
6735 if {[info exists tagloc($dd)]} {
6736 unset tagloc($dd)
6737 }
6738 } elseif {[info exists queued($dd)]} {
6739 incr nc -1
6740 }
6741 set hastaggedancestor($dd) 1
6742 }
6743 }
6744 }
6745 if {![info exists queued($d)]} {
6746 lappend todo $d
6747 set queued($d) 1
6748 if {![info exists hastaggedancestor($d)]} {
6749 incr nc
6750 }
6751 }
6752 }
6753 }
6754 set tags {}
6755 foreach id [array names tagloc] {
6756 if {![info exists hastaggedancestor($id)]} {
6757 foreach t $tagloc($id) {
6758 if {[lsearch -exact $tags $t] < 0} {
6759 lappend tags $t
6760 }
6761 }
6762 }
6763 }
6764 set t2 [clock clicks -milliseconds]
6765 set loopix $i
6766
6767 # remove tags that are descendents of other tags
6768 for {set i 0} {$i < [llength $tags]} {incr i} {
6769 set a [lindex $tags $i]
6770 for {set j 0} {$j < $i} {incr j} {
6771 set b [lindex $tags $j]
6772 set r [anc_or_desc $a $b]
6773 if {$r == 1} {
6774 set tags [lreplace $tags $j $j]
6775 incr j -1
6776 incr i -1
6777 } elseif {$r == -1} {
6778 set tags [lreplace $tags $i $i]
6779 incr i -1
6780 break
6781 }
6782 }
6783 }
6784
6785 if {[array names growing] ne {}} {
6786 # graph isn't finished, need to check if any tag could get
6787 # eclipsed by another tag coming later. Simply ignore any
6788 # tags that could later get eclipsed.
6789 set ctags {}
6790 foreach t $tags {
6791 if {[is_certain $t $origid]} {
6792 lappend ctags $t
6793 }
6794 }
6795 if {$tags eq $ctags} {
6796 set cached_dtags($origid) $tags
6797 } else {
6798 set tags $ctags
6799 }
6800 } else {
6801 set cached_dtags($origid) $tags
6802 }
6803 set t3 [clock clicks -milliseconds]
6804 if {0 && $t3 - $t1 >= 100} {
6805 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
6806 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
6807 }
6808 return $tags
6809}
6810
6811proc anctags {id} {
6812 global arcnos arcids arcout arcend arctags idtags allparents
6813 global growing cached_atags
6814
6815 if {![info exists allparents($id)]} {
6816 return {}
6817 }
6818 set t1 [clock clicks -milliseconds]
6819 set argid $id
6820 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6821 # part-way along an arc; check that arc first
6822 set a [lindex $arcnos($id) 0]
6823 if {$arctags($a) ne {}} {
6824 validate_arctags $a
6825 set i [lsearch -exact $arcids($a) $id]
6826 foreach t $arctags($a) {
6827 set j [lsearch -exact $arcids($a) $t]
6828 if {$j > $i} {
6829 return $t
6830 }
6831 }
6832 }
6833 if {![info exists arcend($a)]} {
6834 return {}
6835 }
6836 set id $arcend($a)
6837 if {[info exists idtags($id)]} {
6838 return $id
6839 }
6840 }
6841 if {[info exists cached_atags($id)]} {
6842 return $cached_atags($id)
6843 }
6844
6845 set origid $id
6846 set todo [list $id]
6847 set queued($id) 1
6848 set taglist {}
6849 set nc 1
6850 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
6851 set id [lindex $todo $i]
6852 set done($id) 1
6853 set td [info exists hastaggeddescendent($id)]
6854 if {!$td} {
6855 incr nc -1
6856 }
6857 # ignore tags on starting node
6858 if {!$td && $i > 0} {
6859 if {[info exists idtags($id)]} {
6860 set tagloc($id) $id
6861 set td 1
6862 } elseif {[info exists cached_atags($id)]} {
6863 set tagloc($id) $cached_atags($id)
6864 set td 1
6865 }
6866 }
6867 foreach a $arcout($id) {
6868 if {!$td && $arctags($a) ne {}} {
6869 validate_arctags $a
6870 if {$arctags($a) ne {}} {
6871 lappend tagloc($id) [lindex $arctags($a) 0]
6872 }
6873 }
6874 if {![info exists arcend($a)]} continue
6875 set d $arcend($a)
6876 if {$td || $arctags($a) ne {}} {
6877 set tomark [list $d]
6878 for {set j 0} {$j < [llength $tomark]} {incr j} {
6879 set dd [lindex $tomark $j]
6880 if {![info exists hastaggeddescendent($dd)]} {
6881 if {[info exists done($dd)]} {
6882 foreach b $arcout($dd) {
6883 if {[info exists arcend($b)]} {
6884 lappend tomark $arcend($b)
6885 }
6886 }
6887 if {[info exists tagloc($dd)]} {
6888 unset tagloc($dd)
6889 }
6890 } elseif {[info exists queued($dd)]} {
6891 incr nc -1
6892 }
6893 set hastaggeddescendent($dd) 1
6894 }
6895 }
6896 }
6897 if {![info exists queued($d)]} {
6898 lappend todo $d
6899 set queued($d) 1
6900 if {![info exists hastaggeddescendent($d)]} {
6901 incr nc
6902 }
6903 }
6904 }
6905 }
6906 set t2 [clock clicks -milliseconds]
6907 set loopix $i
6908 set tags {}
6909 foreach id [array names tagloc] {
6910 if {![info exists hastaggeddescendent($id)]} {
6911 foreach t $tagloc($id) {
6912 if {[lsearch -exact $tags $t] < 0} {
6913 lappend tags $t
6914 }
6915 }
6916 }
6917 }
6918
6919 # remove tags that are ancestors of other tags
6920 for {set i 0} {$i < [llength $tags]} {incr i} {
6921 set a [lindex $tags $i]
6922 for {set j 0} {$j < $i} {incr j} {
6923 set b [lindex $tags $j]
6924 set r [anc_or_desc $a $b]
6925 if {$r == -1} {
6926 set tags [lreplace $tags $j $j]
6927 incr j -1
6928 incr i -1
6929 } elseif {$r == 1} {
6930 set tags [lreplace $tags $i $i]
6931 incr i -1
6932 break
6933 }
6934 }
6935 }
6936
6937 if {[array names growing] ne {}} {
6938 # graph isn't finished, need to check if any tag could get
6939 # eclipsed by another tag coming later. Simply ignore any
6940 # tags that could later get eclipsed.
6941 set ctags {}
6942 foreach t $tags {
6943 if {[is_certain $origid $t]} {
6944 lappend ctags $t
6945 }
6946 }
6947 if {$tags eq $ctags} {
6948 set cached_atags($origid) $tags
6949 } else {
6950 set tags $ctags
6951 }
6952 } else {
6953 set cached_atags($origid) $tags
6954 }
6955 set t3 [clock clicks -milliseconds]
6956 if {0 && $t3 - $t1 >= 100} {
6957 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
6958 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
6959 }
6960 return $tags
6961}
6962
6963# Return the list of IDs that have heads that are descendents of id,
6964# including id itself if it has a head.
6965proc descheads {id} {
6966 global arcnos arcstart arcids archeads idheads cached_dheads
6967 global allparents
6968
6969 if {![info exists allparents($id)]} {
6970 return {}
6971 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10006972 set aret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10006973 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
6974 # part-way along an arc; check it first
6975 set a [lindex $arcnos($id) 0]
6976 if {$archeads($a) ne {}} {
6977 validate_archeads $a
6978 set i [lsearch -exact $arcids($a) $id]
6979 foreach t $archeads($a) {
6980 set j [lsearch -exact $arcids($a) $t]
6981 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +10006982 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +10006983 }
6984 }
6985 set id $arcstart($a)
6986 }
6987 set origid $id
6988 set todo [list $id]
6989 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +10006990 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10006991 for {set i 0} {$i < [llength $todo]} {incr i} {
6992 set id [lindex $todo $i]
6993 if {[info exists cached_dheads($id)]} {
6994 set ret [concat $ret $cached_dheads($id)]
6995 } else {
6996 if {[info exists idheads($id)]} {
6997 lappend ret $id
6998 }
6999 foreach a $arcnos($id) {
7000 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +10007001 validate_archeads $a
7002 if {$archeads($a) ne {}} {
7003 set ret [concat $ret $archeads($a)]
7004 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007005 }
7006 set d $arcstart($a)
7007 if {![info exists seen($d)]} {
7008 lappend todo $d
7009 set seen($d) 1
7010 }
7011 }
7012 }
7013 }
7014 set ret [lsort -unique $ret]
7015 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +10007016 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +10007017}
7018
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007019proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007020 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007021
Paul Mackerrase11f1232007-06-16 20:29:25 +10007022 if {![info exists arcnos($id)]} return
7023 if {![info exists arcout($id)]} {
7024 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007025 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007026 catch {unset cached_dtags}
7027 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007028}
7029
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007030proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007031 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007032
Paul Mackerrase11f1232007-06-16 20:29:25 +10007033 if {![info exists arcnos($hid)]} return
7034 if {![info exists arcout($hid)]} {
7035 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007036 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007037 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007038}
7039
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007040proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007041 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007042
Paul Mackerrase11f1232007-06-16 20:29:25 +10007043 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +10007044}
7045
Paul Mackerrase11f1232007-06-16 20:29:25 +10007046proc movedhead {hid head} {
7047 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007048
Paul Mackerrase11f1232007-06-16 20:29:25 +10007049 if {![info exists arcnos($hid)]} return
7050 if {![info exists arcout($hid)]} {
7051 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007052 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007053 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007054}
7055
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007056proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007057 global cached_dheads cached_dtags cached_atags
7058 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007059
Paul Mackerrase11f1232007-06-16 20:29:25 +10007060 foreach id [concat [array names idheads] [array names idtags]] {
7061 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
7062 set a [lindex $arcnos($id) 0]
7063 if {![info exists donearc($a)]} {
7064 recalcarc $a
7065 set donearc($a) 1
7066 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007067 }
7068 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007069 catch {unset cached_dtags}
7070 catch {unset cached_atags}
7071 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007072}
7073
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007074proc rereadrefs {} {
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007075 global idtags idheads idotherrefs mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007076
7077 set refids [concat [array names idtags] \
7078 [array names idheads] [array names idotherrefs]]
7079 foreach id $refids {
7080 if {![info exists ref($id)]} {
7081 set ref($id) [listrefs $id]
7082 }
7083 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007084 set oldmainhead $mainhead
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007085 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007086 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007087 set refids [lsort -unique [concat $refids [array names idtags] \
7088 [array names idheads] [array names idotherrefs]]]
7089 foreach id $refids {
7090 set v [listrefs $id]
Paul Mackerrascec7bec2006-08-02 09:38:10 +10007091 if {![info exists ref($id)] || $ref($id) != $v ||
7092 ($id eq $oldmainhead && $id ne $mainhead) ||
7093 ($id eq $mainhead && $id ne $oldmainhead)} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007094 redrawtags $id
7095 }
7096 }
7097}
7098
Junio C Hamano2e1ded42006-06-11 09:50:47 -07007099proc listrefs {id} {
7100 global idtags idheads idotherrefs
7101
7102 set x {}
7103 if {[info exists idtags($id)]} {
7104 set x $idtags($id)
7105 }
7106 set y {}
7107 if {[info exists idheads($id)]} {
7108 set y $idheads($id)
7109 }
7110 set z {}
7111 if {[info exists idotherrefs($id)]} {
7112 set z $idotherrefs($id)
7113 }
7114 return [list $x $y $z]
7115}
7116
Paul Mackerras106288c2005-08-19 23:11:39 +10007117proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10007118 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +10007119
7120 if {$isnew} {
7121 addtohistory [list showtag $tag 0]
7122 }
7123 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007124 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007125 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +10007126 if {![info exists tagcontents($tag)]} {
7127 catch {
7128 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
7129 }
7130 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007131 if {[info exists tagcontents($tag)]} {
7132 set text $tagcontents($tag)
7133 } else {
7134 set text "Tag: $tag\nId: $tagids($tag)"
7135 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007136 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +10007137 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007138 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +10007139}
7140
Paul Mackerras1d10f362005-05-15 12:55:47 +00007141proc doquit {} {
7142 global stopped
7143 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -05007144 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +00007145 destroy .
7146}
7147
Paul Mackerras712fcc02005-11-30 09:28:16 +11007148proc doprefs {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10007149 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007150 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl60378c02007-05-20 12:12:48 -04007151 global bgcolor fgcolor ctext diffcolors selectbgcolor
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007152 global uifont tabstop
Paul Mackerras232475d2005-11-15 10:34:03 +11007153
Paul Mackerras712fcc02005-11-30 09:28:16 +11007154 set top .gitkprefs
7155 set prefstop $top
7156 if {[winfo exists $top]} {
7157 raise $top
7158 return
Paul Mackerras757f17b2005-11-21 09:56:07 +11007159 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007160 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11007161 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +11007162 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11007163 toplevel $top
7164 wm title $top "Gitk preferences"
7165 label $top.ldisp -text "Commit list display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007166 $top.ldisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11007167 grid $top.ldisp - -sticky w -pady 10
7168 label $top.spacer -text " "
7169 label $top.maxwidthl -text "Maximum graph width (lines)" \
7170 -font optionfont
7171 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
7172 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
7173 label $top.maxpctl -text "Maximum graph width (% of pane)" \
7174 -font optionfont
7175 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
7176 grid x $top.maxpctl $top.maxpct -sticky w
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007177 frame $top.showlocal
7178 label $top.showlocal.l -text "Show local changes" -font optionfont
7179 checkbutton $top.showlocal.b -variable showlocalchanges
7180 pack $top.showlocal.b $top.showlocal.l -side left
7181 grid x $top.showlocal -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007182
Paul Mackerras712fcc02005-11-30 09:28:16 +11007183 label $top.ddisp -text "Diff display options"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007184 $top.ddisp configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11007185 grid $top.ddisp - -sticky w -pady 10
7186 label $top.diffoptl -text "Options for diff program" \
7187 -font optionfont
7188 entry $top.diffopt -width 20 -textvariable diffopts
7189 grid x $top.diffoptl $top.diffopt -sticky w
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007190 frame $top.ntag
7191 label $top.ntag.l -text "Display nearby tags" -font optionfont
7192 checkbutton $top.ntag.b -variable showneartags
7193 pack $top.ntag.b $top.ntag.l -side left
7194 grid x $top.ntag -sticky w
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007195 label $top.tabstopl -text "tabstop" -font optionfont
Mark Levedahl6bc9d1e2007-06-26 21:51:35 -04007196 spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007197 grid x $top.tabstopl $top.tabstop -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007198
7199 label $top.cdisp -text "Colors: press to choose"
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007200 $top.cdisp configure -font $uifont
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007201 grid $top.cdisp - -sticky w -pady 10
7202 label $top.bg -padx 40 -relief sunk -background $bgcolor
7203 button $top.bgbut -text "Background" -font optionfont \
7204 -command [list choosecolor bgcolor 0 $top.bg background setbg]
7205 grid x $top.bgbut $top.bg -sticky w
7206 label $top.fg -padx 40 -relief sunk -background $fgcolor
7207 button $top.fgbut -text "Foreground" -font optionfont \
7208 -command [list choosecolor fgcolor 0 $top.fg foreground setfg]
7209 grid x $top.fgbut $top.fg -sticky w
7210 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
7211 button $top.diffoldbut -text "Diff: old lines" -font optionfont \
7212 -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
7213 [list $ctext tag conf d0 -foreground]]
7214 grid x $top.diffoldbut $top.diffold -sticky w
7215 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
7216 button $top.diffnewbut -text "Diff: new lines" -font optionfont \
7217 -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
7218 [list $ctext tag conf d1 -foreground]]
7219 grid x $top.diffnewbut $top.diffnew -sticky w
7220 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
7221 button $top.hunksepbut -text "Diff: hunk header" -font optionfont \
7222 -command [list choosecolor diffcolors 2 $top.hunksep \
7223 "diff hunk header" \
7224 [list $ctext tag conf hunksep -foreground]]
7225 grid x $top.hunksepbut $top.hunksep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -04007226 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
7227 button $top.selbgbut -text "Select bg" -font optionfont \
Mark Levedahl281404c2007-06-26 21:51:34 -04007228 -command [list choosecolor selectbgcolor 0 $top.selbgsep background setselbg]
Mark Levedahl60378c02007-05-20 12:12:48 -04007229 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007230
Paul Mackerras712fcc02005-11-30 09:28:16 +11007231 frame $top.buts
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04007232 button $top.buts.ok -text "OK" -command prefsok -default active
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007233 $top.buts.ok configure -font $uifont
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04007234 button $top.buts.can -text "Cancel" -command prefscan -default normal
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04007235 $top.buts.can configure -font $uifont
Paul Mackerras712fcc02005-11-30 09:28:16 +11007236 grid $top.buts.ok $top.buts.can
7237 grid columnconfigure $top.buts 0 -weight 1 -uniform a
7238 grid columnconfigure $top.buts 1 -weight 1 -uniform a
7239 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04007240 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +11007241}
7242
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007243proc choosecolor {v vi w x cmd} {
7244 global $v
7245
7246 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
7247 -title "Gitk: choose color for $x"]
7248 if {$c eq {}} return
7249 $w conf -background $c
7250 lset $v $vi $c
7251 eval $cmd $c
7252}
7253
Mark Levedahl60378c02007-05-20 12:12:48 -04007254proc setselbg {c} {
7255 global bglist cflist
7256 foreach w $bglist {
7257 $w configure -selectbackground $c
7258 }
7259 $cflist tag configure highlight \
7260 -background [$cflist cget -selectbackground]
7261 allcanvs itemconf secsel -fill $c
7262}
7263
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007264proc setbg {c} {
7265 global bglist
7266
7267 foreach w $bglist {
7268 $w conf -background $c
7269 }
7270}
7271
7272proc setfg {c} {
7273 global fglist canv
7274
7275 foreach w $fglist {
7276 $w conf -foreground $c
7277 }
7278 allcanvs itemconf text -fill $c
7279 $canv itemconf circle -outline $c
7280}
7281
Paul Mackerras712fcc02005-11-30 09:28:16 +11007282proc prefscan {} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10007283 global maxwidth maxgraphpct diffopts
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007284 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras712fcc02005-11-30 09:28:16 +11007285
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007286 foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11007287 set $v $oldprefs($v)
7288 }
7289 catch {destroy $prefstop}
7290 unset prefstop
7291}
7292
7293proc prefsok {} {
7294 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007295 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007296 global charspc ctext tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11007297
7298 catch {destroy $prefstop}
7299 unset prefstop
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007300 $ctext configure -tabs "[expr {$tabstop * $charspc}]"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007301 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
7302 if {$showlocalchanges} {
7303 doshowlocalchanges
7304 } else {
7305 dohidelocalchanges
7306 }
7307 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11007308 if {$maxwidth != $oldprefs(maxwidth)
7309 || $maxgraphpct != $oldprefs(maxgraphpct)} {
7310 redisplay
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007311 } elseif {$showneartags != $oldprefs(showneartags)} {
7312 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +11007313 }
7314}
7315
7316proc formatdate {d} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007317 if {$d ne {}} {
7318 set d [clock format $d -format "%Y-%m-%d %H:%M:%S"]
7319 }
7320 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +11007321}
7322
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007323# This list of encoding names and aliases is distilled from
7324# http://www.iana.org/assignments/character-sets.
7325# Not all of them are supported by Tcl.
7326set encoding_aliases {
7327 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
7328 ISO646-US US-ASCII us IBM367 cp367 csASCII }
7329 { ISO-10646-UTF-1 csISO10646UTF1 }
7330 { ISO_646.basic:1983 ref csISO646basic1983 }
7331 { INVARIANT csINVARIANT }
7332 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
7333 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
7334 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
7335 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
7336 { NATS-DANO iso-ir-9-1 csNATSDANO }
7337 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
7338 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
7339 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
7340 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
7341 { ISO-2022-KR csISO2022KR }
7342 { EUC-KR csEUCKR }
7343 { ISO-2022-JP csISO2022JP }
7344 { ISO-2022-JP-2 csISO2022JP2 }
7345 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
7346 csISO13JISC6220jp }
7347 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
7348 { IT iso-ir-15 ISO646-IT csISO15Italian }
7349 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
7350 { ES iso-ir-17 ISO646-ES csISO17Spanish }
7351 { greek7-old iso-ir-18 csISO18Greek7Old }
7352 { latin-greek iso-ir-19 csISO19LatinGreek }
7353 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
7354 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
7355 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
7356 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
7357 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
7358 { BS_viewdata iso-ir-47 csISO47BSViewdata }
7359 { INIS iso-ir-49 csISO49INIS }
7360 { INIS-8 iso-ir-50 csISO50INIS8 }
7361 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
7362 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
7363 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
7364 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
7365 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
7366 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
7367 csISO60Norwegian1 }
7368 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
7369 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
7370 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
7371 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
7372 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
7373 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
7374 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
7375 { greek7 iso-ir-88 csISO88Greek7 }
7376 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
7377 { iso-ir-90 csISO90 }
7378 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
7379 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
7380 csISO92JISC62991984b }
7381 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
7382 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
7383 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
7384 csISO95JIS62291984handadd }
7385 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
7386 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
7387 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
7388 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
7389 CP819 csISOLatin1 }
7390 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
7391 { T.61-7bit iso-ir-102 csISO102T617bit }
7392 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
7393 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
7394 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
7395 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
7396 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
7397 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
7398 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
7399 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
7400 arabic csISOLatinArabic }
7401 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
7402 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
7403 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
7404 greek greek8 csISOLatinGreek }
7405 { T.101-G2 iso-ir-128 csISO128T101G2 }
7406 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
7407 csISOLatinHebrew }
7408 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
7409 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
7410 { CSN_369103 iso-ir-139 csISO139CSN369103 }
7411 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
7412 { ISO_6937-2-add iso-ir-142 csISOTextComm }
7413 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
7414 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
7415 csISOLatinCyrillic }
7416 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
7417 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
7418 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
7419 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
7420 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
7421 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
7422 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
7423 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
7424 { ISO_10367-box iso-ir-155 csISO10367Box }
7425 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
7426 { latin-lap lap iso-ir-158 csISO158Lap }
7427 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
7428 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
7429 { us-dk csUSDK }
7430 { dk-us csDKUS }
7431 { JIS_X0201 X0201 csHalfWidthKatakana }
7432 { KSC5636 ISO646-KR csKSC5636 }
7433 { ISO-10646-UCS-2 csUnicode }
7434 { ISO-10646-UCS-4 csUCS4 }
7435 { DEC-MCS dec csDECMCS }
7436 { hp-roman8 roman8 r8 csHPRoman8 }
7437 { macintosh mac csMacintosh }
7438 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
7439 csIBM037 }
7440 { IBM038 EBCDIC-INT cp038 csIBM038 }
7441 { IBM273 CP273 csIBM273 }
7442 { IBM274 EBCDIC-BE CP274 csIBM274 }
7443 { IBM275 EBCDIC-BR cp275 csIBM275 }
7444 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
7445 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
7446 { IBM280 CP280 ebcdic-cp-it csIBM280 }
7447 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
7448 { IBM284 CP284 ebcdic-cp-es csIBM284 }
7449 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
7450 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
7451 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
7452 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
7453 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
7454 { IBM424 cp424 ebcdic-cp-he csIBM424 }
7455 { IBM437 cp437 437 csPC8CodePage437 }
7456 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
7457 { IBM775 cp775 csPC775Baltic }
7458 { IBM850 cp850 850 csPC850Multilingual }
7459 { IBM851 cp851 851 csIBM851 }
7460 { IBM852 cp852 852 csPCp852 }
7461 { IBM855 cp855 855 csIBM855 }
7462 { IBM857 cp857 857 csIBM857 }
7463 { IBM860 cp860 860 csIBM860 }
7464 { IBM861 cp861 861 cp-is csIBM861 }
7465 { IBM862 cp862 862 csPC862LatinHebrew }
7466 { IBM863 cp863 863 csIBM863 }
7467 { IBM864 cp864 csIBM864 }
7468 { IBM865 cp865 865 csIBM865 }
7469 { IBM866 cp866 866 csIBM866 }
7470 { IBM868 CP868 cp-ar csIBM868 }
7471 { IBM869 cp869 869 cp-gr csIBM869 }
7472 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
7473 { IBM871 CP871 ebcdic-cp-is csIBM871 }
7474 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
7475 { IBM891 cp891 csIBM891 }
7476 { IBM903 cp903 csIBM903 }
7477 { IBM904 cp904 904 csIBBM904 }
7478 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
7479 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
7480 { IBM1026 CP1026 csIBM1026 }
7481 { EBCDIC-AT-DE csIBMEBCDICATDE }
7482 { EBCDIC-AT-DE-A csEBCDICATDEA }
7483 { EBCDIC-CA-FR csEBCDICCAFR }
7484 { EBCDIC-DK-NO csEBCDICDKNO }
7485 { EBCDIC-DK-NO-A csEBCDICDKNOA }
7486 { EBCDIC-FI-SE csEBCDICFISE }
7487 { EBCDIC-FI-SE-A csEBCDICFISEA }
7488 { EBCDIC-FR csEBCDICFR }
7489 { EBCDIC-IT csEBCDICIT }
7490 { EBCDIC-PT csEBCDICPT }
7491 { EBCDIC-ES csEBCDICES }
7492 { EBCDIC-ES-A csEBCDICESA }
7493 { EBCDIC-ES-S csEBCDICESS }
7494 { EBCDIC-UK csEBCDICUK }
7495 { EBCDIC-US csEBCDICUS }
7496 { UNKNOWN-8BIT csUnknown8BiT }
7497 { MNEMONIC csMnemonic }
7498 { MNEM csMnem }
7499 { VISCII csVISCII }
7500 { VIQR csVIQR }
7501 { KOI8-R csKOI8R }
7502 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
7503 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
7504 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
7505 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
7506 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
7507 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
7508 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
7509 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
7510 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
7511 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
7512 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
7513 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
7514 { IBM1047 IBM-1047 }
7515 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
7516 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
7517 { UNICODE-1-1 csUnicode11 }
7518 { CESU-8 csCESU-8 }
7519 { BOCU-1 csBOCU-1 }
7520 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
7521 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
7522 l8 }
7523 { ISO-8859-15 ISO_8859-15 Latin-9 }
7524 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
7525 { GBK CP936 MS936 windows-936 }
7526 { JIS_Encoding csJISEncoding }
7527 { Shift_JIS MS_Kanji csShiftJIS }
7528 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
7529 EUC-JP }
7530 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
7531 { ISO-10646-UCS-Basic csUnicodeASCII }
7532 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
7533 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
7534 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
7535 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
7536 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
7537 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
7538 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
7539 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
7540 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
7541 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
7542 { Adobe-Standard-Encoding csAdobeStandardEncoding }
7543 { Ventura-US csVenturaUS }
7544 { Ventura-International csVenturaInternational }
7545 { PC8-Danish-Norwegian csPC8DanishNorwegian }
7546 { PC8-Turkish csPC8Turkish }
7547 { IBM-Symbols csIBMSymbols }
7548 { IBM-Thai csIBMThai }
7549 { HP-Legal csHPLegal }
7550 { HP-Pi-font csHPPiFont }
7551 { HP-Math8 csHPMath8 }
7552 { Adobe-Symbol-Encoding csHPPSMath }
7553 { HP-DeskTop csHPDesktop }
7554 { Ventura-Math csVenturaMath }
7555 { Microsoft-Publishing csMicrosoftPublishing }
7556 { Windows-31J csWindows31J }
7557 { GB2312 csGB2312 }
7558 { Big5 csBig5 }
7559}
7560
7561proc tcl_encoding {enc} {
7562 global encoding_aliases
7563 set names [encoding names]
7564 set lcnames [string tolower $names]
7565 set enc [string tolower $enc]
7566 set i [lsearch -exact $lcnames $enc]
7567 if {$i < 0} {
7568 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
7569 if {[regsub {^iso[-_]} $enc iso encx]} {
7570 set i [lsearch -exact $lcnames $encx]
7571 }
7572 }
7573 if {$i < 0} {
7574 foreach l $encoding_aliases {
7575 set ll [string tolower $l]
7576 if {[lsearch -exact $ll $enc] < 0} continue
7577 # look through the aliases for one that tcl knows about
7578 foreach e $ll {
7579 set i [lsearch -exact $lcnames $e]
7580 if {$i < 0} {
7581 if {[regsub {^iso[-_]} $e iso ex]} {
7582 set i [lsearch -exact $lcnames $ex]
7583 }
7584 }
7585 if {$i >= 0} break
7586 }
7587 break
7588 }
7589 }
7590 if {$i >= 0} {
7591 return [lindex $names $i]
7592 }
7593 return {}
7594}
7595
Paul Mackerras1d10f362005-05-15 12:55:47 +00007596# defaults...
7597set datemode 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007598set diffopts "-U 5 -p"
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03007599set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -08007600
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007601set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -08007602catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +11007603 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -08007604}
7605if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11007606 set gitencoding "utf-8"
7607}
7608set tclencoding [tcl_encoding $gitencoding]
7609if {$tclencoding == {}} {
7610 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -08007611}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007612
7613set mainfont {Helvetica 9}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007614set textfont {Courier 9}
Keith Packard4840be62006-04-04 00:19:45 -07007615set uifont {Helvetica 9 bold}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04007616set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -04007617set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +10007618set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007619set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +11007620set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +11007621set fastdate 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007622set uparrowlen 7
7623set downarrowlen 7
7624set mingaplen 30
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007625set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007626set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007627set showneartags 1
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007628set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +10007629set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007630set showlocalchanges 1
Paul Mackerras1d10f362005-05-15 12:55:47 +00007631
7632set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007633set bgcolor white
7634set fgcolor black
7635set diffcolors {red "#00a000" blue}
Mark Levedahl60378c02007-05-20 12:12:48 -04007636set selectbgcolor gray85
Paul Mackerras1d10f362005-05-15 12:55:47 +00007637
7638catch {source ~/.gitk}
7639
Paul Mackerras712fcc02005-11-30 09:28:16 +11007640font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +00007641
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007642# check that we can find a .git directory somewhere...
Alex Riesen6c87d602007-07-29 22:29:45 +02007643if {[catch {set gitdir [gitdir]}]} {
7644 show_error {} . "Cannot find a git repository here."
7645 exit 1
7646}
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007647if {![file isdirectory $gitdir]} {
Paul Mackerrase54be9e2006-05-26 22:34:30 +10007648 show_error {} . "Cannot find the git directory \"$gitdir\"."
Paul Mackerrasaa81d972006-02-28 11:27:12 +11007649 exit 1
7650}
7651
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10007652set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007653set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10007654set i 0
7655foreach arg $argv {
Paul Mackerras6ebedab2007-07-13 13:45:55 +10007656 switch -- $arg {
7657 "" { }
7658 "-d" { set datemode 1 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10007659 "--" {
7660 set cmdline_files [lrange $argv [expr {$i + 1}] end]
7661 break
7662 }
7663 default {
7664 lappend revtreeargs $arg
7665 }
7666 }
7667 incr i
7668}
7669
7670if {$i >= [llength $argv] && $revtreeargs ne {}} {
7671 # no -- on command line, but some arguments (other than -d)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007672 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03007673 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007674 set cmdline_files [split $f "\n"]
7675 set n [llength $cmdline_files]
7676 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10007677 # Unfortunately git rev-parse doesn't produce an error when
7678 # something is both a revision and a filename. To be consistent
7679 # with git log and git rev-list, check revtreeargs for filenames.
7680 foreach arg $revtreeargs {
7681 if {[file exists $arg]} {
7682 show_error {} . "Ambiguous argument '$arg': both revision\
7683 and filename"
7684 exit 1
7685 }
7686 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007687 } err]} {
7688 # unfortunately we get both stdout and stderr in $err,
7689 # so look for "fatal:".
7690 set i [string first "fatal:" $err]
7691 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -07007692 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007693 }
Paul Mackerrase54be9e2006-05-26 22:34:30 +10007694 show_error {} . "Bad arguments to gitk:\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007695 exit 1
7696 }
7697}
7698
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007699set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +10007700set nullid2 "0000000000000000000000000000000000000001"
7701
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007702
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007703set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007704set history {}
7705set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007706set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007707set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +10007708set highlight_paths {}
Paul Mackerras1902c272006-05-25 21:25:13 +10007709set searchdirn -forwards
Paul Mackerras4e7d6772006-05-30 21:33:07 +10007710set boldrows {}
7711set boldnamerows {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007712set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10007713set markingmatches 0
Paul Mackerrasd6982062005-08-06 22:06:06 +10007714
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007715set optim_delay 16
7716
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007717set nextviewnum 1
7718set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007719set selectedview 0
Paul Mackerras908c3582006-05-20 09:38:11 +10007720set selectedhlview None
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007721set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007722set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007723set viewargs(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007724
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007725set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007726set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +00007727set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +10007728set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007729set lookingforhead 0
Paul Mackerras8f489362007-07-13 19:49:37 +10007730set localirow -1
7731set localfrow -1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007732set lserial 0
Paul Mackerras1d10f362005-05-15 12:55:47 +00007733setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007734makewindow
Paul Mackerras0eafba12007-07-23 21:35:03 +10007735# wait for the window to become visible
7736tkwait visibility .
Doug Maxey6c283322006-12-10 14:31:46 -06007737wm title . "[file tail $argv0]: [file tail [pwd]]"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007738readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10007739
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007740if {$cmdline_files ne {} || $revtreeargs ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007741 # create a view for the files/dirs specified on the command line
7742 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007743 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007744 set nextviewnum 2
7745 set viewname(1) "Command line"
7746 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007747 set viewargs(1) $revtreeargs
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007748 set viewperm(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007749 addviewmenu 1
Paul Mackerras3cd204e2006-11-23 21:06:16 +11007750 .bar.view entryconf Edit* -state normal
7751 .bar.view entryconf Delete* -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007752}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007753
7754if {[info exists permviews]} {
7755 foreach v $permviews {
7756 set n $nextviewnum
7757 incr nextviewnum
7758 set viewname($n) [lindex $v 0]
7759 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10007760 set viewargs($n) [lindex $v 2]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007761 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007762 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10007763 }
7764}
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10007765getcommits