##// END OF EJS Templates
hgk: colorize commits by authors...
Georg.Koltermann@mscsoftware.com -
r5464:7dafd9ab default
parent child Browse files
Show More
@@ -1,3817 +1,3888
1 #!/usr/bin/env wish
1 #!/usr/bin/env wish
2
2
3 # Copyright (C) 2005 Paul Mackerras. All rights reserved.
3 # Copyright (C) 2005 Paul Mackerras. All rights reserved.
4 # This program is free software; it may be used, copied, modified
4 # This program is free software; it may be used, copied, modified
5 # and distributed under the terms of the GNU General Public Licence,
5 # and distributed under the terms of the GNU General Public Licence,
6 # either version 2, or (at your option) any later version.
6 # either version 2, or (at your option) any later version.
7 #
7 #
8 # See hgk.py for extension usage and configuration.
8 # See hgk.py for extension usage and configuration.
9
9
10
10
11 # Modified version of Tip 171:
11 # Modified version of Tip 171:
12 # http://www.tcl.tk/cgi-bin/tct/tip/171.html
12 # http://www.tcl.tk/cgi-bin/tct/tip/171.html
13 #
13 #
14 # The in_mousewheel global was added to fix strange reentrancy issues.
14 # The in_mousewheel global was added to fix strange reentrancy issues.
15 # The whole snipped is activated only under windows, mouse wheel
15 # The whole snipped is activated only under windows, mouse wheel
16 # bindings working already under MacOSX and Linux.
16 # bindings working already under MacOSX and Linux.
17
17
18 if {[tk windowingsystem] eq "win32"} {
18 if {[tk windowingsystem] eq "win32"} {
19
19
20 set mw_classes [list Text Listbox Table TreeCtrl]
20 set mw_classes [list Text Listbox Table TreeCtrl]
21 foreach class $mw_classes { bind $class <MouseWheel> {} }
21 foreach class $mw_classes { bind $class <MouseWheel> {} }
22
22
23 set in_mousewheel 0
23 set in_mousewheel 0
24
24
25 proc ::tk::MouseWheel {wFired X Y D {shifted 0}} {
25 proc ::tk::MouseWheel {wFired X Y D {shifted 0}} {
26 global in_mousewheel
26 global in_mousewheel
27 if { $in_mousewheel != 0 } { return }
27 if { $in_mousewheel != 0 } { return }
28 # Set event to check based on call
28 # Set event to check based on call
29 set evt "<[expr {$shifted?{Shift-}:{}}]MouseWheel>"
29 set evt "<[expr {$shifted?{Shift-}:{}}]MouseWheel>"
30 # do not double-fire in case the class already has a binding
30 # do not double-fire in case the class already has a binding
31 if {[bind [winfo class $wFired] $evt] ne ""} { return }
31 if {[bind [winfo class $wFired] $evt] ne ""} { return }
32 # obtain the window the mouse is over
32 # obtain the window the mouse is over
33 set w [winfo containing $X $Y]
33 set w [winfo containing $X $Y]
34 # if we are outside the app, try and scroll the focus widget
34 # if we are outside the app, try and scroll the focus widget
35 if {![winfo exists $w]} { catch {set w [focus]} }
35 if {![winfo exists $w]} { catch {set w [focus]} }
36 if {[winfo exists $w]} {
36 if {[winfo exists $w]} {
37
37
38 if {[bind $w $evt] ne ""} {
38 if {[bind $w $evt] ne ""} {
39 # Awkward ... this widget has a MouseWheel binding, but to
39 # Awkward ... this widget has a MouseWheel binding, but to
40 # trigger successfully in it, we must give it focus.
40 # trigger successfully in it, we must give it focus.
41 catch {focus} old
41 catch {focus} old
42 if {$w ne $old} { focus $w }
42 if {$w ne $old} { focus $w }
43 set in_mousewheel 1
43 set in_mousewheel 1
44 event generate $w $evt -rootx $X -rooty $Y -delta $D
44 event generate $w $evt -rootx $X -rooty $Y -delta $D
45 set in_mousewheel 0
45 set in_mousewheel 0
46 if {$w ne $old} { focus $old }
46 if {$w ne $old} { focus $old }
47 return
47 return
48 }
48 }
49
49
50 # aqua and x11/win32 have different delta handling
50 # aqua and x11/win32 have different delta handling
51 if {[tk windowingsystem] ne "aqua"} {
51 if {[tk windowingsystem] ne "aqua"} {
52 set delta [expr {- ($D / 30)}]
52 set delta [expr {- ($D / 30)}]
53 } else {
53 } else {
54 set delta [expr {- ($D)}]
54 set delta [expr {- ($D)}]
55 }
55 }
56 # scrollbars have different call conventions
56 # scrollbars have different call conventions
57 if {[string match "*Scrollbar" [winfo class $w]]} {
57 if {[string match "*Scrollbar" [winfo class $w]]} {
58 catch {tk::ScrollByUnits $w \
58 catch {tk::ScrollByUnits $w \
59 [string index [$w cget -orient] 0] $delta}
59 [string index [$w cget -orient] 0] $delta}
60 } else {
60 } else {
61 set cmd [list $w [expr {$shifted ? "xview" : "yview"}] \
61 set cmd [list $w [expr {$shifted ? "xview" : "yview"}] \
62 scroll $delta units]
62 scroll $delta units]
63 # Walking up to find the proper widget (handles cases like
63 # Walking up to find the proper widget (handles cases like
64 # embedded widgets in a canvas)
64 # embedded widgets in a canvas)
65 while {[catch $cmd] && [winfo toplevel $w] ne $w} {
65 while {[catch $cmd] && [winfo toplevel $w] ne $w} {
66 set w [winfo parent $w]
66 set w [winfo parent $w]
67 }
67 }
68 }
68 }
69 }
69 }
70 }
70 }
71
71
72 bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0]
72 bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0]
73
73
74 # end of win32 section
74 # end of win32 section
75 }
75 }
76
76
77
77
78 # Unify right mouse button handling.
78 # Unify right mouse button handling.
79 # See "mouse buttons on macintosh" thread on comp.lang.tcl
79 # See "mouse buttons on macintosh" thread on comp.lang.tcl
80 if {[tk windowingsystem] eq "aqua"} {
80 if {[tk windowingsystem] eq "aqua"} {
81 event add <<B3>> <Control-ButtonPress-1>
81 event add <<B3>> <Control-ButtonPress-1>
82 event add <<B3>> <Button-2>
82 event add <<B3>> <Button-2>
83 } else {
83 } else {
84 event add <<B3>> <Button-3>
84 event add <<B3>> <Button-3>
85 }
85 }
86
86
87 proc gitdir {} {
87 proc gitdir {} {
88 global env
88 global env
89 if {[info exists env(GIT_DIR)]} {
89 if {[info exists env(GIT_DIR)]} {
90 return $env(GIT_DIR)
90 return $env(GIT_DIR)
91 } else {
91 } else {
92 return ".hg"
92 return ".hg"
93 }
93 }
94 }
94 }
95
95
96 proc getcommits {rargs} {
96 proc getcommits {rargs} {
97 global commits commfd phase canv mainfont env
97 global commits commfd phase canv mainfont env
98 global startmsecs nextupdate ncmupdate
98 global startmsecs nextupdate ncmupdate
99 global ctext maincursor textcursor leftover
99 global ctext maincursor textcursor leftover
100
100
101 # check that we can find a .git directory somewhere...
101 # check that we can find a .git directory somewhere...
102 set gitdir [gitdir]
102 set gitdir [gitdir]
103 if {![file isdirectory $gitdir]} {
103 if {![file isdirectory $gitdir]} {
104 error_popup "Cannot find the git directory \"$gitdir\"."
104 error_popup "Cannot find the git directory \"$gitdir\"."
105 exit 1
105 exit 1
106 }
106 }
107 set commits {}
107 set commits {}
108 set phase getcommits
108 set phase getcommits
109 set startmsecs [clock clicks -milliseconds]
109 set startmsecs [clock clicks -milliseconds]
110 set nextupdate [expr $startmsecs + 100]
110 set nextupdate [expr $startmsecs + 100]
111 set ncmupdate 1
111 set ncmupdate 1
112 set limit 0
112 set limit 0
113 set revargs {}
113 set revargs {}
114 for {set i 0} {$i < [llength $rargs]} {incr i} {
114 for {set i 0} {$i < [llength $rargs]} {incr i} {
115 set opt [lindex $rargs $i]
115 set opt [lindex $rargs $i]
116 if {$opt == "--limit"} {
116 if {$opt == "--limit"} {
117 incr i
117 incr i
118 set limit [lindex $rargs $i]
118 set limit [lindex $rargs $i]
119 } else {
119 } else {
120 lappend revargs $opt
120 lappend revargs $opt
121 }
121 }
122 }
122 }
123 if [catch {
123 if [catch {
124 set parse_args [concat --default HEAD $revargs]
124 set parse_args [concat --default HEAD $revargs]
125 set parse_temp [eval exec {$env(HG)} --config ui.report_untrusted=false debug-rev-parse $parse_args]
125 set parse_temp [eval exec {$env(HG)} --config ui.report_untrusted=false debug-rev-parse $parse_args]
126 regsub -all "\r\n" $parse_temp "\n" parse_temp
126 regsub -all "\r\n" $parse_temp "\n" parse_temp
127 set parsed_args [split $parse_temp "\n"]
127 set parsed_args [split $parse_temp "\n"]
128 } err] {
128 } err] {
129 # if git-rev-parse failed for some reason...
129 # if git-rev-parse failed for some reason...
130 if {$rargs == {}} {
130 if {$rargs == {}} {
131 set revargs HEAD
131 set revargs HEAD
132 }
132 }
133 set parsed_args $revargs
133 set parsed_args $revargs
134 }
134 }
135 if {$limit > 0} {
135 if {$limit > 0} {
136 set parsed_args [concat -n $limit $parsed_args]
136 set parsed_args [concat -n $limit $parsed_args]
137 }
137 }
138 if [catch {
138 if [catch {
139 set commfd [open "|{$env(HG)} --config ui.report_untrusted=false debug-rev-list --header --topo-order --parents $parsed_args" r]
139 set commfd [open "|{$env(HG)} --config ui.report_untrusted=false debug-rev-list --header --topo-order --parents $parsed_args" r]
140 } err] {
140 } err] {
141 puts stderr "Error executing hg debug-rev-list: $err"
141 puts stderr "Error executing hg debug-rev-list: $err"
142 exit 1
142 exit 1
143 }
143 }
144 set leftover {}
144 set leftover {}
145 fconfigure $commfd -blocking 0 -translation lf
145 fconfigure $commfd -blocking 0 -translation lf
146 fileevent $commfd readable [list getcommitlines $commfd]
146 fileevent $commfd readable [list getcommitlines $commfd]
147 $canv delete all
147 $canv delete all
148 $canv create text 3 3 -anchor nw -text "Reading commits..." \
148 $canv create text 3 3 -anchor nw -text "Reading commits..." \
149 -font $mainfont -tags textitems
149 -font $mainfont -tags textitems
150 . config -cursor watch
150 . config -cursor watch
151 settextcursor watch
151 settextcursor watch
152 }
152 }
153
153
154 proc getcommitlines {commfd} {
154 proc getcommitlines {commfd} {
155 global commits parents cdate children
155 global commits parents cdate children
156 global commitlisted phase commitinfo nextupdate
156 global commitlisted phase commitinfo nextupdate
157 global stopped redisplaying leftover
157 global stopped redisplaying leftover
158
158
159 set stuff [read $commfd]
159 set stuff [read $commfd]
160 if {$stuff == {}} {
160 if {$stuff == {}} {
161 if {![eof $commfd]} return
161 if {![eof $commfd]} return
162 # set it blocking so we wait for the process to terminate
162 # set it blocking so we wait for the process to terminate
163 fconfigure $commfd -blocking 1
163 fconfigure $commfd -blocking 1
164 if {![catch {close $commfd} err]} {
164 if {![catch {close $commfd} err]} {
165 after idle finishcommits
165 after idle finishcommits
166 return
166 return
167 }
167 }
168 if {[string range $err 0 4] == "usage"} {
168 if {[string range $err 0 4] == "usage"} {
169 set err \
169 set err \
170 {Gitk: error reading commits: bad arguments to git-rev-list.
170 {Gitk: error reading commits: bad arguments to git-rev-list.
171 (Note: arguments to gitk are passed to git-rev-list
171 (Note: arguments to gitk are passed to git-rev-list
172 to allow selection of commits to be displayed.)}
172 to allow selection of commits to be displayed.)}
173 } else {
173 } else {
174 set err "Error reading commits: $err"
174 set err "Error reading commits: $err"
175 }
175 }
176 error_popup $err
176 error_popup $err
177 exit 1
177 exit 1
178 }
178 }
179 set start 0
179 set start 0
180 while 1 {
180 while 1 {
181 set i [string first "\0" $stuff $start]
181 set i [string first "\0" $stuff $start]
182 if {$i < 0} {
182 if {$i < 0} {
183 append leftover [string range $stuff $start end]
183 append leftover [string range $stuff $start end]
184 return
184 return
185 }
185 }
186 set cmit [string range $stuff $start [expr {$i - 1}]]
186 set cmit [string range $stuff $start [expr {$i - 1}]]
187 if {$start == 0} {
187 if {$start == 0} {
188 set cmit "$leftover$cmit"
188 set cmit "$leftover$cmit"
189 set leftover {}
189 set leftover {}
190 }
190 }
191 set start [expr {$i + 1}]
191 set start [expr {$i + 1}]
192 regsub -all "\r\n" $cmit "\n" cmit
192 regsub -all "\r\n" $cmit "\n" cmit
193 set j [string first "\n" $cmit]
193 set j [string first "\n" $cmit]
194 set ok 0
194 set ok 0
195 if {$j >= 0} {
195 if {$j >= 0} {
196 set ids [string range $cmit 0 [expr {$j - 1}]]
196 set ids [string range $cmit 0 [expr {$j - 1}]]
197 set ok 1
197 set ok 1
198 foreach id $ids {
198 foreach id $ids {
199 if {![regexp {^[0-9a-f]{12}$} $id]} {
199 if {![regexp {^[0-9a-f]{12}$} $id]} {
200 set ok 0
200 set ok 0
201 break
201 break
202 }
202 }
203 }
203 }
204 }
204 }
205 if {!$ok} {
205 if {!$ok} {
206 set shortcmit $cmit
206 set shortcmit $cmit
207 if {[string length $shortcmit] > 80} {
207 if {[string length $shortcmit] > 80} {
208 set shortcmit "[string range $shortcmit 0 80]..."
208 set shortcmit "[string range $shortcmit 0 80]..."
209 }
209 }
210 error_popup "Can't parse hg debug-rev-list output: {$shortcmit}"
210 error_popup "Can't parse hg debug-rev-list output: {$shortcmit}"
211 exit 1
211 exit 1
212 }
212 }
213 set id [lindex $ids 0]
213 set id [lindex $ids 0]
214 set olds [lrange $ids 1 end]
214 set olds [lrange $ids 1 end]
215 set cmit [string range $cmit [expr {$j + 1}] end]
215 set cmit [string range $cmit [expr {$j + 1}] end]
216 lappend commits $id
216 lappend commits $id
217 set commitlisted($id) 1
217 set commitlisted($id) 1
218 parsecommit $id $cmit 1 [lrange $ids 1 end]
218 parsecommit $id $cmit 1 [lrange $ids 1 end]
219 drawcommit $id
219 drawcommit $id
220 if {[clock clicks -milliseconds] >= $nextupdate} {
220 if {[clock clicks -milliseconds] >= $nextupdate} {
221 doupdate 1
221 doupdate 1
222 }
222 }
223 while {$redisplaying} {
223 while {$redisplaying} {
224 set redisplaying 0
224 set redisplaying 0
225 if {$stopped == 1} {
225 if {$stopped == 1} {
226 set stopped 0
226 set stopped 0
227 set phase "getcommits"
227 set phase "getcommits"
228 foreach id $commits {
228 foreach id $commits {
229 drawcommit $id
229 drawcommit $id
230 if {$stopped} break
230 if {$stopped} break
231 if {[clock clicks -milliseconds] >= $nextupdate} {
231 if {[clock clicks -milliseconds] >= $nextupdate} {
232 doupdate 1
232 doupdate 1
233 }
233 }
234 }
234 }
235 }
235 }
236 }
236 }
237 }
237 }
238 }
238 }
239
239
240 proc doupdate {reading} {
240 proc doupdate {reading} {
241 global commfd nextupdate numcommits ncmupdate
241 global commfd nextupdate numcommits ncmupdate
242
242
243 if {$reading} {
243 if {$reading} {
244 fileevent $commfd readable {}
244 fileevent $commfd readable {}
245 }
245 }
246 update
246 update
247 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
247 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
248 if {$numcommits < 100} {
248 if {$numcommits < 100} {
249 set ncmupdate [expr {$numcommits + 1}]
249 set ncmupdate [expr {$numcommits + 1}]
250 } elseif {$numcommits < 10000} {
250 } elseif {$numcommits < 10000} {
251 set ncmupdate [expr {$numcommits + 10}]
251 set ncmupdate [expr {$numcommits + 10}]
252 } else {
252 } else {
253 set ncmupdate [expr {$numcommits + 100}]
253 set ncmupdate [expr {$numcommits + 100}]
254 }
254 }
255 if {$reading} {
255 if {$reading} {
256 fileevent $commfd readable [list getcommitlines $commfd]
256 fileevent $commfd readable [list getcommitlines $commfd]
257 }
257 }
258 }
258 }
259
259
260 proc readcommit {id} {
260 proc readcommit {id} {
261 global env
261 global env
262 if [catch {set contents [exec $env(HG) --config ui.report_untrusted=false debug-cat-file commit $id]}] return
262 if [catch {set contents [exec $env(HG) --config ui.report_untrusted=false debug-cat-file commit $id]}] return
263 parsecommit $id $contents 0 {}
263 parsecommit $id $contents 0 {}
264 }
264 }
265
265
266 proc parsecommit {id contents listed olds} {
266 proc parsecommit {id contents listed olds} {
267 global commitinfo children nchildren parents nparents cdate ncleft
267 global commitinfo children nchildren parents nparents cdate ncleft
268
268
269 set inhdr 1
269 set inhdr 1
270 set comment {}
270 set comment {}
271 set headline {}
271 set headline {}
272 set auname {}
272 set auname {}
273 set audate {}
273 set audate {}
274 set comname {}
274 set comname {}
275 set comdate {}
275 set comdate {}
276 set rev {}
276 set rev {}
277 if {![info exists nchildren($id)]} {
277 if {![info exists nchildren($id)]} {
278 set children($id) {}
278 set children($id) {}
279 set nchildren($id) 0
279 set nchildren($id) 0
280 set ncleft($id) 0
280 set ncleft($id) 0
281 }
281 }
282 set parents($id) $olds
282 set parents($id) $olds
283 set nparents($id) [llength $olds]
283 set nparents($id) [llength $olds]
284 foreach p $olds {
284 foreach p $olds {
285 if {![info exists nchildren($p)]} {
285 if {![info exists nchildren($p)]} {
286 set children($p) [list $id]
286 set children($p) [list $id]
287 set nchildren($p) 1
287 set nchildren($p) 1
288 set ncleft($p) 1
288 set ncleft($p) 1
289 } elseif {[lsearch -exact $children($p) $id] < 0} {
289 } elseif {[lsearch -exact $children($p) $id] < 0} {
290 lappend children($p) $id
290 lappend children($p) $id
291 incr nchildren($p)
291 incr nchildren($p)
292 incr ncleft($p)
292 incr ncleft($p)
293 }
293 }
294 }
294 }
295 regsub -all "\r\n" $contents "\n" contents
295 regsub -all "\r\n" $contents "\n" contents
296 foreach line [split $contents "\n"] {
296 foreach line [split $contents "\n"] {
297 if {$inhdr} {
297 if {$inhdr} {
298 set line [split $line]
298 set line [split $line]
299 if {$line == {}} {
299 if {$line == {}} {
300 set inhdr 0
300 set inhdr 0
301 } else {
301 } else {
302 set tag [lindex $line 0]
302 set tag [lindex $line 0]
303 if {$tag == "author"} {
303 if {$tag == "author"} {
304 set x [expr {[llength $line] - 2}]
304 set x [expr {[llength $line] - 2}]
305 set audate [lindex $line $x]
305 set audate [lindex $line $x]
306 set auname [join [lrange $line 1 [expr {$x - 1}]]]
306 set auname [join [lrange $line 1 [expr {$x - 1}]]]
307 } elseif {$tag == "committer"} {
307 } elseif {$tag == "committer"} {
308 set x [expr {[llength $line] - 2}]
308 set x [expr {[llength $line] - 2}]
309 set comdate [lindex $line $x]
309 set comdate [lindex $line $x]
310 set comname [join [lrange $line 1 [expr {$x - 1}]]]
310 set comname [join [lrange $line 1 [expr {$x - 1}]]]
311 } elseif {$tag == "revision"} {
311 } elseif {$tag == "revision"} {
312 set rev [lindex $line 1]
312 set rev [lindex $line 1]
313 }
313 }
314 }
314 }
315 } else {
315 } else {
316 if {$comment == {}} {
316 if {$comment == {}} {
317 set headline [string trim $line]
317 set headline [string trim $line]
318 } else {
318 } else {
319 append comment "\n"
319 append comment "\n"
320 }
320 }
321 if {!$listed} {
321 if {!$listed} {
322 # git-rev-list indents the comment by 4 spaces;
322 # git-rev-list indents the comment by 4 spaces;
323 # if we got this via git-cat-file, add the indentation
323 # if we got this via git-cat-file, add the indentation
324 append comment " "
324 append comment " "
325 }
325 }
326 append comment $line
326 append comment $line
327 }
327 }
328 }
328 }
329 if {$audate != {}} {
329 if {$audate != {}} {
330 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
330 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
331 }
331 }
332 if {$comdate != {}} {
332 if {$comdate != {}} {
333 set cdate($id) $comdate
333 set cdate($id) $comdate
334 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
334 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
335 }
335 }
336 set commitinfo($id) [list $headline $auname $audate \
336 set commitinfo($id) [list $headline $auname $audate \
337 $comname $comdate $comment $rev]
337 $comname $comdate $comment $rev]
338 }
338 }
339
339
340 proc readrefs {} {
340 proc readrefs {} {
341 global tagids idtags headids idheads tagcontents env
341 global tagids idtags headids idheads tagcontents env curid
342
343 set curid [exec $env(HG) --config ui.report_untrusted=false id]
344 regexp -- {[[:xdigit:]]+} $curid curid
342
345
343 set tags [exec $env(HG) --config ui.report_untrusted=false tags]
346 set tags [exec $env(HG) --config ui.report_untrusted=false tags]
344 regsub -all "\r\n" $tags "\n" tags
347 regsub -all "\r\n" $tags "\n" tags
345 set lines [split $tags "\n"]
348 set lines [split $tags "\n"]
346 foreach f $lines {
349 foreach f $lines {
347 regexp {(\S+)$} $f full
350 regexp {(\S+)$} $f full
348 regsub {\s+(\S+)$} $f "" direct
351 regsub {\s+(\S+)$} $f "" direct
349 set sha [split $full ':']
352 set sha [split $full ':']
350 set tag [lindex $sha 1]
353 set tag [lindex $sha 1]
351 lappend tagids($direct) $tag
354 lappend tagids($direct) $tag
352 lappend idtags($tag) $direct
355 lappend idtags($tag) $direct
353 }
356 }
354 }
357 }
355
358
356 proc readotherrefs {base dname excl} {
359 proc readotherrefs {base dname excl} {
357 global otherrefids idotherrefs
360 global otherrefids idotherrefs
358
361
359 set git [gitdir]
362 set git [gitdir]
360 set files [glob -nocomplain -types f [file join $git $base *]]
363 set files [glob -nocomplain -types f [file join $git $base *]]
361 foreach f $files {
364 foreach f $files {
362 catch {
365 catch {
363 set fd [open $f r]
366 set fd [open $f r]
364 set line [read $fd 40]
367 set line [read $fd 40]
365 if {[regexp {^[0-9a-f]{12}} $line id]} {
368 if {[regexp {^[0-9a-f]{12}} $line id]} {
366 set name "$dname[file tail $f]"
369 set name "$dname[file tail $f]"
367 set otherrefids($name) $id
370 set otherrefids($name) $id
368 lappend idotherrefs($id) $name
371 lappend idotherrefs($id) $name
369 }
372 }
370 close $fd
373 close $fd
371 }
374 }
372 }
375 }
373 set dirs [glob -nocomplain -types d [file join $git $base *]]
376 set dirs [glob -nocomplain -types d [file join $git $base *]]
374 foreach d $dirs {
377 foreach d $dirs {
375 set dir [file tail $d]
378 set dir [file tail $d]
376 if {[lsearch -exact $excl $dir] >= 0} continue
379 if {[lsearch -exact $excl $dir] >= 0} continue
377 readotherrefs [file join $base $dir] "$dname$dir/" {}
380 readotherrefs [file join $base $dir] "$dname$dir/" {}
378 }
381 }
379 }
382 }
380
383
381 proc allcansmousewheel {delta} {
384 proc allcansmousewheel {delta} {
382 set delta [expr -5*(int($delta)/abs($delta))]
385 set delta [expr -5*(int($delta)/abs($delta))]
383 allcanvs yview scroll $delta units
386 allcanvs yview scroll $delta units
384 }
387 }
385
388
386 proc error_popup msg {
389 proc error_popup msg {
387 set w .error
390 set w .error
388 toplevel $w
391 toplevel $w
389 wm transient $w .
392 wm transient $w .
390 message $w.m -text $msg -justify center -aspect 400
393 message $w.m -text $msg -justify center -aspect 400
391 pack $w.m -side top -fill x -padx 20 -pady 20
394 pack $w.m -side top -fill x -padx 20 -pady 20
392 button $w.ok -text OK -command "destroy $w"
395 button $w.ok -text OK -command "destroy $w"
393 pack $w.ok -side bottom -fill x
396 pack $w.ok -side bottom -fill x
394 bind $w <Visibility> "grab $w; focus $w"
397 bind $w <Visibility> "grab $w; focus $w"
395 tkwait window $w
398 tkwait window $w
396 }
399 }
397
400
398 proc makewindow {} {
401 proc makewindow {} {
399 global canv canv2 canv3 linespc charspc ctext cflist textfont
402 global canv canv2 canv3 linespc charspc ctext cflist textfont
400 global findtype findtypemenu findloc findstring fstring geometry
403 global findtype findtypemenu findloc findstring fstring geometry
401 global entries sha1entry sha1string sha1but
404 global entries sha1entry sha1string sha1but
402 global maincursor textcursor curtextcursor
405 global maincursor textcursor curtextcursor
403 global rowctxmenu gaudydiff mergemax
406 global rowctxmenu gaudydiff mergemax
404 global hgvdiff
407 global hgvdiff
405
408
406 menu .bar
409 menu .bar
407 .bar add cascade -label "File" -menu .bar.file
410 .bar add cascade -label "File" -menu .bar.file
408 menu .bar.file
411 menu .bar.file
409 .bar.file add command -label "Reread references" -command rereadrefs
412 .bar.file add command -label "Reread references" -command rereadrefs
410 .bar.file add command -label "Quit" -command doquit
413 .bar.file add command -label "Quit" -command doquit
411 menu .bar.help
414 menu .bar.help
412 .bar add cascade -label "Help" -menu .bar.help
415 .bar add cascade -label "Help" -menu .bar.help
413 .bar.help add command -label "About gitk" -command about
416 .bar.help add command -label "About gitk" -command about
414 . configure -menu .bar
417 . configure -menu .bar
415
418
416 if {![info exists geometry(canv1)]} {
419 if {![info exists geometry(canv1)]} {
417 set geometry(canv1) [expr 45 * $charspc]
420 set geometry(canv1) [expr 45 * $charspc]
418 set geometry(canv2) [expr 30 * $charspc]
421 set geometry(canv2) [expr 30 * $charspc]
419 set geometry(canv3) [expr 15 * $charspc]
422 set geometry(canv3) [expr 15 * $charspc]
420 set geometry(canvh) [expr 25 * $linespc + 4]
423 set geometry(canvh) [expr 25 * $linespc + 4]
421 set geometry(ctextw) 80
424 set geometry(ctextw) 80
422 set geometry(ctexth) 30
425 set geometry(ctexth) 30
423 set geometry(cflistw) 30
426 set geometry(cflistw) 30
424 }
427 }
425 panedwindow .ctop -orient vertical
428 panedwindow .ctop -orient vertical
426 if {[info exists geometry(width)]} {
429 if {[info exists geometry(width)]} {
427 .ctop conf -width $geometry(width) -height $geometry(height)
430 .ctop conf -width $geometry(width) -height $geometry(height)
428 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
431 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
429 set geometry(ctexth) [expr {($texth - 8) /
432 set geometry(ctexth) [expr {($texth - 8) /
430 [font metrics $textfont -linespace]}]
433 [font metrics $textfont -linespace]}]
431 }
434 }
432 frame .ctop.top
435 frame .ctop.top
433 frame .ctop.top.bar
436 frame .ctop.top.bar
434 pack .ctop.top.bar -side bottom -fill x
437 pack .ctop.top.bar -side bottom -fill x
435 set cscroll .ctop.top.csb
438 set cscroll .ctop.top.csb
436 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
439 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
437 pack $cscroll -side right -fill y
440 pack $cscroll -side right -fill y
438 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
441 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
439 pack .ctop.top.clist -side top -fill both -expand 1
442 pack .ctop.top.clist -side top -fill both -expand 1
440 .ctop add .ctop.top
443 .ctop add .ctop.top
441 set canv .ctop.top.clist.canv
444 set canv .ctop.top.clist.canv
442 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
445 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
443 -bg white -bd 0 \
446 -bg white -bd 0 \
444 -yscrollincr $linespc -yscrollcommand "$cscroll set" -selectbackground grey
447 -yscrollincr $linespc -yscrollcommand "$cscroll set" -selectbackground grey
445 .ctop.top.clist add $canv
448 .ctop.top.clist add $canv
446 set canv2 .ctop.top.clist.canv2
449 set canv2 .ctop.top.clist.canv2
447 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
450 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
448 -bg white -bd 0 -yscrollincr $linespc -selectbackground grey
451 -bg white -bd 0 -yscrollincr $linespc -selectbackground grey
449 .ctop.top.clist add $canv2
452 .ctop.top.clist add $canv2
450 set canv3 .ctop.top.clist.canv3
453 set canv3 .ctop.top.clist.canv3
451 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
454 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
452 -bg white -bd 0 -yscrollincr $linespc -selectbackground grey
455 -bg white -bd 0 -yscrollincr $linespc -selectbackground grey
453 .ctop.top.clist add $canv3
456 .ctop.top.clist add $canv3
454 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
457 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
455
458
456 set sha1entry .ctop.top.bar.sha1
459 set sha1entry .ctop.top.bar.sha1
457 set entries $sha1entry
460 set entries $sha1entry
458 set sha1but .ctop.top.bar.sha1label
461 set sha1but .ctop.top.bar.sha1label
459 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
462 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
460 -command gotocommit -width 8
463 -command gotocommit -width 8
461 $sha1but conf -disabledforeground [$sha1but cget -foreground]
464 $sha1but conf -disabledforeground [$sha1but cget -foreground]
462 pack .ctop.top.bar.sha1label -side left
465 pack .ctop.top.bar.sha1label -side left
463 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
466 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
464 trace add variable sha1string write sha1change
467 trace add variable sha1string write sha1change
465 pack $sha1entry -side left -pady 2
468 pack $sha1entry -side left -pady 2
466
469
467 image create bitmap bm-left -data {
470 image create bitmap bm-left -data {
468 #define left_width 16
471 #define left_width 16
469 #define left_height 16
472 #define left_height 16
470 static unsigned char left_bits[] = {
473 static unsigned char left_bits[] = {
471 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
474 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
472 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
475 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
473 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
476 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
474 }
477 }
475 image create bitmap bm-right -data {
478 image create bitmap bm-right -data {
476 #define right_width 16
479 #define right_width 16
477 #define right_height 16
480 #define right_height 16
478 static unsigned char right_bits[] = {
481 static unsigned char right_bits[] = {
479 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
482 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
480 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
483 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
481 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
484 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
482 }
485 }
483 button .ctop.top.bar.leftbut -image bm-left -command goback \
486 button .ctop.top.bar.leftbut -image bm-left -command goback \
484 -state disabled -width 26
487 -state disabled -width 26
485 pack .ctop.top.bar.leftbut -side left -fill y
488 pack .ctop.top.bar.leftbut -side left -fill y
486 button .ctop.top.bar.rightbut -image bm-right -command goforw \
489 button .ctop.top.bar.rightbut -image bm-right -command goforw \
487 -state disabled -width 26
490 -state disabled -width 26
488 pack .ctop.top.bar.rightbut -side left -fill y
491 pack .ctop.top.bar.rightbut -side left -fill y
489
492
490 button .ctop.top.bar.findbut -text "Find" -command dofind
493 button .ctop.top.bar.findbut -text "Find" -command dofind
491 pack .ctop.top.bar.findbut -side left
494 pack .ctop.top.bar.findbut -side left
492 set findstring {}
495 set findstring {}
493 set fstring .ctop.top.bar.findstring
496 set fstring .ctop.top.bar.findstring
494 lappend entries $fstring
497 lappend entries $fstring
495 entry $fstring -width 30 -font $textfont -textvariable findstring
498 entry $fstring -width 30 -font $textfont -textvariable findstring
496 pack $fstring -side left -expand 1 -fill x
499 pack $fstring -side left -expand 1 -fill x
497 set findtype Exact
500 set findtype Exact
498 set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \
501 set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \
499 findtype Exact IgnCase Regexp]
502 findtype Exact IgnCase Regexp]
500 set findloc "All fields"
503 set findloc "All fields"
501 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
504 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
502 Comments Author Committer Files Pickaxe
505 Comments Author Committer Files Pickaxe
503 pack .ctop.top.bar.findloc -side right
506 pack .ctop.top.bar.findloc -side right
504 pack .ctop.top.bar.findtype -side right
507 pack .ctop.top.bar.findtype -side right
505 # for making sure type==Exact whenever loc==Pickaxe
508 # for making sure type==Exact whenever loc==Pickaxe
506 trace add variable findloc write findlocchange
509 trace add variable findloc write findlocchange
507
510
508 panedwindow .ctop.cdet -orient horizontal
511 panedwindow .ctop.cdet -orient horizontal
509 .ctop add .ctop.cdet
512 .ctop add .ctop.cdet
510 frame .ctop.cdet.left
513 frame .ctop.cdet.left
511 set ctext .ctop.cdet.left.ctext
514 set ctext .ctop.cdet.left.ctext
512 text $ctext -bg white -state disabled -font $textfont \
515 text $ctext -bg white -state disabled -font $textfont \
513 -width $geometry(ctextw) -height $geometry(ctexth) \
516 -width $geometry(ctextw) -height $geometry(ctexth) \
514 -yscrollcommand ".ctop.cdet.left.sb set" \
517 -yscrollcommand ".ctop.cdet.left.sb set" \
515 -xscrollcommand ".ctop.cdet.left.hb set" -wrap none
518 -xscrollcommand ".ctop.cdet.left.hb set" -wrap none
516 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
519 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
517 scrollbar .ctop.cdet.left.hb -orient horizontal -command "$ctext xview"
520 scrollbar .ctop.cdet.left.hb -orient horizontal -command "$ctext xview"
518 pack .ctop.cdet.left.sb -side right -fill y
521 pack .ctop.cdet.left.sb -side right -fill y
519 pack .ctop.cdet.left.hb -side bottom -fill x
522 pack .ctop.cdet.left.hb -side bottom -fill x
520 pack $ctext -side left -fill both -expand 1
523 pack $ctext -side left -fill both -expand 1
521 .ctop.cdet add .ctop.cdet.left
524 .ctop.cdet add .ctop.cdet.left
522
525
523 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
526 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
524 if {$gaudydiff} {
527 if {$gaudydiff} {
525 $ctext tag conf hunksep -back blue -fore white
528 $ctext tag conf hunksep -back blue -fore white
526 $ctext tag conf d0 -back "#ff8080"
529 $ctext tag conf d0 -back "#ff8080"
527 $ctext tag conf d1 -back green
530 $ctext tag conf d1 -back green
528 } else {
531 } else {
529 $ctext tag conf hunksep -fore blue
532 $ctext tag conf hunksep -fore blue
530 $ctext tag conf d0 -fore red
533 $ctext tag conf d0 -fore red
531 $ctext tag conf d1 -fore "#00a000"
534 $ctext tag conf d1 -fore "#00a000"
532 $ctext tag conf m0 -fore red
535 $ctext tag conf m0 -fore red
533 $ctext tag conf m1 -fore blue
536 $ctext tag conf m1 -fore blue
534 $ctext tag conf m2 -fore green
537 $ctext tag conf m2 -fore green
535 $ctext tag conf m3 -fore purple
538 $ctext tag conf m3 -fore purple
536 $ctext tag conf m4 -fore brown
539 $ctext tag conf m4 -fore brown
537 $ctext tag conf mmax -fore darkgrey
540 $ctext tag conf mmax -fore darkgrey
538 set mergemax 5
541 set mergemax 5
539 $ctext tag conf mresult -font [concat $textfont bold]
542 $ctext tag conf mresult -font [concat $textfont bold]
540 $ctext tag conf msep -font [concat $textfont bold]
543 $ctext tag conf msep -font [concat $textfont bold]
541 $ctext tag conf found -back yellow
544 $ctext tag conf found -back yellow
542 }
545 }
543
546
544 frame .ctop.cdet.right
547 frame .ctop.cdet.right
545 set cflist .ctop.cdet.right.cfiles
548 set cflist .ctop.cdet.right.cfiles
546 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \
549 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \
547 -yscrollcommand ".ctop.cdet.right.sb set"
550 -yscrollcommand ".ctop.cdet.right.sb set"
548 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
551 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
549 pack .ctop.cdet.right.sb -side right -fill y
552 pack .ctop.cdet.right.sb -side right -fill y
550 pack $cflist -side left -fill both -expand 1
553 pack $cflist -side left -fill both -expand 1
551 .ctop.cdet add .ctop.cdet.right
554 .ctop.cdet add .ctop.cdet.right
552 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
555 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
553
556
554 pack .ctop -side top -fill both -expand 1
557 pack .ctop -side top -fill both -expand 1
555
558
556 bindall <1> {selcanvline %W %x %y}
559 bindall <1> {selcanvline %W %x %y}
557 #bindall <B1-Motion> {selcanvline %W %x %y}
560 #bindall <B1-Motion> {selcanvline %W %x %y}
558 bindall <MouseWheel> "allcansmousewheel %D"
561 bindall <MouseWheel> "allcansmousewheel %D"
559 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
562 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
560 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
563 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
561 bindall <2> "allcanvs scan mark 0 %y"
564 bindall <2> "allcanvs scan mark 0 %y"
562 bindall <B2-Motion> "allcanvs scan dragto 0 %y"
565 bindall <B2-Motion> "allcanvs scan dragto 0 %y"
563 bind . <Key-Up> "selnextline -1"
566 bind . <Key-Up> "selnextline -1"
564 bind . <Key-Down> "selnextline 1"
567 bind . <Key-Down> "selnextline 1"
565 bind . <Key-Prior> "allcanvs yview scroll -1 pages"
568 bind . <Key-Prior> "allcanvs yview scroll -1 pages"
566 bind . <Key-Next> "allcanvs yview scroll 1 pages"
569 bind . <Key-Next> "allcanvs yview scroll 1 pages"
567 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
570 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
568 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
571 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
569 bindkey <Key-space> "$ctext yview scroll 1 pages"
572 bindkey <Key-space> "$ctext yview scroll 1 pages"
570 bindkey p "selnextline -1"
573 bindkey p "selnextline -1"
571 bindkey n "selnextline 1"
574 bindkey n "selnextline 1"
572 bindkey b "$ctext yview scroll -1 pages"
575 bindkey b "$ctext yview scroll -1 pages"
573 bindkey d "$ctext yview scroll 18 units"
576 bindkey d "$ctext yview scroll 18 units"
574 bindkey u "$ctext yview scroll -18 units"
577 bindkey u "$ctext yview scroll -18 units"
575 bindkey / {findnext 1}
578 bindkey / {findnext 1}
576 bindkey <Key-Return> {findnext 0}
579 bindkey <Key-Return> {findnext 0}
577 bindkey ? findprev
580 bindkey ? findprev
578 bindkey f nextfile
581 bindkey f nextfile
579 bind . <Control-q> doquit
582 bind . <Control-q> doquit
580 bind . <Control-w> doquit
583 bind . <Control-w> doquit
581 bind . <Control-f> dofind
584 bind . <Control-f> dofind
582 bind . <Control-g> {findnext 0}
585 bind . <Control-g> {findnext 0}
583 bind . <Control-r> findprev
586 bind . <Control-r> findprev
584 bind . <Control-equal> {incrfont 1}
587 bind . <Control-equal> {incrfont 1}
585 bind . <Control-KP_Add> {incrfont 1}
588 bind . <Control-KP_Add> {incrfont 1}
586 bind . <Control-minus> {incrfont -1}
589 bind . <Control-minus> {incrfont -1}
587 bind . <Control-KP_Subtract> {incrfont -1}
590 bind . <Control-KP_Subtract> {incrfont -1}
588 bind $cflist <<ListboxSelect>> listboxsel
591 bind $cflist <<ListboxSelect>> listboxsel
589 bind . <Destroy> {savestuff %W}
592 bind . <Destroy> {savestuff %W}
590 bind . <Button-1> "click %W"
593 bind . <Button-1> "click %W"
591 bind $fstring <Key-Return> dofind
594 bind $fstring <Key-Return> dofind
592 bind $sha1entry <Key-Return> gotocommit
595 bind $sha1entry <Key-Return> gotocommit
593 bind $sha1entry <<PasteSelection>> clearsha1
596 bind $sha1entry <<PasteSelection>> clearsha1
594
597
595 set maincursor [. cget -cursor]
598 set maincursor [. cget -cursor]
596 set textcursor [$ctext cget -cursor]
599 set textcursor [$ctext cget -cursor]
597 set curtextcursor $textcursor
600 set curtextcursor $textcursor
598
601
599 set rowctxmenu .rowctxmenu
602 set rowctxmenu .rowctxmenu
600 menu $rowctxmenu -tearoff 0
603 menu $rowctxmenu -tearoff 0
601 $rowctxmenu add command -label "Diff this -> selected" \
604 $rowctxmenu add command -label "Diff this -> selected" \
602 -command {diffvssel 0}
605 -command {diffvssel 0}
603 $rowctxmenu add command -label "Diff selected -> this" \
606 $rowctxmenu add command -label "Diff selected -> this" \
604 -command {diffvssel 1}
607 -command {diffvssel 1}
605 $rowctxmenu add command -label "Make patch" -command mkpatch
608 $rowctxmenu add command -label "Make patch" -command mkpatch
606 $rowctxmenu add command -label "Create tag" -command mktag
609 $rowctxmenu add command -label "Create tag" -command mktag
607 $rowctxmenu add command -label "Write commit to file" -command writecommit
610 $rowctxmenu add command -label "Write commit to file" -command writecommit
608 if { $hgvdiff ne "" } {
611 if { $hgvdiff ne "" } {
609 $rowctxmenu add command -label "Visual diff with parent" \
612 $rowctxmenu add command -label "Visual diff with parent" \
610 -command {vdiff 1}
613 -command {vdiff 1}
611 $rowctxmenu add command -label "Visual diff with selected" \
614 $rowctxmenu add command -label "Visual diff with selected" \
612 -command {vdiff 0}
615 -command {vdiff 0}
613 }
616 }
614 }
617 }
615
618
616 # when we make a key binding for the toplevel, make sure
619 # when we make a key binding for the toplevel, make sure
617 # it doesn't get triggered when that key is pressed in the
620 # it doesn't get triggered when that key is pressed in the
618 # find string entry widget.
621 # find string entry widget.
619 proc bindkey {ev script} {
622 proc bindkey {ev script} {
620 global entries
623 global entries
621 bind . $ev $script
624 bind . $ev $script
622 set escript [bind Entry $ev]
625 set escript [bind Entry $ev]
623 if {$escript == {}} {
626 if {$escript == {}} {
624 set escript [bind Entry <Key>]
627 set escript [bind Entry <Key>]
625 }
628 }
626 foreach e $entries {
629 foreach e $entries {
627 bind $e $ev "$escript; break"
630 bind $e $ev "$escript; break"
628 }
631 }
629 }
632 }
630
633
631 # set the focus back to the toplevel for any click outside
634 # set the focus back to the toplevel for any click outside
632 # the entry widgets
635 # the entry widgets
633 proc click {w} {
636 proc click {w} {
634 global entries
637 global entries
635 foreach e $entries {
638 foreach e $entries {
636 if {$w == $e} return
639 if {$w == $e} return
637 }
640 }
638 focus .
641 focus .
639 }
642 }
640
643
641 proc savestuff {w} {
644 proc savestuff {w} {
642 global canv canv2 canv3 ctext cflist mainfont textfont
645 global canv canv2 canv3 ctext cflist mainfont textfont
643 global stuffsaved findmergefiles gaudydiff maxgraphpct
646 global stuffsaved findmergefiles gaudydiff maxgraphpct
644 global maxwidth
647 global maxwidth authorcolors curidfont
645
648
646 if {$stuffsaved} return
649 if {$stuffsaved} return
647 if {![winfo viewable .]} return
650 if {![winfo viewable .]} return
648 catch {
651 catch {
649 set f [open "~/.gitk-new" w]
652 set f [open "~/.gitk-new" w]
650 puts $f [list set mainfont $mainfont]
653 puts $f [list set mainfont $mainfont]
654 puts $f [list set curidfont $curidfont]
651 puts $f [list set textfont $textfont]
655 puts $f [list set textfont $textfont]
652 puts $f [list set findmergefiles $findmergefiles]
656 puts $f [list set findmergefiles $findmergefiles]
653 puts $f [list set gaudydiff $gaudydiff]
657 puts $f [list set gaudydiff $gaudydiff]
654 puts $f [list set maxgraphpct $maxgraphpct]
658 puts $f [list set maxgraphpct $maxgraphpct]
655 puts $f [list set maxwidth $maxwidth]
659 puts $f [list set maxwidth $maxwidth]
656 puts $f "set geometry(width) [winfo width .ctop]"
660 puts $f "set geometry(width) [winfo width .ctop]"
657 puts $f "set geometry(height) [winfo height .ctop]"
661 puts $f "set geometry(height) [winfo height .ctop]"
658 puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
662 puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
659 puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]"
663 puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]"
660 puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]"
664 puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]"
661 puts $f "set geometry(canvh) [expr [winfo height $canv]-2]"
665 puts $f "set geometry(canvh) [expr [winfo height $canv]-2]"
662 set wid [expr {([winfo width $ctext] - 8) \
666 set wid [expr {([winfo width $ctext] - 8) \
663 / [font measure $textfont "0"]}]
667 / [font measure $textfont "0"]}]
664 puts $f "set geometry(ctextw) $wid"
668 puts $f "set geometry(ctextw) $wid"
665 set wid [expr {([winfo width $cflist] - 11) \
669 set wid [expr {([winfo width $cflist] - 11) \
666 / [font measure [$cflist cget -font] "0"]}]
670 / [font measure [$cflist cget -font] "0"]}]
667 puts $f "set geometry(cflistw) $wid"
671 puts $f "set geometry(cflistw) $wid"
672 puts $f "#"
673 puts $f "# authorcolors format:"
674 puts $f "#"
675 puts $f "# zero or more sublists of"
676 puts $f "#"
677 puts $f "# { regex color }"
678 puts $f "#"
679 puts $f "# followed by a list of colors"
680 puts $f "#"
681 puts $f "# If the commit author matches a regex in a sublist,"
682 puts $f "# the commit will be colored by that color"
683 puts $f "# otherwise the next unused entry from the list of colors"
684 puts $f "# will be assigned to this commit and also all other commits"
685 puts $f "# of the same author. When the list of colors is exhausted,"
686 puts $f "# the last entry will be reused."
687 puts $f "#"
688 puts $f "set authorcolors {$authorcolors}"
668 close $f
689 close $f
669 file rename -force "~/.gitk-new" "~/.gitk"
690 file rename -force "~/.gitk-new" "~/.gitk"
670 }
691 }
671 set stuffsaved 1
692 set stuffsaved 1
672 }
693 }
673
694
674 proc resizeclistpanes {win w} {
695 proc resizeclistpanes {win w} {
675 global oldwidth
696 global oldwidth
676 if [info exists oldwidth($win)] {
697 if [info exists oldwidth($win)] {
677 set s0 [$win sash coord 0]
698 set s0 [$win sash coord 0]
678 set s1 [$win sash coord 1]
699 set s1 [$win sash coord 1]
679 if {$w < 60} {
700 if {$w < 60} {
680 set sash0 [expr {int($w/2 - 2)}]
701 set sash0 [expr {int($w/2 - 2)}]
681 set sash1 [expr {int($w*5/6 - 2)}]
702 set sash1 [expr {int($w*5/6 - 2)}]
682 } else {
703 } else {
683 set factor [expr {1.0 * $w / $oldwidth($win)}]
704 set factor [expr {1.0 * $w / $oldwidth($win)}]
684 set sash0 [expr {int($factor * [lindex $s0 0])}]
705 set sash0 [expr {int($factor * [lindex $s0 0])}]
685 set sash1 [expr {int($factor * [lindex $s1 0])}]
706 set sash1 [expr {int($factor * [lindex $s1 0])}]
686 if {$sash0 < 30} {
707 if {$sash0 < 30} {
687 set sash0 30
708 set sash0 30
688 }
709 }
689 if {$sash1 < $sash0 + 20} {
710 if {$sash1 < $sash0 + 20} {
690 set sash1 [expr $sash0 + 20]
711 set sash1 [expr $sash0 + 20]
691 }
712 }
692 if {$sash1 > $w - 10} {
713 if {$sash1 > $w - 10} {
693 set sash1 [expr $w - 10]
714 set sash1 [expr $w - 10]
694 if {$sash0 > $sash1 - 20} {
715 if {$sash0 > $sash1 - 20} {
695 set sash0 [expr $sash1 - 20]
716 set sash0 [expr $sash1 - 20]
696 }
717 }
697 }
718 }
698 }
719 }
699 $win sash place 0 $sash0 [lindex $s0 1]
720 $win sash place 0 $sash0 [lindex $s0 1]
700 $win sash place 1 $sash1 [lindex $s1 1]
721 $win sash place 1 $sash1 [lindex $s1 1]
701 }
722 }
702 set oldwidth($win) $w
723 set oldwidth($win) $w
703 }
724 }
704
725
705 proc resizecdetpanes {win w} {
726 proc resizecdetpanes {win w} {
706 global oldwidth
727 global oldwidth
707 if [info exists oldwidth($win)] {
728 if [info exists oldwidth($win)] {
708 set s0 [$win sash coord 0]
729 set s0 [$win sash coord 0]
709 if {$w < 60} {
730 if {$w < 60} {
710 set sash0 [expr {int($w*3/4 - 2)}]
731 set sash0 [expr {int($w*3/4 - 2)}]
711 } else {
732 } else {
712 set factor [expr {1.0 * $w / $oldwidth($win)}]
733 set factor [expr {1.0 * $w / $oldwidth($win)}]
713 set sash0 [expr {int($factor * [lindex $s0 0])}]
734 set sash0 [expr {int($factor * [lindex $s0 0])}]
714 if {$sash0 < 45} {
735 if {$sash0 < 45} {
715 set sash0 45
736 set sash0 45
716 }
737 }
717 if {$sash0 > $w - 15} {
738 if {$sash0 > $w - 15} {
718 set sash0 [expr $w - 15]
739 set sash0 [expr $w - 15]
719 }
740 }
720 }
741 }
721 $win sash place 0 $sash0 [lindex $s0 1]
742 $win sash place 0 $sash0 [lindex $s0 1]
722 }
743 }
723 set oldwidth($win) $w
744 set oldwidth($win) $w
724 }
745 }
725
746
726 proc allcanvs args {
747 proc allcanvs args {
727 global canv canv2 canv3
748 global canv canv2 canv3
728 eval $canv $args
749 eval $canv $args
729 eval $canv2 $args
750 eval $canv2 $args
730 eval $canv3 $args
751 eval $canv3 $args
731 }
752 }
732
753
733 proc bindall {event action} {
754 proc bindall {event action} {
734 global canv canv2 canv3
755 global canv canv2 canv3
735 bind $canv $event $action
756 bind $canv $event $action
736 bind $canv2 $event $action
757 bind $canv2 $event $action
737 bind $canv3 $event $action
758 bind $canv3 $event $action
738 }
759 }
739
760
740 proc about {} {
761 proc about {} {
741 set w .about
762 set w .about
742 if {[winfo exists $w]} {
763 if {[winfo exists $w]} {
743 raise $w
764 raise $w
744 return
765 return
745 }
766 }
746 toplevel $w
767 toplevel $w
747 wm title $w "About gitk"
768 wm title $w "About gitk"
748 message $w.m -text {
769 message $w.m -text {
749 Gitk version 1.2
770 Gitk version 1.2
750
771
751 Copyright οΏ½ 2005 Paul Mackerras
772 Copyright οΏ½ 2005 Paul Mackerras
752
773
753 Use and redistribute under the terms of the GNU General Public License} \
774 Use and redistribute under the terms of the GNU General Public License} \
754 -justify center -aspect 400
775 -justify center -aspect 400
755 pack $w.m -side top -fill x -padx 20 -pady 20
776 pack $w.m -side top -fill x -padx 20 -pady 20
756 button $w.ok -text Close -command "destroy $w"
777 button $w.ok -text Close -command "destroy $w"
757 pack $w.ok -side bottom
778 pack $w.ok -side bottom
758 }
779 }
759
780
781 set aunextcolor 0
782 proc assignauthorcolor {name} {
783 global authorcolors aucolormap aunextcolor
784 if [info exists aucolormap($name)] return
785
786 set randomcolors {black}
787 for {set i 0} {$i < [llength $authorcolors]} {incr i} {
788 set col [lindex $authorcolors $i]
789 if {[llength $col] > 1} {
790 set re [lindex $col 0]
791 set c [lindex $col 1]
792 if {[regexp -- $re $name]} {
793 set aucolormap($name) $c
794 return
795 }
796 } else {
797 set randomcolors [lrange $authorcolors $i end]
798 break
799 }
800 }
801
802 set ncolors [llength $randomcolors]
803 set c [lindex $randomcolors $aunextcolor]
804 if {[incr aunextcolor] >= $ncolors} {
805 incr aunextcolor -1
806 }
807 set aucolormap($name) $c
808 }
809
760 proc assigncolor {id} {
810 proc assigncolor {id} {
761 global commitinfo colormap commcolors colors nextcolor
811 global commitinfo colormap commcolors colors nextcolor
762 global parents nparents children nchildren
812 global parents nparents children nchildren
763 global cornercrossings crossings
813 global cornercrossings crossings
764
814
765 if [info exists colormap($id)] return
815 if [info exists colormap($id)] return
766 set ncolors [llength $colors]
816 set ncolors [llength $colors]
767 if {$nparents($id) <= 1 && $nchildren($id) == 1} {
817 if {$nparents($id) <= 1 && $nchildren($id) == 1} {
768 set child [lindex $children($id) 0]
818 set child [lindex $children($id) 0]
769 if {[info exists colormap($child)]
819 if {[info exists colormap($child)]
770 && $nparents($child) == 1} {
820 && $nparents($child) == 1} {
771 set colormap($id) $colormap($child)
821 set colormap($id) $colormap($child)
772 return
822 return
773 }
823 }
774 }
824 }
775 set badcolors {}
825 set badcolors {}
776 if {[info exists cornercrossings($id)]} {
826 if {[info exists cornercrossings($id)]} {
777 foreach x $cornercrossings($id) {
827 foreach x $cornercrossings($id) {
778 if {[info exists colormap($x)]
828 if {[info exists colormap($x)]
779 && [lsearch -exact $badcolors $colormap($x)] < 0} {
829 && [lsearch -exact $badcolors $colormap($x)] < 0} {
780 lappend badcolors $colormap($x)
830 lappend badcolors $colormap($x)
781 }
831 }
782 }
832 }
783 if {[llength $badcolors] >= $ncolors} {
833 if {[llength $badcolors] >= $ncolors} {
784 set badcolors {}
834 set badcolors {}
785 }
835 }
786 }
836 }
787 set origbad $badcolors
837 set origbad $badcolors
788 if {[llength $badcolors] < $ncolors - 1} {
838 if {[llength $badcolors] < $ncolors - 1} {
789 if {[info exists crossings($id)]} {
839 if {[info exists crossings($id)]} {
790 foreach x $crossings($id) {
840 foreach x $crossings($id) {
791 if {[info exists colormap($x)]
841 if {[info exists colormap($x)]
792 && [lsearch -exact $badcolors $colormap($x)] < 0} {
842 && [lsearch -exact $badcolors $colormap($x)] < 0} {
793 lappend badcolors $colormap($x)
843 lappend badcolors $colormap($x)
794 }
844 }
795 }
845 }
796 if {[llength $badcolors] >= $ncolors} {
846 if {[llength $badcolors] >= $ncolors} {
797 set badcolors $origbad
847 set badcolors $origbad
798 }
848 }
799 }
849 }
800 set origbad $badcolors
850 set origbad $badcolors
801 }
851 }
802 if {[llength $badcolors] < $ncolors - 1} {
852 if {[llength $badcolors] < $ncolors - 1} {
803 foreach child $children($id) {
853 foreach child $children($id) {
804 if {[info exists colormap($child)]
854 if {[info exists colormap($child)]
805 && [lsearch -exact $badcolors $colormap($child)] < 0} {
855 && [lsearch -exact $badcolors $colormap($child)] < 0} {
806 lappend badcolors $colormap($child)
856 lappend badcolors $colormap($child)
807 }
857 }
808 if {[info exists parents($child)]} {
858 if {[info exists parents($child)]} {
809 foreach p $parents($child) {
859 foreach p $parents($child) {
810 if {[info exists colormap($p)]
860 if {[info exists colormap($p)]
811 && [lsearch -exact $badcolors $colormap($p)] < 0} {
861 && [lsearch -exact $badcolors $colormap($p)] < 0} {
812 lappend badcolors $colormap($p)
862 lappend badcolors $colormap($p)
813 }
863 }
814 }
864 }
815 }
865 }
816 }
866 }
817 if {[llength $badcolors] >= $ncolors} {
867 if {[llength $badcolors] >= $ncolors} {
818 set badcolors $origbad
868 set badcolors $origbad
819 }
869 }
820 }
870 }
821 for {set i 0} {$i <= $ncolors} {incr i} {
871 for {set i 0} {$i <= $ncolors} {incr i} {
822 set c [lindex $colors $nextcolor]
872 set c [lindex $colors $nextcolor]
823 if {[incr nextcolor] >= $ncolors} {
873 if {[incr nextcolor] >= $ncolors} {
824 set nextcolor 0
874 set nextcolor 0
825 }
875 }
826 if {[lsearch -exact $badcolors $c]} break
876 if {[lsearch -exact $badcolors $c]} break
827 }
877 }
828 set colormap($id) $c
878 set colormap($id) $c
829 }
879 }
830
880
831 proc initgraph {} {
881 proc initgraph {} {
832 global canvy canvy0 lineno numcommits nextcolor linespc
882 global canvy canvy0 lineno numcommits nextcolor linespc
833 global mainline mainlinearrow sidelines
883 global mainline mainlinearrow sidelines
834 global nchildren ncleft
884 global nchildren ncleft
835 global displist nhyperspace
885 global displist nhyperspace
836
886
837 allcanvs delete all
887 allcanvs delete all
838 set nextcolor 0
888 set nextcolor 0
839 set canvy $canvy0
889 set canvy $canvy0
840 set lineno -1
890 set lineno -1
841 set numcommits 0
891 set numcommits 0
842 catch {unset mainline}
892 catch {unset mainline}
843 catch {unset mainlinearrow}
893 catch {unset mainlinearrow}
844 catch {unset sidelines}
894 catch {unset sidelines}
845 foreach id [array names nchildren] {
895 foreach id [array names nchildren] {
846 set ncleft($id) $nchildren($id)
896 set ncleft($id) $nchildren($id)
847 }
897 }
848 set displist {}
898 set displist {}
849 set nhyperspace 0
899 set nhyperspace 0
850 }
900 }
851
901
852 proc bindline {t id} {
902 proc bindline {t id} {
853 global canv
903 global canv
854
904
855 $canv bind $t <Enter> "lineenter %x %y $id"
905 $canv bind $t <Enter> "lineenter %x %y $id"
856 $canv bind $t <Motion> "linemotion %x %y $id"
906 $canv bind $t <Motion> "linemotion %x %y $id"
857 $canv bind $t <Leave> "lineleave $id"
907 $canv bind $t <Leave> "lineleave $id"
858 $canv bind $t <Button-1> "lineclick %x %y $id 1"
908 $canv bind $t <Button-1> "lineclick %x %y $id 1"
859 }
909 }
860
910
861 proc drawlines {id xtra} {
911 proc drawlines {id xtra} {
862 global mainline mainlinearrow sidelines lthickness colormap canv
912 global mainline mainlinearrow sidelines lthickness colormap canv
863
913
864 $canv delete lines.$id
914 $canv delete lines.$id
865 if {[info exists mainline($id)]} {
915 if {[info exists mainline($id)]} {
866 set t [$canv create line $mainline($id) \
916 set t [$canv create line $mainline($id) \
867 -width [expr {($xtra + 1) * $lthickness}] \
917 -width [expr {($xtra + 1) * $lthickness}] \
868 -fill $colormap($id) -tags lines.$id \
918 -fill $colormap($id) -tags lines.$id \
869 -arrow $mainlinearrow($id)]
919 -arrow $mainlinearrow($id)]
870 $canv lower $t
920 $canv lower $t
871 bindline $t $id
921 bindline $t $id
872 }
922 }
873 if {[info exists sidelines($id)]} {
923 if {[info exists sidelines($id)]} {
874 foreach ls $sidelines($id) {
924 foreach ls $sidelines($id) {
875 set coords [lindex $ls 0]
925 set coords [lindex $ls 0]
876 set thick [lindex $ls 1]
926 set thick [lindex $ls 1]
877 set arrow [lindex $ls 2]
927 set arrow [lindex $ls 2]
878 set t [$canv create line $coords -fill $colormap($id) \
928 set t [$canv create line $coords -fill $colormap($id) \
879 -width [expr {($thick + $xtra) * $lthickness}] \
929 -width [expr {($thick + $xtra) * $lthickness}] \
880 -arrow $arrow -tags lines.$id]
930 -arrow $arrow -tags lines.$id]
881 $canv lower $t
931 $canv lower $t
882 bindline $t $id
932 bindline $t $id
883 }
933 }
884 }
934 }
885 }
935 }
886
936
887 # level here is an index in displist
937 # level here is an index in displist
888 proc drawcommitline {level} {
938 proc drawcommitline {level} {
889 global parents children nparents displist
939 global parents children nparents displist
890 global canv canv2 canv3 mainfont namefont canvy linespc
940 global canv canv2 canv3 mainfont namefont canvy linespc
891 global lineid linehtag linentag linedtag commitinfo
941 global lineid linehtag linentag linedtag commitinfo
892 global colormap numcommits currentparents dupparents
942 global colormap numcommits currentparents dupparents
893 global idtags idline idheads idotherrefs
943 global idtags idline idheads idotherrefs
894 global lineno lthickness mainline mainlinearrow sidelines
944 global lineno lthickness mainline mainlinearrow sidelines
895 global commitlisted rowtextx idpos lastuse displist
945 global commitlisted rowtextx idpos lastuse displist
896 global oldnlines olddlevel olddisplist
946 global oldnlines olddlevel olddisplist
947 global aucolormap curid curidfont
897
948
898 incr numcommits
949 incr numcommits
899 incr lineno
950 incr lineno
900 set id [lindex $displist $level]
951 set id [lindex $displist $level]
901 set lastuse($id) $lineno
952 set lastuse($id) $lineno
902 set lineid($lineno) $id
953 set lineid($lineno) $id
903 set idline($id) $lineno
954 set idline($id) $lineno
904 set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
955 set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
905 if {![info exists commitinfo($id)]} {
956 if {![info exists commitinfo($id)]} {
906 readcommit $id
957 readcommit $id
907 if {![info exists commitinfo($id)]} {
958 if {![info exists commitinfo($id)]} {
908 set commitinfo($id) {"No commit information available"}
959 set commitinfo($id) {"No commit information available"}
909 set nparents($id) 0
960 set nparents($id) 0
910 }
961 }
911 }
962 }
912 assigncolor $id
963 assigncolor $id
913 set currentparents {}
964 set currentparents {}
914 set dupparents {}
965 set dupparents {}
915 if {[info exists commitlisted($id)] && [info exists parents($id)]} {
966 if {[info exists commitlisted($id)] && [info exists parents($id)]} {
916 foreach p $parents($id) {
967 foreach p $parents($id) {
917 if {[lsearch -exact $currentparents $p] < 0} {
968 if {[lsearch -exact $currentparents $p] < 0} {
918 lappend currentparents $p
969 lappend currentparents $p
919 } else {
970 } else {
920 # remember that this parent was listed twice
971 # remember that this parent was listed twice
921 lappend dupparents $p
972 lappend dupparents $p
922 }
973 }
923 }
974 }
924 }
975 }
925 set x [xcoord $level $level $lineno]
976 set x [xcoord $level $level $lineno]
926 set y1 $canvy
977 set y1 $canvy
927 set canvy [expr $canvy + $linespc]
978 set canvy [expr $canvy + $linespc]
928 allcanvs conf -scrollregion \
979 allcanvs conf -scrollregion \
929 [list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
980 [list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
930 if {[info exists mainline($id)]} {
981 if {[info exists mainline($id)]} {
931 lappend mainline($id) $x $y1
982 lappend mainline($id) $x $y1
932 if {$mainlinearrow($id) ne "none"} {
983 if {$mainlinearrow($id) ne "none"} {
933 set mainline($id) [trimdiagstart $mainline($id)]
984 set mainline($id) [trimdiagstart $mainline($id)]
934 }
985 }
935 }
986 }
936 drawlines $id 0
987 drawlines $id 0
937 set orad [expr {$linespc / 3}]
988 set orad [expr {$linespc / 3}]
938 set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
989 set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
939 [expr $x + $orad - 1] [expr $y1 + $orad - 1] \
990 [expr $x + $orad - 1] [expr $y1 + $orad - 1] \
940 -fill $ofill -outline black -width 1]
991 -fill $ofill -outline black -width 1]
941 $canv raise $t
992 $canv raise $t
942 $canv bind $t <1> {selcanvline {} %x %y}
993 $canv bind $t <1> {selcanvline {} %x %y}
943 set xt [xcoord [llength $displist] $level $lineno]
994 set xt [xcoord [llength $displist] $level $lineno]
944 if {[llength $currentparents] > 2} {
995 if {[llength $currentparents] > 2} {
945 set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
996 set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
946 }
997 }
947 set rowtextx($lineno) $xt
998 set rowtextx($lineno) $xt
948 set idpos($id) [list $x $xt $y1]
999 set idpos($id) [list $x $xt $y1]
949 if {[info exists idtags($id)] || [info exists idheads($id)]
1000 if {[info exists idtags($id)] || [info exists idheads($id)]
950 || [info exists idotherrefs($id)]} {
1001 || [info exists idotherrefs($id)]} {
951 set xt [drawtags $id $x $xt $y1]
1002 set xt [drawtags $id $x $xt $y1]
952 }
1003 }
953 set headline [lindex $commitinfo($id) 0]
1004 set headline [lindex $commitinfo($id) 0]
954 set name [lindex $commitinfo($id) 1]
1005 set name [lindex $commitinfo($id) 1]
1006 assignauthorcolor $name
1007 set fg $aucolormap($name)
1008 if {$id == $curid} {
1009 set fn $curidfont
1010 } else {
1011 set fn $mainfont
1012 }
1013
955 set date [lindex $commitinfo($id) 2]
1014 set date [lindex $commitinfo($id) 2]
956 set linehtag($lineno) [$canv create text $xt $y1 -anchor w \
1015 set linehtag($lineno) [$canv create text $xt $y1 -anchor w \
957 -text $headline -font $mainfont ]
1016 -text $headline -font $fn \
1017 -fill $fg]
958 $canv bind $linehtag($lineno) <<B3>> "rowmenu %X %Y $id"
1018 $canv bind $linehtag($lineno) <<B3>> "rowmenu %X %Y $id"
959 set linentag($lineno) [$canv2 create text 3 $y1 -anchor w \
1019 set linentag($lineno) [$canv2 create text 3 $y1 -anchor w \
960 -text $name -font $namefont]
1020 -text $name -font $namefont \
1021 -fill $fg]
961 set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
1022 set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
962 -text $date -font $mainfont]
1023 -text $date -font $mainfont \
1024 -fill $fg]
963
1025
964 set olddlevel $level
1026 set olddlevel $level
965 set olddisplist $displist
1027 set olddisplist $displist
966 set oldnlines [llength $displist]
1028 set oldnlines [llength $displist]
967 }
1029 }
968
1030
969 proc drawtags {id x xt y1} {
1031 proc drawtags {id x xt y1} {
970 global idtags idheads idotherrefs
1032 global idtags idheads idotherrefs
971 global linespc lthickness
1033 global linespc lthickness
972 global canv mainfont idline rowtextx
1034 global canv mainfont idline rowtextx
973
1035
974 set marks {}
1036 set marks {}
975 set ntags 0
1037 set ntags 0
976 set nheads 0
1038 set nheads 0
977 if {[info exists idtags($id)]} {
1039 if {[info exists idtags($id)]} {
978 set marks $idtags($id)
1040 set marks $idtags($id)
979 set ntags [llength $marks]
1041 set ntags [llength $marks]
980 }
1042 }
981 if {[info exists idheads($id)]} {
1043 if {[info exists idheads($id)]} {
982 set marks [concat $marks $idheads($id)]
1044 set marks [concat $marks $idheads($id)]
983 set nheads [llength $idheads($id)]
1045 set nheads [llength $idheads($id)]
984 }
1046 }
985 if {[info exists idotherrefs($id)]} {
1047 if {[info exists idotherrefs($id)]} {
986 set marks [concat $marks $idotherrefs($id)]
1048 set marks [concat $marks $idotherrefs($id)]
987 }
1049 }
988 if {$marks eq {}} {
1050 if {$marks eq {}} {
989 return $xt
1051 return $xt
990 }
1052 }
991
1053
992 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
1054 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
993 set yt [expr $y1 - 0.5 * $linespc]
1055 set yt [expr $y1 - 0.5 * $linespc]
994 set yb [expr $yt + $linespc - 1]
1056 set yb [expr $yt + $linespc - 1]
995 set xvals {}
1057 set xvals {}
996 set wvals {}
1058 set wvals {}
997 foreach tag $marks {
1059 foreach tag $marks {
998 set wid [font measure $mainfont $tag]
1060 set wid [font measure $mainfont $tag]
999 lappend xvals $xt
1061 lappend xvals $xt
1000 lappend wvals $wid
1062 lappend wvals $wid
1001 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
1063 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
1002 }
1064 }
1003 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
1065 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
1004 -width $lthickness -fill black -tags tag.$id]
1066 -width $lthickness -fill black -tags tag.$id]
1005 $canv lower $t
1067 $canv lower $t
1006 foreach tag $marks x $xvals wid $wvals {
1068 foreach tag $marks x $xvals wid $wvals {
1007 set xl [expr $x + $delta]
1069 set xl [expr $x + $delta]
1008 set xr [expr $x + $delta + $wid + $lthickness]
1070 set xr [expr $x + $delta + $wid + $lthickness]
1009 if {[incr ntags -1] >= 0} {
1071 if {[incr ntags -1] >= 0} {
1010 # draw a tag
1072 # draw a tag
1011 set t [$canv create polygon $x [expr $yt + $delta] $xl $yt \
1073 set t [$canv create polygon $x [expr $yt + $delta] $xl $yt \
1012 $xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \
1074 $xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \
1013 -width 1 -outline black -fill yellow -tags tag.$id]
1075 -width 1 -outline black -fill yellow -tags tag.$id]
1014 $canv bind $t <1> [list showtag $tag 1]
1076 $canv bind $t <1> [list showtag $tag 1]
1015 set rowtextx($idline($id)) [expr {$xr + $linespc}]
1077 set rowtextx($idline($id)) [expr {$xr + $linespc}]
1016 } else {
1078 } else {
1017 # draw a head or other ref
1079 # draw a head or other ref
1018 if {[incr nheads -1] >= 0} {
1080 if {[incr nheads -1] >= 0} {
1019 set col green
1081 set col green
1020 } else {
1082 } else {
1021 set col "#ddddff"
1083 set col "#ddddff"
1022 }
1084 }
1023 set xl [expr $xl - $delta/2]
1085 set xl [expr $xl - $delta/2]
1024 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
1086 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
1025 -width 1 -outline black -fill $col -tags tag.$id
1087 -width 1 -outline black -fill $col -tags tag.$id
1026 }
1088 }
1027 set t [$canv create text $xl $y1 -anchor w -text $tag \
1089 set t [$canv create text $xl $y1 -anchor w -text $tag \
1028 -font $mainfont -tags tag.$id]
1090 -font $mainfont -tags tag.$id]
1029 if {$ntags >= 0} {
1091 if {$ntags >= 0} {
1030 $canv bind $t <1> [list showtag $tag 1]
1092 $canv bind $t <1> [list showtag $tag 1]
1031 }
1093 }
1032 }
1094 }
1033 return $xt
1095 return $xt
1034 }
1096 }
1035
1097
1036 proc notecrossings {id lo hi corner} {
1098 proc notecrossings {id lo hi corner} {
1037 global olddisplist crossings cornercrossings
1099 global olddisplist crossings cornercrossings
1038
1100
1039 for {set i $lo} {[incr i] < $hi} {} {
1101 for {set i $lo} {[incr i] < $hi} {} {
1040 set p [lindex $olddisplist $i]
1102 set p [lindex $olddisplist $i]
1041 if {$p == {}} continue
1103 if {$p == {}} continue
1042 if {$i == $corner} {
1104 if {$i == $corner} {
1043 if {![info exists cornercrossings($id)]
1105 if {![info exists cornercrossings($id)]
1044 || [lsearch -exact $cornercrossings($id) $p] < 0} {
1106 || [lsearch -exact $cornercrossings($id) $p] < 0} {
1045 lappend cornercrossings($id) $p
1107 lappend cornercrossings($id) $p
1046 }
1108 }
1047 if {![info exists cornercrossings($p)]
1109 if {![info exists cornercrossings($p)]
1048 || [lsearch -exact $cornercrossings($p) $id] < 0} {
1110 || [lsearch -exact $cornercrossings($p) $id] < 0} {
1049 lappend cornercrossings($p) $id
1111 lappend cornercrossings($p) $id
1050 }
1112 }
1051 } else {
1113 } else {
1052 if {![info exists crossings($id)]
1114 if {![info exists crossings($id)]
1053 || [lsearch -exact $crossings($id) $p] < 0} {
1115 || [lsearch -exact $crossings($id) $p] < 0} {
1054 lappend crossings($id) $p
1116 lappend crossings($id) $p
1055 }
1117 }
1056 if {![info exists crossings($p)]
1118 if {![info exists crossings($p)]
1057 || [lsearch -exact $crossings($p) $id] < 0} {
1119 || [lsearch -exact $crossings($p) $id] < 0} {
1058 lappend crossings($p) $id
1120 lappend crossings($p) $id
1059 }
1121 }
1060 }
1122 }
1061 }
1123 }
1062 }
1124 }
1063
1125
1064 proc xcoord {i level ln} {
1126 proc xcoord {i level ln} {
1065 global canvx0 xspc1 xspc2
1127 global canvx0 xspc1 xspc2
1066
1128
1067 set x [expr {$canvx0 + $i * $xspc1($ln)}]
1129 set x [expr {$canvx0 + $i * $xspc1($ln)}]
1068 if {$i > 0 && $i == $level} {
1130 if {$i > 0 && $i == $level} {
1069 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
1131 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
1070 } elseif {$i > $level} {
1132 } elseif {$i > $level} {
1071 set x [expr {$x + $xspc2 - $xspc1($ln)}]
1133 set x [expr {$x + $xspc2 - $xspc1($ln)}]
1072 }
1134 }
1073 return $x
1135 return $x
1074 }
1136 }
1075
1137
1076 # it seems Tk can't draw arrows on the end of diagonal line segments...
1138 # it seems Tk can't draw arrows on the end of diagonal line segments...
1077 proc trimdiagend {line} {
1139 proc trimdiagend {line} {
1078 while {[llength $line] > 4} {
1140 while {[llength $line] > 4} {
1079 set x1 [lindex $line end-3]
1141 set x1 [lindex $line end-3]
1080 set y1 [lindex $line end-2]
1142 set y1 [lindex $line end-2]
1081 set x2 [lindex $line end-1]
1143 set x2 [lindex $line end-1]
1082 set y2 [lindex $line end]
1144 set y2 [lindex $line end]
1083 if {($x1 == $x2) != ($y1 == $y2)} break
1145 if {($x1 == $x2) != ($y1 == $y2)} break
1084 set line [lreplace $line end-1 end]
1146 set line [lreplace $line end-1 end]
1085 }
1147 }
1086 return $line
1148 return $line
1087 }
1149 }
1088
1150
1089 proc trimdiagstart {line} {
1151 proc trimdiagstart {line} {
1090 while {[llength $line] > 4} {
1152 while {[llength $line] > 4} {
1091 set x1 [lindex $line 0]
1153 set x1 [lindex $line 0]
1092 set y1 [lindex $line 1]
1154 set y1 [lindex $line 1]
1093 set x2 [lindex $line 2]
1155 set x2 [lindex $line 2]
1094 set y2 [lindex $line 3]
1156 set y2 [lindex $line 3]
1095 if {($x1 == $x2) != ($y1 == $y2)} break
1157 if {($x1 == $x2) != ($y1 == $y2)} break
1096 set line [lreplace $line 0 1]
1158 set line [lreplace $line 0 1]
1097 }
1159 }
1098 return $line
1160 return $line
1099 }
1161 }
1100
1162
1101 proc drawslants {id needonscreen nohs} {
1163 proc drawslants {id needonscreen nohs} {
1102 global canv mainline mainlinearrow sidelines
1164 global canv mainline mainlinearrow sidelines
1103 global canvx0 canvy xspc1 xspc2 lthickness
1165 global canvx0 canvy xspc1 xspc2 lthickness
1104 global currentparents dupparents
1166 global currentparents dupparents
1105 global lthickness linespc canvy colormap lineno geometry
1167 global lthickness linespc canvy colormap lineno geometry
1106 global maxgraphpct maxwidth
1168 global maxgraphpct maxwidth
1107 global displist onscreen lastuse
1169 global displist onscreen lastuse
1108 global parents commitlisted
1170 global parents commitlisted
1109 global oldnlines olddlevel olddisplist
1171 global oldnlines olddlevel olddisplist
1110 global nhyperspace numcommits nnewparents
1172 global nhyperspace numcommits nnewparents
1111
1173
1112 if {$lineno < 0} {
1174 if {$lineno < 0} {
1113 lappend displist $id
1175 lappend displist $id
1114 set onscreen($id) 1
1176 set onscreen($id) 1
1115 return 0
1177 return 0
1116 }
1178 }
1117
1179
1118 set y1 [expr {$canvy - $linespc}]
1180 set y1 [expr {$canvy - $linespc}]
1119 set y2 $canvy
1181 set y2 $canvy
1120
1182
1121 # work out what we need to get back on screen
1183 # work out what we need to get back on screen
1122 set reins {}
1184 set reins {}
1123 if {$onscreen($id) < 0} {
1185 if {$onscreen($id) < 0} {
1124 # next to do isn't displayed, better get it on screen...
1186 # next to do isn't displayed, better get it on screen...
1125 lappend reins [list $id 0]
1187 lappend reins [list $id 0]
1126 }
1188 }
1127 # make sure all the previous commits's parents are on the screen
1189 # make sure all the previous commits's parents are on the screen
1128 foreach p $currentparents {
1190 foreach p $currentparents {
1129 if {$onscreen($p) < 0} {
1191 if {$onscreen($p) < 0} {
1130 lappend reins [list $p 0]
1192 lappend reins [list $p 0]
1131 }
1193 }
1132 }
1194 }
1133 # bring back anything requested by caller
1195 # bring back anything requested by caller
1134 if {$needonscreen ne {}} {
1196 if {$needonscreen ne {}} {
1135 lappend reins $needonscreen
1197 lappend reins $needonscreen
1136 }
1198 }
1137
1199
1138 # try the shortcut
1200 # try the shortcut
1139 if {$currentparents == $id && $onscreen($id) == 0 && $reins eq {}} {
1201 if {$currentparents == $id && $onscreen($id) == 0 && $reins eq {}} {
1140 set dlevel $olddlevel
1202 set dlevel $olddlevel
1141 set x [xcoord $dlevel $dlevel $lineno]
1203 set x [xcoord $dlevel $dlevel $lineno]
1142 set mainline($id) [list $x $y1]
1204 set mainline($id) [list $x $y1]
1143 set mainlinearrow($id) none
1205 set mainlinearrow($id) none
1144 set lastuse($id) $lineno
1206 set lastuse($id) $lineno
1145 set displist [lreplace $displist $dlevel $dlevel $id]
1207 set displist [lreplace $displist $dlevel $dlevel $id]
1146 set onscreen($id) 1
1208 set onscreen($id) 1
1147 set xspc1([expr {$lineno + 1}]) $xspc1($lineno)
1209 set xspc1([expr {$lineno + 1}]) $xspc1($lineno)
1148 return $dlevel
1210 return $dlevel
1149 }
1211 }
1150
1212
1151 # update displist
1213 # update displist
1152 set displist [lreplace $displist $olddlevel $olddlevel]
1214 set displist [lreplace $displist $olddlevel $olddlevel]
1153 set j $olddlevel
1215 set j $olddlevel
1154 foreach p $currentparents {
1216 foreach p $currentparents {
1155 set lastuse($p) $lineno
1217 set lastuse($p) $lineno
1156 if {$onscreen($p) == 0} {
1218 if {$onscreen($p) == 0} {
1157 set displist [linsert $displist $j $p]
1219 set displist [linsert $displist $j $p]
1158 set onscreen($p) 1
1220 set onscreen($p) 1
1159 incr j
1221 incr j
1160 }
1222 }
1161 }
1223 }
1162 if {$onscreen($id) == 0} {
1224 if {$onscreen($id) == 0} {
1163 lappend displist $id
1225 lappend displist $id
1164 set onscreen($id) 1
1226 set onscreen($id) 1
1165 }
1227 }
1166
1228
1167 # remove the null entry if present
1229 # remove the null entry if present
1168 set nullentry [lsearch -exact $displist {}]
1230 set nullentry [lsearch -exact $displist {}]
1169 if {$nullentry >= 0} {
1231 if {$nullentry >= 0} {
1170 set displist [lreplace $displist $nullentry $nullentry]
1232 set displist [lreplace $displist $nullentry $nullentry]
1171 }
1233 }
1172
1234
1173 # bring back the ones we need now (if we did it earlier
1235 # bring back the ones we need now (if we did it earlier
1174 # it would change displist and invalidate olddlevel)
1236 # it would change displist and invalidate olddlevel)
1175 foreach pi $reins {
1237 foreach pi $reins {
1176 # test again in case of duplicates in reins
1238 # test again in case of duplicates in reins
1177 set p [lindex $pi 0]
1239 set p [lindex $pi 0]
1178 if {$onscreen($p) < 0} {
1240 if {$onscreen($p) < 0} {
1179 set onscreen($p) 1
1241 set onscreen($p) 1
1180 set lastuse($p) $lineno
1242 set lastuse($p) $lineno
1181 set displist [linsert $displist [lindex $pi 1] $p]
1243 set displist [linsert $displist [lindex $pi 1] $p]
1182 incr nhyperspace -1
1244 incr nhyperspace -1
1183 }
1245 }
1184 }
1246 }
1185
1247
1186 set lastuse($id) $lineno
1248 set lastuse($id) $lineno
1187
1249
1188 # see if we need to make any lines jump off into hyperspace
1250 # see if we need to make any lines jump off into hyperspace
1189 set displ [llength $displist]
1251 set displ [llength $displist]
1190 if {$displ > $maxwidth} {
1252 if {$displ > $maxwidth} {
1191 set ages {}
1253 set ages {}
1192 foreach x $displist {
1254 foreach x $displist {
1193 lappend ages [list $lastuse($x) $x]
1255 lappend ages [list $lastuse($x) $x]
1194 }
1256 }
1195 set ages [lsort -integer -index 0 $ages]
1257 set ages [lsort -integer -index 0 $ages]
1196 set k 0
1258 set k 0
1197 while {$displ > $maxwidth} {
1259 while {$displ > $maxwidth} {
1198 set use [lindex $ages $k 0]
1260 set use [lindex $ages $k 0]
1199 set victim [lindex $ages $k 1]
1261 set victim [lindex $ages $k 1]
1200 if {$use >= $lineno - 5} break
1262 if {$use >= $lineno - 5} break
1201 incr k
1263 incr k
1202 if {[lsearch -exact $nohs $victim] >= 0} continue
1264 if {[lsearch -exact $nohs $victim] >= 0} continue
1203 set i [lsearch -exact $displist $victim]
1265 set i [lsearch -exact $displist $victim]
1204 set displist [lreplace $displist $i $i]
1266 set displist [lreplace $displist $i $i]
1205 set onscreen($victim) -1
1267 set onscreen($victim) -1
1206 incr nhyperspace
1268 incr nhyperspace
1207 incr displ -1
1269 incr displ -1
1208 if {$i < $nullentry} {
1270 if {$i < $nullentry} {
1209 incr nullentry -1
1271 incr nullentry -1
1210 }
1272 }
1211 set x [lindex $mainline($victim) end-1]
1273 set x [lindex $mainline($victim) end-1]
1212 lappend mainline($victim) $x $y1
1274 lappend mainline($victim) $x $y1
1213 set line [trimdiagend $mainline($victim)]
1275 set line [trimdiagend $mainline($victim)]
1214 set arrow "last"
1276 set arrow "last"
1215 if {$mainlinearrow($victim) ne "none"} {
1277 if {$mainlinearrow($victim) ne "none"} {
1216 set line [trimdiagstart $line]
1278 set line [trimdiagstart $line]
1217 set arrow "both"
1279 set arrow "both"
1218 }
1280 }
1219 lappend sidelines($victim) [list $line 1 $arrow]
1281 lappend sidelines($victim) [list $line 1 $arrow]
1220 unset mainline($victim)
1282 unset mainline($victim)
1221 }
1283 }
1222 }
1284 }
1223
1285
1224 set dlevel [lsearch -exact $displist $id]
1286 set dlevel [lsearch -exact $displist $id]
1225
1287
1226 # If we are reducing, put in a null entry
1288 # If we are reducing, put in a null entry
1227 if {$displ < $oldnlines} {
1289 if {$displ < $oldnlines} {
1228 # does the next line look like a merge?
1290 # does the next line look like a merge?
1229 # i.e. does it have > 1 new parent?
1291 # i.e. does it have > 1 new parent?
1230 if {$nnewparents($id) > 1} {
1292 if {$nnewparents($id) > 1} {
1231 set i [expr {$dlevel + 1}]
1293 set i [expr {$dlevel + 1}]
1232 } elseif {$nnewparents([lindex $olddisplist $olddlevel]) == 0} {
1294 } elseif {$nnewparents([lindex $olddisplist $olddlevel]) == 0} {
1233 set i $olddlevel
1295 set i $olddlevel
1234 if {$nullentry >= 0 && $nullentry < $i} {
1296 if {$nullentry >= 0 && $nullentry < $i} {
1235 incr i -1
1297 incr i -1
1236 }
1298 }
1237 } elseif {$nullentry >= 0} {
1299 } elseif {$nullentry >= 0} {
1238 set i $nullentry
1300 set i $nullentry
1239 while {$i < $displ
1301 while {$i < $displ
1240 && [lindex $olddisplist $i] == [lindex $displist $i]} {
1302 && [lindex $olddisplist $i] == [lindex $displist $i]} {
1241 incr i
1303 incr i
1242 }
1304 }
1243 } else {
1305 } else {
1244 set i $olddlevel
1306 set i $olddlevel
1245 if {$dlevel >= $i} {
1307 if {$dlevel >= $i} {
1246 incr i
1308 incr i
1247 }
1309 }
1248 }
1310 }
1249 if {$i < $displ} {
1311 if {$i < $displ} {
1250 set displist [linsert $displist $i {}]
1312 set displist [linsert $displist $i {}]
1251 incr displ
1313 incr displ
1252 if {$dlevel >= $i} {
1314 if {$dlevel >= $i} {
1253 incr dlevel
1315 incr dlevel
1254 }
1316 }
1255 }
1317 }
1256 }
1318 }
1257
1319
1258 # decide on the line spacing for the next line
1320 # decide on the line spacing for the next line
1259 set lj [expr {$lineno + 1}]
1321 set lj [expr {$lineno + 1}]
1260 set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}]
1322 set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}]
1261 if {$displ <= 1 || $canvx0 + $displ * $xspc2 <= $maxw} {
1323 if {$displ <= 1 || $canvx0 + $displ * $xspc2 <= $maxw} {
1262 set xspc1($lj) $xspc2
1324 set xspc1($lj) $xspc2
1263 } else {
1325 } else {
1264 set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($displ - 1)}]
1326 set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($displ - 1)}]
1265 if {$xspc1($lj) < $lthickness} {
1327 if {$xspc1($lj) < $lthickness} {
1266 set xspc1($lj) $lthickness
1328 set xspc1($lj) $lthickness
1267 }
1329 }
1268 }
1330 }
1269
1331
1270 foreach idi $reins {
1332 foreach idi $reins {
1271 set id [lindex $idi 0]
1333 set id [lindex $idi 0]
1272 set j [lsearch -exact $displist $id]
1334 set j [lsearch -exact $displist $id]
1273 set xj [xcoord $j $dlevel $lj]
1335 set xj [xcoord $j $dlevel $lj]
1274 set mainline($id) [list $xj $y2]
1336 set mainline($id) [list $xj $y2]
1275 set mainlinearrow($id) first
1337 set mainlinearrow($id) first
1276 }
1338 }
1277
1339
1278 set i -1
1340 set i -1
1279 foreach id $olddisplist {
1341 foreach id $olddisplist {
1280 incr i
1342 incr i
1281 if {$id == {}} continue
1343 if {$id == {}} continue
1282 if {$onscreen($id) <= 0} continue
1344 if {$onscreen($id) <= 0} continue
1283 set xi [xcoord $i $olddlevel $lineno]
1345 set xi [xcoord $i $olddlevel $lineno]
1284 if {$i == $olddlevel} {
1346 if {$i == $olddlevel} {
1285 foreach p $currentparents {
1347 foreach p $currentparents {
1286 set j [lsearch -exact $displist $p]
1348 set j [lsearch -exact $displist $p]
1287 set coords [list $xi $y1]
1349 set coords [list $xi $y1]
1288 set xj [xcoord $j $dlevel $lj]
1350 set xj [xcoord $j $dlevel $lj]
1289 if {$xj < $xi - $linespc} {
1351 if {$xj < $xi - $linespc} {
1290 lappend coords [expr {$xj + $linespc}] $y1
1352 lappend coords [expr {$xj + $linespc}] $y1
1291 notecrossings $p $j $i [expr {$j + 1}]
1353 notecrossings $p $j $i [expr {$j + 1}]
1292 } elseif {$xj > $xi + $linespc} {
1354 } elseif {$xj > $xi + $linespc} {
1293 lappend coords [expr {$xj - $linespc}] $y1
1355 lappend coords [expr {$xj - $linespc}] $y1
1294 notecrossings $p $i $j [expr {$j - 1}]
1356 notecrossings $p $i $j [expr {$j - 1}]
1295 }
1357 }
1296 if {[lsearch -exact $dupparents $p] >= 0} {
1358 if {[lsearch -exact $dupparents $p] >= 0} {
1297 # draw a double-width line to indicate the doubled parent
1359 # draw a double-width line to indicate the doubled parent
1298 lappend coords $xj $y2
1360 lappend coords $xj $y2
1299 lappend sidelines($p) [list $coords 2 none]
1361 lappend sidelines($p) [list $coords 2 none]
1300 if {![info exists mainline($p)]} {
1362 if {![info exists mainline($p)]} {
1301 set mainline($p) [list $xj $y2]
1363 set mainline($p) [list $xj $y2]
1302 set mainlinearrow($p) none
1364 set mainlinearrow($p) none
1303 }
1365 }
1304 } else {
1366 } else {
1305 # normal case, no parent duplicated
1367 # normal case, no parent duplicated
1306 set yb $y2
1368 set yb $y2
1307 set dx [expr {abs($xi - $xj)}]
1369 set dx [expr {abs($xi - $xj)}]
1308 if {0 && $dx < $linespc} {
1370 if {0 && $dx < $linespc} {
1309 set yb [expr {$y1 + $dx}]
1371 set yb [expr {$y1 + $dx}]
1310 }
1372 }
1311 if {![info exists mainline($p)]} {
1373 if {![info exists mainline($p)]} {
1312 if {$xi != $xj} {
1374 if {$xi != $xj} {
1313 lappend coords $xj $yb
1375 lappend coords $xj $yb
1314 }
1376 }
1315 set mainline($p) $coords
1377 set mainline($p) $coords
1316 set mainlinearrow($p) none
1378 set mainlinearrow($p) none
1317 } else {
1379 } else {
1318 lappend coords $xj $yb
1380 lappend coords $xj $yb
1319 if {$yb < $y2} {
1381 if {$yb < $y2} {
1320 lappend coords $xj $y2
1382 lappend coords $xj $y2
1321 }
1383 }
1322 lappend sidelines($p) [list $coords 1 none]
1384 lappend sidelines($p) [list $coords 1 none]
1323 }
1385 }
1324 }
1386 }
1325 }
1387 }
1326 } else {
1388 } else {
1327 set j $i
1389 set j $i
1328 if {[lindex $displist $i] != $id} {
1390 if {[lindex $displist $i] != $id} {
1329 set j [lsearch -exact $displist $id]
1391 set j [lsearch -exact $displist $id]
1330 }
1392 }
1331 if {$j != $i || $xspc1($lineno) != $xspc1($lj)
1393 if {$j != $i || $xspc1($lineno) != $xspc1($lj)
1332 || ($olddlevel < $i && $i < $dlevel)
1394 || ($olddlevel < $i && $i < $dlevel)
1333 || ($dlevel < $i && $i < $olddlevel)} {
1395 || ($dlevel < $i && $i < $olddlevel)} {
1334 set xj [xcoord $j $dlevel $lj]
1396 set xj [xcoord $j $dlevel $lj]
1335 lappend mainline($id) $xi $y1 $xj $y2
1397 lappend mainline($id) $xi $y1 $xj $y2
1336 }
1398 }
1337 }
1399 }
1338 }
1400 }
1339 return $dlevel
1401 return $dlevel
1340 }
1402 }
1341
1403
1342 # search for x in a list of lists
1404 # search for x in a list of lists
1343 proc llsearch {llist x} {
1405 proc llsearch {llist x} {
1344 set i 0
1406 set i 0
1345 foreach l $llist {
1407 foreach l $llist {
1346 if {$l == $x || [lsearch -exact $l $x] >= 0} {
1408 if {$l == $x || [lsearch -exact $l $x] >= 0} {
1347 return $i
1409 return $i
1348 }
1410 }
1349 incr i
1411 incr i
1350 }
1412 }
1351 return -1
1413 return -1
1352 }
1414 }
1353
1415
1354 proc drawmore {reading} {
1416 proc drawmore {reading} {
1355 global displayorder numcommits ncmupdate nextupdate
1417 global displayorder numcommits ncmupdate nextupdate
1356 global stopped nhyperspace parents commitlisted
1418 global stopped nhyperspace parents commitlisted
1357 global maxwidth onscreen displist currentparents olddlevel
1419 global maxwidth onscreen displist currentparents olddlevel
1358
1420
1359 set n [llength $displayorder]
1421 set n [llength $displayorder]
1360 while {$numcommits < $n} {
1422 while {$numcommits < $n} {
1361 set id [lindex $displayorder $numcommits]
1423 set id [lindex $displayorder $numcommits]
1362 set ctxend [expr {$numcommits + 10}]
1424 set ctxend [expr {$numcommits + 10}]
1363 if {!$reading && $ctxend > $n} {
1425 if {!$reading && $ctxend > $n} {
1364 set ctxend $n
1426 set ctxend $n
1365 }
1427 }
1366 set dlist {}
1428 set dlist {}
1367 if {$numcommits > 0} {
1429 if {$numcommits > 0} {
1368 set dlist [lreplace $displist $olddlevel $olddlevel]
1430 set dlist [lreplace $displist $olddlevel $olddlevel]
1369 set i $olddlevel
1431 set i $olddlevel
1370 foreach p $currentparents {
1432 foreach p $currentparents {
1371 if {$onscreen($p) == 0} {
1433 if {$onscreen($p) == 0} {
1372 set dlist [linsert $dlist $i $p]
1434 set dlist [linsert $dlist $i $p]
1373 incr i
1435 incr i
1374 }
1436 }
1375 }
1437 }
1376 }
1438 }
1377 set nohs {}
1439 set nohs {}
1378 set reins {}
1440 set reins {}
1379 set isfat [expr {[llength $dlist] > $maxwidth}]
1441 set isfat [expr {[llength $dlist] > $maxwidth}]
1380 if {$nhyperspace > 0 || $isfat} {
1442 if {$nhyperspace > 0 || $isfat} {
1381 if {$ctxend > $n} break
1443 if {$ctxend > $n} break
1382 # work out what to bring back and
1444 # work out what to bring back and
1383 # what we want to don't want to send into hyperspace
1445 # what we want to don't want to send into hyperspace
1384 set room 1
1446 set room 1
1385 for {set k $numcommits} {$k < $ctxend} {incr k} {
1447 for {set k $numcommits} {$k < $ctxend} {incr k} {
1386 set x [lindex $displayorder $k]
1448 set x [lindex $displayorder $k]
1387 set i [llsearch $dlist $x]
1449 set i [llsearch $dlist $x]
1388 if {$i < 0} {
1450 if {$i < 0} {
1389 set i [llength $dlist]
1451 set i [llength $dlist]
1390 lappend dlist $x
1452 lappend dlist $x
1391 }
1453 }
1392 if {[lsearch -exact $nohs $x] < 0} {
1454 if {[lsearch -exact $nohs $x] < 0} {
1393 lappend nohs $x
1455 lappend nohs $x
1394 }
1456 }
1395 if {$reins eq {} && $onscreen($x) < 0 && $room} {
1457 if {$reins eq {} && $onscreen($x) < 0 && $room} {
1396 set reins [list $x $i]
1458 set reins [list $x $i]
1397 }
1459 }
1398 set newp {}
1460 set newp {}
1399 if {[info exists commitlisted($x)]} {
1461 if {[info exists commitlisted($x)]} {
1400 set right 0
1462 set right 0
1401 foreach p $parents($x) {
1463 foreach p $parents($x) {
1402 if {[llsearch $dlist $p] < 0} {
1464 if {[llsearch $dlist $p] < 0} {
1403 lappend newp $p
1465 lappend newp $p
1404 if {[lsearch -exact $nohs $p] < 0} {
1466 if {[lsearch -exact $nohs $p] < 0} {
1405 lappend nohs $p
1467 lappend nohs $p
1406 }
1468 }
1407 if {$reins eq {} && $onscreen($p) < 0 && $room} {
1469 if {$reins eq {} && $onscreen($p) < 0 && $room} {
1408 set reins [list $p [expr {$i + $right}]]
1470 set reins [list $p [expr {$i + $right}]]
1409 }
1471 }
1410 }
1472 }
1411 set right 1
1473 set right 1
1412 }
1474 }
1413 }
1475 }
1414 set l [lindex $dlist $i]
1476 set l [lindex $dlist $i]
1415 if {[llength $l] == 1} {
1477 if {[llength $l] == 1} {
1416 set l $newp
1478 set l $newp
1417 } else {
1479 } else {
1418 set j [lsearch -exact $l $x]
1480 set j [lsearch -exact $l $x]
1419 set l [concat [lreplace $l $j $j] $newp]
1481 set l [concat [lreplace $l $j $j] $newp]
1420 }
1482 }
1421 set dlist [lreplace $dlist $i $i $l]
1483 set dlist [lreplace $dlist $i $i $l]
1422 if {$room && $isfat && [llength $newp] <= 1} {
1484 if {$room && $isfat && [llength $newp] <= 1} {
1423 set room 0
1485 set room 0
1424 }
1486 }
1425 }
1487 }
1426 }
1488 }
1427
1489
1428 set dlevel [drawslants $id $reins $nohs]
1490 set dlevel [drawslants $id $reins $nohs]
1429 drawcommitline $dlevel
1491 drawcommitline $dlevel
1430 if {[clock clicks -milliseconds] >= $nextupdate
1492 if {[clock clicks -milliseconds] >= $nextupdate
1431 && $numcommits >= $ncmupdate} {
1493 && $numcommits >= $ncmupdate} {
1432 doupdate $reading
1494 doupdate $reading
1433 if {$stopped} break
1495 if {$stopped} break
1434 }
1496 }
1435 }
1497 }
1436 }
1498 }
1437
1499
1438 # level here is an index in todo
1500 # level here is an index in todo
1439 proc updatetodo {level noshortcut} {
1501 proc updatetodo {level noshortcut} {
1440 global ncleft todo nnewparents
1502 global ncleft todo nnewparents
1441 global commitlisted parents onscreen
1503 global commitlisted parents onscreen
1442
1504
1443 set id [lindex $todo $level]
1505 set id [lindex $todo $level]
1444 set olds {}
1506 set olds {}
1445 if {[info exists commitlisted($id)]} {
1507 if {[info exists commitlisted($id)]} {
1446 foreach p $parents($id) {
1508 foreach p $parents($id) {
1447 if {[lsearch -exact $olds $p] < 0} {
1509 if {[lsearch -exact $olds $p] < 0} {
1448 lappend olds $p
1510 lappend olds $p
1449 }
1511 }
1450 }
1512 }
1451 }
1513 }
1452 if {!$noshortcut && [llength $olds] == 1} {
1514 if {!$noshortcut && [llength $olds] == 1} {
1453 set p [lindex $olds 0]
1515 set p [lindex $olds 0]
1454 if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
1516 if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
1455 set ncleft($p) 0
1517 set ncleft($p) 0
1456 set todo [lreplace $todo $level $level $p]
1518 set todo [lreplace $todo $level $level $p]
1457 set onscreen($p) 0
1519 set onscreen($p) 0
1458 set nnewparents($id) 1
1520 set nnewparents($id) 1
1459 return 0
1521 return 0
1460 }
1522 }
1461 }
1523 }
1462
1524
1463 set todo [lreplace $todo $level $level]
1525 set todo [lreplace $todo $level $level]
1464 set i $level
1526 set i $level
1465 set n 0
1527 set n 0
1466 foreach p $olds {
1528 foreach p $olds {
1467 incr ncleft($p) -1
1529 incr ncleft($p) -1
1468 set k [lsearch -exact $todo $p]
1530 set k [lsearch -exact $todo $p]
1469 if {$k < 0} {
1531 if {$k < 0} {
1470 set todo [linsert $todo $i $p]
1532 set todo [linsert $todo $i $p]
1471 set onscreen($p) 0
1533 set onscreen($p) 0
1472 incr i
1534 incr i
1473 incr n
1535 incr n
1474 }
1536 }
1475 }
1537 }
1476 set nnewparents($id) $n
1538 set nnewparents($id) $n
1477
1539
1478 return 1
1540 return 1
1479 }
1541 }
1480
1542
1481 proc decidenext {{noread 0}} {
1543 proc decidenext {{noread 0}} {
1482 global ncleft todo
1544 global ncleft todo
1483 global datemode cdate
1545 global datemode cdate
1484 global commitinfo
1546 global commitinfo
1485
1547
1486 # choose which one to do next time around
1548 # choose which one to do next time around
1487 set todol [llength $todo]
1549 set todol [llength $todo]
1488 set level -1
1550 set level -1
1489 set latest {}
1551 set latest {}
1490 for {set k $todol} {[incr k -1] >= 0} {} {
1552 for {set k $todol} {[incr k -1] >= 0} {} {
1491 set p [lindex $todo $k]
1553 set p [lindex $todo $k]
1492 if {$ncleft($p) == 0} {
1554 if {$ncleft($p) == 0} {
1493 if {$datemode} {
1555 if {$datemode} {
1494 if {![info exists commitinfo($p)]} {
1556 if {![info exists commitinfo($p)]} {
1495 if {$noread} {
1557 if {$noread} {
1496 return {}
1558 return {}
1497 }
1559 }
1498 readcommit $p
1560 readcommit $p
1499 }
1561 }
1500 if {$latest == {} || $cdate($p) > $latest} {
1562 if {$latest == {} || $cdate($p) > $latest} {
1501 set level $k
1563 set level $k
1502 set latest $cdate($p)
1564 set latest $cdate($p)
1503 }
1565 }
1504 } else {
1566 } else {
1505 set level $k
1567 set level $k
1506 break
1568 break
1507 }
1569 }
1508 }
1570 }
1509 }
1571 }
1510 if {$level < 0} {
1572 if {$level < 0} {
1511 if {$todo != {}} {
1573 if {$todo != {}} {
1512 puts "ERROR: none of the pending commits can be done yet:"
1574 puts "ERROR: none of the pending commits can be done yet:"
1513 foreach p $todo {
1575 foreach p $todo {
1514 puts " $p ($ncleft($p))"
1576 puts " $p ($ncleft($p))"
1515 }
1577 }
1516 }
1578 }
1517 return -1
1579 return -1
1518 }
1580 }
1519
1581
1520 return $level
1582 return $level
1521 }
1583 }
1522
1584
1523 proc drawcommit {id} {
1585 proc drawcommit {id} {
1524 global phase todo nchildren datemode nextupdate
1586 global phase todo nchildren datemode nextupdate
1525 global numcommits ncmupdate displayorder todo onscreen
1587 global numcommits ncmupdate displayorder todo onscreen
1526
1588
1527 if {$phase != "incrdraw"} {
1589 if {$phase != "incrdraw"} {
1528 set phase incrdraw
1590 set phase incrdraw
1529 set displayorder {}
1591 set displayorder {}
1530 set todo {}
1592 set todo {}
1531 initgraph
1593 initgraph
1532 }
1594 }
1533 if {$nchildren($id) == 0} {
1595 if {$nchildren($id) == 0} {
1534 lappend todo $id
1596 lappend todo $id
1535 set onscreen($id) 0
1597 set onscreen($id) 0
1536 }
1598 }
1537 set level [decidenext 1]
1599 set level [decidenext 1]
1538 if {$level == {} || $id != [lindex $todo $level]} {
1600 if {$level == {} || $id != [lindex $todo $level]} {
1539 return
1601 return
1540 }
1602 }
1541 while 1 {
1603 while 1 {
1542 lappend displayorder [lindex $todo $level]
1604 lappend displayorder [lindex $todo $level]
1543 if {[updatetodo $level $datemode]} {
1605 if {[updatetodo $level $datemode]} {
1544 set level [decidenext 1]
1606 set level [decidenext 1]
1545 if {$level == {}} break
1607 if {$level == {}} break
1546 }
1608 }
1547 set id [lindex $todo $level]
1609 set id [lindex $todo $level]
1548 if {![info exists commitlisted($id)]} {
1610 if {![info exists commitlisted($id)]} {
1549 break
1611 break
1550 }
1612 }
1551 }
1613 }
1552 drawmore 1
1614 drawmore 1
1553 }
1615 }
1554
1616
1555 proc finishcommits {} {
1617 proc finishcommits {} {
1556 global phase
1618 global phase
1557 global canv mainfont ctext maincursor textcursor
1619 global canv mainfont ctext maincursor textcursor
1558
1620
1559 if {$phase != "incrdraw"} {
1621 if {$phase != "incrdraw"} {
1560 $canv delete all
1622 $canv delete all
1561 $canv create text 3 3 -anchor nw -text "No commits selected" \
1623 $canv create text 3 3 -anchor nw -text "No commits selected" \
1562 -font $mainfont -tags textitems
1624 -font $mainfont -tags textitems
1563 set phase {}
1625 set phase {}
1564 } else {
1626 } else {
1565 drawrest
1627 drawrest
1566 }
1628 }
1567 . config -cursor $maincursor
1629 . config -cursor $maincursor
1568 settextcursor $textcursor
1630 settextcursor $textcursor
1569 }
1631 }
1570
1632
1571 # Don't change the text pane cursor if it is currently the hand cursor,
1633 # Don't change the text pane cursor if it is currently the hand cursor,
1572 # showing that we are over a sha1 ID link.
1634 # showing that we are over a sha1 ID link.
1573 proc settextcursor {c} {
1635 proc settextcursor {c} {
1574 global ctext curtextcursor
1636 global ctext curtextcursor
1575
1637
1576 if {[$ctext cget -cursor] == $curtextcursor} {
1638 if {[$ctext cget -cursor] == $curtextcursor} {
1577 $ctext config -cursor $c
1639 $ctext config -cursor $c
1578 }
1640 }
1579 set curtextcursor $c
1641 set curtextcursor $c
1580 }
1642 }
1581
1643
1582 proc drawgraph {} {
1644 proc drawgraph {} {
1583 global nextupdate startmsecs ncmupdate
1645 global nextupdate startmsecs ncmupdate
1584 global displayorder onscreen
1646 global displayorder onscreen
1585
1647
1586 if {$displayorder == {}} return
1648 if {$displayorder == {}} return
1587 set startmsecs [clock clicks -milliseconds]
1649 set startmsecs [clock clicks -milliseconds]
1588 set nextupdate [expr $startmsecs + 100]
1650 set nextupdate [expr $startmsecs + 100]
1589 set ncmupdate 1
1651 set ncmupdate 1
1590 initgraph
1652 initgraph
1591 foreach id $displayorder {
1653 foreach id $displayorder {
1592 set onscreen($id) 0
1654 set onscreen($id) 0
1593 }
1655 }
1594 drawmore 0
1656 drawmore 0
1595 }
1657 }
1596
1658
1597 proc drawrest {} {
1659 proc drawrest {} {
1598 global phase stopped redisplaying selectedline
1660 global phase stopped redisplaying selectedline
1599 global datemode todo displayorder
1661 global datemode todo displayorder
1600 global numcommits ncmupdate
1662 global numcommits ncmupdate
1601 global nextupdate startmsecs
1663 global nextupdate startmsecs
1602
1664
1603 set level [decidenext]
1665 set level [decidenext]
1604 if {$level >= 0} {
1666 if {$level >= 0} {
1605 set phase drawgraph
1667 set phase drawgraph
1606 while 1 {
1668 while 1 {
1607 lappend displayorder [lindex $todo $level]
1669 lappend displayorder [lindex $todo $level]
1608 set hard [updatetodo $level $datemode]
1670 set hard [updatetodo $level $datemode]
1609 if {$hard} {
1671 if {$hard} {
1610 set level [decidenext]
1672 set level [decidenext]
1611 if {$level < 0} break
1673 if {$level < 0} break
1612 }
1674 }
1613 }
1675 }
1614 drawmore 0
1676 drawmore 0
1615 }
1677 }
1616 set phase {}
1678 set phase {}
1617 set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
1679 set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
1618 #puts "overall $drawmsecs ms for $numcommits commits"
1680 #puts "overall $drawmsecs ms for $numcommits commits"
1619 if {$redisplaying} {
1681 if {$redisplaying} {
1620 if {$stopped == 0 && [info exists selectedline]} {
1682 if {$stopped == 0 && [info exists selectedline]} {
1621 selectline $selectedline 0
1683 selectline $selectedline 0
1622 }
1684 }
1623 if {$stopped == 1} {
1685 if {$stopped == 1} {
1624 set stopped 0
1686 set stopped 0
1625 after idle drawgraph
1687 after idle drawgraph
1626 } else {
1688 } else {
1627 set redisplaying 0
1689 set redisplaying 0
1628 }
1690 }
1629 }
1691 }
1630 }
1692 }
1631
1693
1632 proc findmatches {f} {
1694 proc findmatches {f} {
1633 global findtype foundstring foundstrlen
1695 global findtype foundstring foundstrlen
1634 if {$findtype == "Regexp"} {
1696 if {$findtype == "Regexp"} {
1635 set matches [regexp -indices -all -inline $foundstring $f]
1697 set matches [regexp -indices -all -inline $foundstring $f]
1636 } else {
1698 } else {
1637 if {$findtype == "IgnCase"} {
1699 if {$findtype == "IgnCase"} {
1638 set str [string tolower $f]
1700 set str [string tolower $f]
1639 } else {
1701 } else {
1640 set str $f
1702 set str $f
1641 }
1703 }
1642 set matches {}
1704 set matches {}
1643 set i 0
1705 set i 0
1644 while {[set j [string first $foundstring $str $i]] >= 0} {
1706 while {[set j [string first $foundstring $str $i]] >= 0} {
1645 lappend matches [list $j [expr $j+$foundstrlen-1]]
1707 lappend matches [list $j [expr $j+$foundstrlen-1]]
1646 set i [expr $j + $foundstrlen]
1708 set i [expr $j + $foundstrlen]
1647 }
1709 }
1648 }
1710 }
1649 return $matches
1711 return $matches
1650 }
1712 }
1651
1713
1652 proc dofind {} {
1714 proc dofind {} {
1653 global findtype findloc findstring markedmatches commitinfo
1715 global findtype findloc findstring markedmatches commitinfo
1654 global numcommits lineid linehtag linentag linedtag
1716 global numcommits lineid linehtag linentag linedtag
1655 global mainfont namefont canv canv2 canv3 selectedline
1717 global mainfont namefont canv canv2 canv3 selectedline
1656 global matchinglines foundstring foundstrlen
1718 global matchinglines foundstring foundstrlen
1657
1719
1658 stopfindproc
1720 stopfindproc
1659 unmarkmatches
1721 unmarkmatches
1660 focus .
1722 focus .
1661 set matchinglines {}
1723 set matchinglines {}
1662 if {$findloc == "Pickaxe"} {
1724 if {$findloc == "Pickaxe"} {
1663 findpatches
1725 findpatches
1664 return
1726 return
1665 }
1727 }
1666 if {$findtype == "IgnCase"} {
1728 if {$findtype == "IgnCase"} {
1667 set foundstring [string tolower $findstring]
1729 set foundstring [string tolower $findstring]
1668 } else {
1730 } else {
1669 set foundstring $findstring
1731 set foundstring $findstring
1670 }
1732 }
1671 set foundstrlen [string length $findstring]
1733 set foundstrlen [string length $findstring]
1672 if {$foundstrlen == 0} return
1734 if {$foundstrlen == 0} return
1673 if {$findloc == "Files"} {
1735 if {$findloc == "Files"} {
1674 findfiles
1736 findfiles
1675 return
1737 return
1676 }
1738 }
1677 if {![info exists selectedline]} {
1739 if {![info exists selectedline]} {
1678 set oldsel -1
1740 set oldsel -1
1679 } else {
1741 } else {
1680 set oldsel $selectedline
1742 set oldsel $selectedline
1681 }
1743 }
1682 set didsel 0
1744 set didsel 0
1683 set fldtypes {Headline Author Date Committer CDate Comment}
1745 set fldtypes {Headline Author Date Committer CDate Comment}
1684 for {set l 0} {$l < $numcommits} {incr l} {
1746 for {set l 0} {$l < $numcommits} {incr l} {
1685 set id $lineid($l)
1747 set id $lineid($l)
1686 set info $commitinfo($id)
1748 set info $commitinfo($id)
1687 set doesmatch 0
1749 set doesmatch 0
1688 foreach f $info ty $fldtypes {
1750 foreach f $info ty $fldtypes {
1689 if {$findloc != "All fields" && $findloc != $ty} {
1751 if {$findloc != "All fields" && $findloc != $ty} {
1690 continue
1752 continue
1691 }
1753 }
1692 set matches [findmatches $f]
1754 set matches [findmatches $f]
1693 if {$matches == {}} continue
1755 if {$matches == {}} continue
1694 set doesmatch 1
1756 set doesmatch 1
1695 if {$ty == "Headline"} {
1757 if {$ty == "Headline"} {
1696 markmatches $canv $l $f $linehtag($l) $matches $mainfont
1758 markmatches $canv $l $f $linehtag($l) $matches $mainfont
1697 } elseif {$ty == "Author"} {
1759 } elseif {$ty == "Author"} {
1698 markmatches $canv2 $l $f $linentag($l) $matches $namefont
1760 markmatches $canv2 $l $f $linentag($l) $matches $namefont
1699 } elseif {$ty == "Date"} {
1761 } elseif {$ty == "Date"} {
1700 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
1762 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
1701 }
1763 }
1702 }
1764 }
1703 if {$doesmatch} {
1765 if {$doesmatch} {
1704 lappend matchinglines $l
1766 lappend matchinglines $l
1705 if {!$didsel && $l > $oldsel} {
1767 if {!$didsel && $l > $oldsel} {
1706 findselectline $l
1768 findselectline $l
1707 set didsel 1
1769 set didsel 1
1708 }
1770 }
1709 }
1771 }
1710 }
1772 }
1711 if {$matchinglines == {}} {
1773 if {$matchinglines == {}} {
1712 bell
1774 bell
1713 } elseif {!$didsel} {
1775 } elseif {!$didsel} {
1714 findselectline [lindex $matchinglines 0]
1776 findselectline [lindex $matchinglines 0]
1715 }
1777 }
1716 }
1778 }
1717
1779
1718 proc findselectline {l} {
1780 proc findselectline {l} {
1719 global findloc commentend ctext
1781 global findloc commentend ctext
1720 selectline $l 1
1782 selectline $l 1
1721 if {$findloc == "All fields" || $findloc == "Comments"} {
1783 if {$findloc == "All fields" || $findloc == "Comments"} {
1722 # highlight the matches in the comments
1784 # highlight the matches in the comments
1723 set f [$ctext get 1.0 $commentend]
1785 set f [$ctext get 1.0 $commentend]
1724 set matches [findmatches $f]
1786 set matches [findmatches $f]
1725 foreach match $matches {
1787 foreach match $matches {
1726 set start [lindex $match 0]
1788 set start [lindex $match 0]
1727 set end [expr [lindex $match 1] + 1]
1789 set end [expr [lindex $match 1] + 1]
1728 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
1790 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
1729 }
1791 }
1730 }
1792 }
1731 }
1793 }
1732
1794
1733 proc findnext {restart} {
1795 proc findnext {restart} {
1734 global matchinglines selectedline
1796 global matchinglines selectedline
1735 if {![info exists matchinglines]} {
1797 if {![info exists matchinglines]} {
1736 if {$restart} {
1798 if {$restart} {
1737 dofind
1799 dofind
1738 }
1800 }
1739 return
1801 return
1740 }
1802 }
1741 if {![info exists selectedline]} return
1803 if {![info exists selectedline]} return
1742 foreach l $matchinglines {
1804 foreach l $matchinglines {
1743 if {$l > $selectedline} {
1805 if {$l > $selectedline} {
1744 findselectline $l
1806 findselectline $l
1745 return
1807 return
1746 }
1808 }
1747 }
1809 }
1748 bell
1810 bell
1749 }
1811 }
1750
1812
1751 proc findprev {} {
1813 proc findprev {} {
1752 global matchinglines selectedline
1814 global matchinglines selectedline
1753 if {![info exists matchinglines]} {
1815 if {![info exists matchinglines]} {
1754 dofind
1816 dofind
1755 return
1817 return
1756 }
1818 }
1757 if {![info exists selectedline]} return
1819 if {![info exists selectedline]} return
1758 set prev {}
1820 set prev {}
1759 foreach l $matchinglines {
1821 foreach l $matchinglines {
1760 if {$l >= $selectedline} break
1822 if {$l >= $selectedline} break
1761 set prev $l
1823 set prev $l
1762 }
1824 }
1763 if {$prev != {}} {
1825 if {$prev != {}} {
1764 findselectline $prev
1826 findselectline $prev
1765 } else {
1827 } else {
1766 bell
1828 bell
1767 }
1829 }
1768 }
1830 }
1769
1831
1770 proc findlocchange {name ix op} {
1832 proc findlocchange {name ix op} {
1771 global findloc findtype findtypemenu
1833 global findloc findtype findtypemenu
1772 if {$findloc == "Pickaxe"} {
1834 if {$findloc == "Pickaxe"} {
1773 set findtype Exact
1835 set findtype Exact
1774 set state disabled
1836 set state disabled
1775 } else {
1837 } else {
1776 set state normal
1838 set state normal
1777 }
1839 }
1778 $findtypemenu entryconf 1 -state $state
1840 $findtypemenu entryconf 1 -state $state
1779 $findtypemenu entryconf 2 -state $state
1841 $findtypemenu entryconf 2 -state $state
1780 }
1842 }
1781
1843
1782 proc stopfindproc {{done 0}} {
1844 proc stopfindproc {{done 0}} {
1783 global findprocpid findprocfile findids
1845 global findprocpid findprocfile findids
1784 global ctext findoldcursor phase maincursor textcursor
1846 global ctext findoldcursor phase maincursor textcursor
1785 global findinprogress
1847 global findinprogress
1786
1848
1787 catch {unset findids}
1849 catch {unset findids}
1788 if {[info exists findprocpid]} {
1850 if {[info exists findprocpid]} {
1789 if {!$done} {
1851 if {!$done} {
1790 catch {exec kill $findprocpid}
1852 catch {exec kill $findprocpid}
1791 }
1853 }
1792 catch {close $findprocfile}
1854 catch {close $findprocfile}
1793 unset findprocpid
1855 unset findprocpid
1794 }
1856 }
1795 if {[info exists findinprogress]} {
1857 if {[info exists findinprogress]} {
1796 unset findinprogress
1858 unset findinprogress
1797 if {$phase != "incrdraw"} {
1859 if {$phase != "incrdraw"} {
1798 . config -cursor $maincursor
1860 . config -cursor $maincursor
1799 settextcursor $textcursor
1861 settextcursor $textcursor
1800 }
1862 }
1801 }
1863 }
1802 }
1864 }
1803
1865
1804 proc findpatches {} {
1866 proc findpatches {} {
1805 global findstring selectedline numcommits
1867 global findstring selectedline numcommits
1806 global findprocpid findprocfile
1868 global findprocpid findprocfile
1807 global finddidsel ctext lineid findinprogress
1869 global finddidsel ctext lineid findinprogress
1808 global findinsertpos
1870 global findinsertpos
1809 global env
1871 global env
1810
1872
1811 if {$numcommits == 0} return
1873 if {$numcommits == 0} return
1812
1874
1813 # make a list of all the ids to search, starting at the one
1875 # make a list of all the ids to search, starting at the one
1814 # after the selected line (if any)
1876 # after the selected line (if any)
1815 if {[info exists selectedline]} {
1877 if {[info exists selectedline]} {
1816 set l $selectedline
1878 set l $selectedline
1817 } else {
1879 } else {
1818 set l -1
1880 set l -1
1819 }
1881 }
1820 set inputids {}
1882 set inputids {}
1821 for {set i 0} {$i < $numcommits} {incr i} {
1883 for {set i 0} {$i < $numcommits} {incr i} {
1822 if {[incr l] >= $numcommits} {
1884 if {[incr l] >= $numcommits} {
1823 set l 0
1885 set l 0
1824 }
1886 }
1825 append inputids $lineid($l) "\n"
1887 append inputids $lineid($l) "\n"
1826 }
1888 }
1827
1889
1828 if {[catch {
1890 if {[catch {
1829 set f [open [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree --stdin -s -r -S$findstring << $inputids] r]
1891 set f [open [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree --stdin -s -r -S$findstring << $inputids] r]
1830 } err]} {
1892 } err]} {
1831 error_popup "Error starting search process: $err"
1893 error_popup "Error starting search process: $err"
1832 return
1894 return
1833 }
1895 }
1834
1896
1835 set findinsertpos end
1897 set findinsertpos end
1836 set findprocfile $f
1898 set findprocfile $f
1837 set findprocpid [pid $f]
1899 set findprocpid [pid $f]
1838 fconfigure $f -blocking 0
1900 fconfigure $f -blocking 0
1839 fileevent $f readable readfindproc
1901 fileevent $f readable readfindproc
1840 set finddidsel 0
1902 set finddidsel 0
1841 . config -cursor watch
1903 . config -cursor watch
1842 settextcursor watch
1904 settextcursor watch
1843 set findinprogress 1
1905 set findinprogress 1
1844 }
1906 }
1845
1907
1846 proc readfindproc {} {
1908 proc readfindproc {} {
1847 global findprocfile finddidsel
1909 global findprocfile finddidsel
1848 global idline matchinglines findinsertpos
1910 global idline matchinglines findinsertpos
1849
1911
1850 set n [gets $findprocfile line]
1912 set n [gets $findprocfile line]
1851 if {$n < 0} {
1913 if {$n < 0} {
1852 if {[eof $findprocfile]} {
1914 if {[eof $findprocfile]} {
1853 stopfindproc 1
1915 stopfindproc 1
1854 if {!$finddidsel} {
1916 if {!$finddidsel} {
1855 bell
1917 bell
1856 }
1918 }
1857 }
1919 }
1858 return
1920 return
1859 }
1921 }
1860 if {![regexp {^[0-9a-f]{12}} $line id]} {
1922 if {![regexp {^[0-9a-f]{12}} $line id]} {
1861 error_popup "Can't parse git-diff-tree output: $line"
1923 error_popup "Can't parse git-diff-tree output: $line"
1862 stopfindproc
1924 stopfindproc
1863 return
1925 return
1864 }
1926 }
1865 if {![info exists idline($id)]} {
1927 if {![info exists idline($id)]} {
1866 puts stderr "spurious id: $id"
1928 puts stderr "spurious id: $id"
1867 return
1929 return
1868 }
1930 }
1869 set l $idline($id)
1931 set l $idline($id)
1870 insertmatch $l $id
1932 insertmatch $l $id
1871 }
1933 }
1872
1934
1873 proc insertmatch {l id} {
1935 proc insertmatch {l id} {
1874 global matchinglines findinsertpos finddidsel
1936 global matchinglines findinsertpos finddidsel
1875
1937
1876 if {$findinsertpos == "end"} {
1938 if {$findinsertpos == "end"} {
1877 if {$matchinglines != {} && $l < [lindex $matchinglines 0]} {
1939 if {$matchinglines != {} && $l < [lindex $matchinglines 0]} {
1878 set matchinglines [linsert $matchinglines 0 $l]
1940 set matchinglines [linsert $matchinglines 0 $l]
1879 set findinsertpos 1
1941 set findinsertpos 1
1880 } else {
1942 } else {
1881 lappend matchinglines $l
1943 lappend matchinglines $l
1882 }
1944 }
1883 } else {
1945 } else {
1884 set matchinglines [linsert $matchinglines $findinsertpos $l]
1946 set matchinglines [linsert $matchinglines $findinsertpos $l]
1885 incr findinsertpos
1947 incr findinsertpos
1886 }
1948 }
1887 markheadline $l $id
1949 markheadline $l $id
1888 if {!$finddidsel} {
1950 if {!$finddidsel} {
1889 findselectline $l
1951 findselectline $l
1890 set finddidsel 1
1952 set finddidsel 1
1891 }
1953 }
1892 }
1954 }
1893
1955
1894 proc findfiles {} {
1956 proc findfiles {} {
1895 global selectedline numcommits lineid ctext
1957 global selectedline numcommits lineid ctext
1896 global ffileline finddidsel parents nparents
1958 global ffileline finddidsel parents nparents
1897 global findinprogress findstartline findinsertpos
1959 global findinprogress findstartline findinsertpos
1898 global treediffs fdiffids fdiffsneeded fdiffpos
1960 global treediffs fdiffids fdiffsneeded fdiffpos
1899 global findmergefiles
1961 global findmergefiles
1900 global env
1962 global env
1901
1963
1902 if {$numcommits == 0} return
1964 if {$numcommits == 0} return
1903
1965
1904 if {[info exists selectedline]} {
1966 if {[info exists selectedline]} {
1905 set l [expr {$selectedline + 1}]
1967 set l [expr {$selectedline + 1}]
1906 } else {
1968 } else {
1907 set l 0
1969 set l 0
1908 }
1970 }
1909 set ffileline $l
1971 set ffileline $l
1910 set findstartline $l
1972 set findstartline $l
1911 set diffsneeded {}
1973 set diffsneeded {}
1912 set fdiffsneeded {}
1974 set fdiffsneeded {}
1913 while 1 {
1975 while 1 {
1914 set id $lineid($l)
1976 set id $lineid($l)
1915 if {$findmergefiles || $nparents($id) == 1} {
1977 if {$findmergefiles || $nparents($id) == 1} {
1916 foreach p $parents($id) {
1978 foreach p $parents($id) {
1917 if {![info exists treediffs([list $id $p])]} {
1979 if {![info exists treediffs([list $id $p])]} {
1918 append diffsneeded "$id $p\n"
1980 append diffsneeded "$id $p\n"
1919 lappend fdiffsneeded [list $id $p]
1981 lappend fdiffsneeded [list $id $p]
1920 }
1982 }
1921 }
1983 }
1922 }
1984 }
1923 if {[incr l] >= $numcommits} {
1985 if {[incr l] >= $numcommits} {
1924 set l 0
1986 set l 0
1925 }
1987 }
1926 if {$l == $findstartline} break
1988 if {$l == $findstartline} break
1927 }
1989 }
1928
1990
1929 # start off a git-diff-tree process if needed
1991 # start off a git-diff-tree process if needed
1930 if {$diffsneeded ne {}} {
1992 if {$diffsneeded ne {}} {
1931 if {[catch {
1993 if {[catch {
1932 set df [open [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -r --stdin << $diffsneeded] r]
1994 set df [open [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -r --stdin << $diffsneeded] r]
1933 } err ]} {
1995 } err ]} {
1934 error_popup "Error starting search process: $err"
1996 error_popup "Error starting search process: $err"
1935 return
1997 return
1936 }
1998 }
1937 catch {unset fdiffids}
1999 catch {unset fdiffids}
1938 set fdiffpos 0
2000 set fdiffpos 0
1939 fconfigure $df -blocking 0
2001 fconfigure $df -blocking 0
1940 fileevent $df readable [list readfilediffs $df]
2002 fileevent $df readable [list readfilediffs $df]
1941 }
2003 }
1942
2004
1943 set finddidsel 0
2005 set finddidsel 0
1944 set findinsertpos end
2006 set findinsertpos end
1945 set id $lineid($l)
2007 set id $lineid($l)
1946 set p [lindex $parents($id) 0]
2008 set p [lindex $parents($id) 0]
1947 . config -cursor watch
2009 . config -cursor watch
1948 settextcursor watch
2010 settextcursor watch
1949 set findinprogress 1
2011 set findinprogress 1
1950 findcont [list $id $p]
2012 findcont [list $id $p]
1951 update
2013 update
1952 }
2014 }
1953
2015
1954 proc readfilediffs {df} {
2016 proc readfilediffs {df} {
1955 global findids fdiffids fdiffs
2017 global findids fdiffids fdiffs
1956
2018
1957 set n [gets $df line]
2019 set n [gets $df line]
1958 if {$n < 0} {
2020 if {$n < 0} {
1959 if {[eof $df]} {
2021 if {[eof $df]} {
1960 donefilediff
2022 donefilediff
1961 if {[catch {close $df} err]} {
2023 if {[catch {close $df} err]} {
1962 stopfindproc
2024 stopfindproc
1963 bell
2025 bell
1964 error_popup "Error in hg debug-diff-tree: $err"
2026 error_popup "Error in hg debug-diff-tree: $err"
1965 } elseif {[info exists findids]} {
2027 } elseif {[info exists findids]} {
1966 set ids $findids
2028 set ids $findids
1967 stopfindproc
2029 stopfindproc
1968 bell
2030 bell
1969 error_popup "Couldn't find diffs for {$ids}"
2031 error_popup "Couldn't find diffs for {$ids}"
1970 }
2032 }
1971 }
2033 }
1972 return
2034 return
1973 }
2035 }
1974 if {[regexp {^([0-9a-f]{12}) \(from ([0-9a-f]{12})\)} $line match id p]} {
2036 if {[regexp {^([0-9a-f]{12}) \(from ([0-9a-f]{12})\)} $line match id p]} {
1975 # start of a new string of diffs
2037 # start of a new string of diffs
1976 donefilediff
2038 donefilediff
1977 set fdiffids [list $id $p]
2039 set fdiffids [list $id $p]
1978 set fdiffs {}
2040 set fdiffs {}
1979 } elseif {[string match ":*" $line]} {
2041 } elseif {[string match ":*" $line]} {
1980 lappend fdiffs [lindex $line 5]
2042 lappend fdiffs [lindex $line 5]
1981 }
2043 }
1982 }
2044 }
1983
2045
1984 proc donefilediff {} {
2046 proc donefilediff {} {
1985 global fdiffids fdiffs treediffs findids
2047 global fdiffids fdiffs treediffs findids
1986 global fdiffsneeded fdiffpos
2048 global fdiffsneeded fdiffpos
1987
2049
1988 if {[info exists fdiffids]} {
2050 if {[info exists fdiffids]} {
1989 while {[lindex $fdiffsneeded $fdiffpos] ne $fdiffids
2051 while {[lindex $fdiffsneeded $fdiffpos] ne $fdiffids
1990 && $fdiffpos < [llength $fdiffsneeded]} {
2052 && $fdiffpos < [llength $fdiffsneeded]} {
1991 # git-diff-tree doesn't output anything for a commit
2053 # git-diff-tree doesn't output anything for a commit
1992 # which doesn't change anything
2054 # which doesn't change anything
1993 set nullids [lindex $fdiffsneeded $fdiffpos]
2055 set nullids [lindex $fdiffsneeded $fdiffpos]
1994 set treediffs($nullids) {}
2056 set treediffs($nullids) {}
1995 if {[info exists findids] && $nullids eq $findids} {
2057 if {[info exists findids] && $nullids eq $findids} {
1996 unset findids
2058 unset findids
1997 findcont $nullids
2059 findcont $nullids
1998 }
2060 }
1999 incr fdiffpos
2061 incr fdiffpos
2000 }
2062 }
2001 incr fdiffpos
2063 incr fdiffpos
2002
2064
2003 if {![info exists treediffs($fdiffids)]} {
2065 if {![info exists treediffs($fdiffids)]} {
2004 set treediffs($fdiffids) $fdiffs
2066 set treediffs($fdiffids) $fdiffs
2005 }
2067 }
2006 if {[info exists findids] && $fdiffids eq $findids} {
2068 if {[info exists findids] && $fdiffids eq $findids} {
2007 unset findids
2069 unset findids
2008 findcont $fdiffids
2070 findcont $fdiffids
2009 }
2071 }
2010 }
2072 }
2011 }
2073 }
2012
2074
2013 proc findcont {ids} {
2075 proc findcont {ids} {
2014 global findids treediffs parents nparents
2076 global findids treediffs parents nparents
2015 global ffileline findstartline finddidsel
2077 global ffileline findstartline finddidsel
2016 global lineid numcommits matchinglines findinprogress
2078 global lineid numcommits matchinglines findinprogress
2017 global findmergefiles
2079 global findmergefiles
2018
2080
2019 set id [lindex $ids 0]
2081 set id [lindex $ids 0]
2020 set p [lindex $ids 1]
2082 set p [lindex $ids 1]
2021 set pi [lsearch -exact $parents($id) $p]
2083 set pi [lsearch -exact $parents($id) $p]
2022 set l $ffileline
2084 set l $ffileline
2023 while 1 {
2085 while 1 {
2024 if {$findmergefiles || $nparents($id) == 1} {
2086 if {$findmergefiles || $nparents($id) == 1} {
2025 if {![info exists treediffs($ids)]} {
2087 if {![info exists treediffs($ids)]} {
2026 set findids $ids
2088 set findids $ids
2027 set ffileline $l
2089 set ffileline $l
2028 return
2090 return
2029 }
2091 }
2030 set doesmatch 0
2092 set doesmatch 0
2031 foreach f $treediffs($ids) {
2093 foreach f $treediffs($ids) {
2032 set x [findmatches $f]
2094 set x [findmatches $f]
2033 if {$x != {}} {
2095 if {$x != {}} {
2034 set doesmatch 1
2096 set doesmatch 1
2035 break
2097 break
2036 }
2098 }
2037 }
2099 }
2038 if {$doesmatch} {
2100 if {$doesmatch} {
2039 insertmatch $l $id
2101 insertmatch $l $id
2040 set pi $nparents($id)
2102 set pi $nparents($id)
2041 }
2103 }
2042 } else {
2104 } else {
2043 set pi $nparents($id)
2105 set pi $nparents($id)
2044 }
2106 }
2045 if {[incr pi] >= $nparents($id)} {
2107 if {[incr pi] >= $nparents($id)} {
2046 set pi 0
2108 set pi 0
2047 if {[incr l] >= $numcommits} {
2109 if {[incr l] >= $numcommits} {
2048 set l 0
2110 set l 0
2049 }
2111 }
2050 if {$l == $findstartline} break
2112 if {$l == $findstartline} break
2051 set id $lineid($l)
2113 set id $lineid($l)
2052 }
2114 }
2053 set p [lindex $parents($id) $pi]
2115 set p [lindex $parents($id) $pi]
2054 set ids [list $id $p]
2116 set ids [list $id $p]
2055 }
2117 }
2056 stopfindproc
2118 stopfindproc
2057 if {!$finddidsel} {
2119 if {!$finddidsel} {
2058 bell
2120 bell
2059 }
2121 }
2060 }
2122 }
2061
2123
2062 # mark a commit as matching by putting a yellow background
2124 # mark a commit as matching by putting a yellow background
2063 # behind the headline
2125 # behind the headline
2064 proc markheadline {l id} {
2126 proc markheadline {l id} {
2065 global canv mainfont linehtag commitinfo
2127 global canv mainfont linehtag commitinfo
2066
2128
2067 set bbox [$canv bbox $linehtag($l)]
2129 set bbox [$canv bbox $linehtag($l)]
2068 set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
2130 set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
2069 $canv lower $t
2131 $canv lower $t
2070 }
2132 }
2071
2133
2072 # mark the bits of a headline, author or date that match a find string
2134 # mark the bits of a headline, author or date that match a find string
2073 proc markmatches {canv l str tag matches font} {
2135 proc markmatches {canv l str tag matches font} {
2074 set bbox [$canv bbox $tag]
2136 set bbox [$canv bbox $tag]
2075 set x0 [lindex $bbox 0]
2137 set x0 [lindex $bbox 0]
2076 set y0 [lindex $bbox 1]
2138 set y0 [lindex $bbox 1]
2077 set y1 [lindex $bbox 3]
2139 set y1 [lindex $bbox 3]
2078 foreach match $matches {
2140 foreach match $matches {
2079 set start [lindex $match 0]
2141 set start [lindex $match 0]
2080 set end [lindex $match 1]
2142 set end [lindex $match 1]
2081 if {$start > $end} continue
2143 if {$start > $end} continue
2082 set xoff [font measure $font [string range $str 0 [expr $start-1]]]
2144 set xoff [font measure $font [string range $str 0 [expr $start-1]]]
2083 set xlen [font measure $font [string range $str 0 [expr $end]]]
2145 set xlen [font measure $font [string range $str 0 [expr $end]]]
2084 set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \
2146 set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \
2085 -outline {} -tags matches -fill yellow]
2147 -outline {} -tags matches -fill yellow]
2086 $canv lower $t
2148 $canv lower $t
2087 }
2149 }
2088 }
2150 }
2089
2151
2090 proc unmarkmatches {} {
2152 proc unmarkmatches {} {
2091 global matchinglines findids
2153 global matchinglines findids
2092 allcanvs delete matches
2154 allcanvs delete matches
2093 catch {unset matchinglines}
2155 catch {unset matchinglines}
2094 catch {unset findids}
2156 catch {unset findids}
2095 }
2157 }
2096
2158
2097 proc selcanvline {w x y} {
2159 proc selcanvline {w x y} {
2098 global canv canvy0 ctext linespc
2160 global canv canvy0 ctext linespc
2099 global lineid linehtag linentag linedtag rowtextx
2161 global lineid linehtag linentag linedtag rowtextx
2100 set ymax [lindex [$canv cget -scrollregion] 3]
2162 set ymax [lindex [$canv cget -scrollregion] 3]
2101 if {$ymax == {}} return
2163 if {$ymax == {}} return
2102 set yfrac [lindex [$canv yview] 0]
2164 set yfrac [lindex [$canv yview] 0]
2103 set y [expr {$y + $yfrac * $ymax}]
2165 set y [expr {$y + $yfrac * $ymax}]
2104 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
2166 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
2105 if {$l < 0} {
2167 if {$l < 0} {
2106 set l 0
2168 set l 0
2107 }
2169 }
2108 if {$w eq $canv} {
2170 if {$w eq $canv} {
2109 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
2171 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
2110 }
2172 }
2111 unmarkmatches
2173 unmarkmatches
2112 selectline $l 1
2174 selectline $l 1
2113 }
2175 }
2114
2176
2115 proc commit_descriptor {p} {
2177 proc commit_descriptor {p} {
2116 global commitinfo
2178 global commitinfo
2117 set l "..."
2179 set l "..."
2118 if {[info exists commitinfo($p)]} {
2180 if {[info exists commitinfo($p)]} {
2119 set l [lindex $commitinfo($p) 0]
2181 set l [lindex $commitinfo($p) 0]
2120 set r [lindex $commitinfo($p) 6]
2182 set r [lindex $commitinfo($p) 6]
2121 }
2183 }
2122 return "$r:$p ($l)"
2184 return "$r:$p ($l)"
2123 }
2185 }
2124
2186
2125 # append some text to the ctext widget, and make any SHA1 ID
2187 # append some text to the ctext widget, and make any SHA1 ID
2126 # that we know about be a clickable link.
2188 # that we know about be a clickable link.
2127 proc appendwithlinks {text} {
2189 proc appendwithlinks {text} {
2128 global ctext idline linknum
2190 global ctext idline linknum
2129
2191
2130 set start [$ctext index "end - 1c"]
2192 set start [$ctext index "end - 1c"]
2131 $ctext insert end $text
2193 $ctext insert end $text
2132 $ctext insert end "\n"
2194 $ctext insert end "\n"
2133 set links [regexp -indices -all -inline {[0-9a-f]{12}} $text]
2195 set links [regexp -indices -all -inline {[0-9a-f]{12}} $text]
2134 foreach l $links {
2196 foreach l $links {
2135 set s [lindex $l 0]
2197 set s [lindex $l 0]
2136 set e [lindex $l 1]
2198 set e [lindex $l 1]
2137 set linkid [string range $text $s $e]
2199 set linkid [string range $text $s $e]
2138 if {![info exists idline($linkid)]} continue
2200 if {![info exists idline($linkid)]} continue
2139 incr e
2201 incr e
2140 $ctext tag add link "$start + $s c" "$start + $e c"
2202 $ctext tag add link "$start + $s c" "$start + $e c"
2141 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
2203 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
2142 $ctext tag bind link$linknum <1> [list selectline $idline($linkid) 1]
2204 $ctext tag bind link$linknum <1> [list selectline $idline($linkid) 1]
2143 incr linknum
2205 incr linknum
2144 }
2206 }
2145 $ctext tag conf link -foreground blue -underline 1
2207 $ctext tag conf link -foreground blue -underline 1
2146 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
2208 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
2147 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
2209 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
2148 }
2210 }
2149
2211
2150 proc selectline {l isnew} {
2212 proc selectline {l isnew} {
2151 global canv canv2 canv3 ctext commitinfo selectedline
2213 global canv canv2 canv3 ctext commitinfo selectedline
2152 global lineid linehtag linentag linedtag
2214 global lineid linehtag linentag linedtag
2153 global canvy0 linespc parents nparents children
2215 global canvy0 linespc parents nparents children
2154 global cflist currentid sha1entry
2216 global cflist currentid sha1entry
2155 global commentend idtags idline linknum
2217 global commentend idtags idline linknum
2156
2218
2157 $canv delete hover
2219 $canv delete hover
2158 normalline
2220 normalline
2159 if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
2221 if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
2160 $canv delete secsel
2222 $canv delete secsel
2161 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
2223 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
2162 -tags secsel -fill [$canv cget -selectbackground]]
2224 -tags secsel -fill [$canv cget -selectbackground]]
2163 $canv lower $t
2225 $canv lower $t
2164 $canv2 delete secsel
2226 $canv2 delete secsel
2165 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
2227 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
2166 -tags secsel -fill [$canv2 cget -selectbackground]]
2228 -tags secsel -fill [$canv2 cget -selectbackground]]
2167 $canv2 lower $t
2229 $canv2 lower $t
2168 $canv3 delete secsel
2230 $canv3 delete secsel
2169 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
2231 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
2170 -tags secsel -fill [$canv3 cget -selectbackground]]
2232 -tags secsel -fill [$canv3 cget -selectbackground]]
2171 $canv3 lower $t
2233 $canv3 lower $t
2172 set y [expr {$canvy0 + $l * $linespc}]
2234 set y [expr {$canvy0 + $l * $linespc}]
2173 set ymax [lindex [$canv cget -scrollregion] 3]
2235 set ymax [lindex [$canv cget -scrollregion] 3]
2174 set ytop [expr {$y - $linespc - 1}]
2236 set ytop [expr {$y - $linespc - 1}]
2175 set ybot [expr {$y + $linespc + 1}]
2237 set ybot [expr {$y + $linespc + 1}]
2176 set wnow [$canv yview]
2238 set wnow [$canv yview]
2177 set wtop [expr [lindex $wnow 0] * $ymax]
2239 set wtop [expr [lindex $wnow 0] * $ymax]
2178 set wbot [expr [lindex $wnow 1] * $ymax]
2240 set wbot [expr [lindex $wnow 1] * $ymax]
2179 set wh [expr {$wbot - $wtop}]
2241 set wh [expr {$wbot - $wtop}]
2180 set newtop $wtop
2242 set newtop $wtop
2181 if {$ytop < $wtop} {
2243 if {$ytop < $wtop} {
2182 if {$ybot < $wtop} {
2244 if {$ybot < $wtop} {
2183 set newtop [expr {$y - $wh / 2.0}]
2245 set newtop [expr {$y - $wh / 2.0}]
2184 } else {
2246 } else {
2185 set newtop $ytop
2247 set newtop $ytop
2186 if {$newtop > $wtop - $linespc} {
2248 if {$newtop > $wtop - $linespc} {
2187 set newtop [expr {$wtop - $linespc}]
2249 set newtop [expr {$wtop - $linespc}]
2188 }
2250 }
2189 }
2251 }
2190 } elseif {$ybot > $wbot} {
2252 } elseif {$ybot > $wbot} {
2191 if {$ytop > $wbot} {
2253 if {$ytop > $wbot} {
2192 set newtop [expr {$y - $wh / 2.0}]
2254 set newtop [expr {$y - $wh / 2.0}]
2193 } else {
2255 } else {
2194 set newtop [expr {$ybot - $wh}]
2256 set newtop [expr {$ybot - $wh}]
2195 if {$newtop < $wtop + $linespc} {
2257 if {$newtop < $wtop + $linespc} {
2196 set newtop [expr {$wtop + $linespc}]
2258 set newtop [expr {$wtop + $linespc}]
2197 }
2259 }
2198 }
2260 }
2199 }
2261 }
2200 if {$newtop != $wtop} {
2262 if {$newtop != $wtop} {
2201 if {$newtop < 0} {
2263 if {$newtop < 0} {
2202 set newtop 0
2264 set newtop 0
2203 }
2265 }
2204 allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
2266 allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
2205 }
2267 }
2206
2268
2207 if {$isnew} {
2269 if {$isnew} {
2208 addtohistory [list selectline $l 0]
2270 addtohistory [list selectline $l 0]
2209 }
2271 }
2210
2272
2211 set selectedline $l
2273 set selectedline $l
2212
2274
2213 set id $lineid($l)
2275 set id $lineid($l)
2214 set currentid $id
2276 set currentid $id
2215 $sha1entry delete 0 end
2277 $sha1entry delete 0 end
2216 $sha1entry insert 0 $id
2278 $sha1entry insert 0 $id
2217 $sha1entry selection from 0
2279 $sha1entry selection from 0
2218 $sha1entry selection to end
2280 $sha1entry selection to end
2219
2281
2220 $ctext conf -state normal
2282 $ctext conf -state normal
2221 $ctext delete 0.0 end
2283 $ctext delete 0.0 end
2222 set linknum 0
2284 set linknum 0
2223 $ctext mark set fmark.0 0.0
2285 $ctext mark set fmark.0 0.0
2224 $ctext mark gravity fmark.0 left
2286 $ctext mark gravity fmark.0 left
2225 set info $commitinfo($id)
2287 set info $commitinfo($id)
2226 $ctext insert end "Revision: [lindex $info 6]\n"
2288 $ctext insert end "Revision: [lindex $info 6]\n"
2227 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n"
2289 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n"
2228 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n"
2290 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n"
2229 if {[info exists idtags($id)]} {
2291 if {[info exists idtags($id)]} {
2230 $ctext insert end "Tags:"
2292 $ctext insert end "Tags:"
2231 foreach tag $idtags($id) {
2293 foreach tag $idtags($id) {
2232 $ctext insert end " $tag"
2294 $ctext insert end " $tag"
2233 }
2295 }
2234 $ctext insert end "\n"
2296 $ctext insert end "\n"
2235 }
2297 }
2236
2298
2237 set comment {}
2299 set comment {}
2238 if {[info exists parents($id)]} {
2300 if {[info exists parents($id)]} {
2239 foreach p $parents($id) {
2301 foreach p $parents($id) {
2240 append comment "Parent: [commit_descriptor $p]\n"
2302 append comment "Parent: [commit_descriptor $p]\n"
2241 }
2303 }
2242 }
2304 }
2243 if {[info exists children($id)]} {
2305 if {[info exists children($id)]} {
2244 foreach c $children($id) {
2306 foreach c $children($id) {
2245 append comment "Child: [commit_descriptor $c]\n"
2307 append comment "Child: [commit_descriptor $c]\n"
2246 }
2308 }
2247 }
2309 }
2248 append comment "\n"
2310 append comment "\n"
2249 append comment [lindex $info 5]
2311 append comment [lindex $info 5]
2250
2312
2251 # make anything that looks like a SHA1 ID be a clickable link
2313 # make anything that looks like a SHA1 ID be a clickable link
2252 appendwithlinks $comment
2314 appendwithlinks $comment
2253
2315
2254 $ctext tag delete Comments
2316 $ctext tag delete Comments
2255 $ctext tag remove found 1.0 end
2317 $ctext tag remove found 1.0 end
2256 $ctext conf -state disabled
2318 $ctext conf -state disabled
2257 set commentend [$ctext index "end - 1c"]
2319 set commentend [$ctext index "end - 1c"]
2258
2320
2259 $cflist delete 0 end
2321 $cflist delete 0 end
2260 $cflist insert end "Comments"
2322 $cflist insert end "Comments"
2261 if {$nparents($id) == 1} {
2323 if {$nparents($id) == 1} {
2262 startdiff [concat $id $parents($id)]
2324 startdiff [concat $id $parents($id)]
2263 } elseif {$nparents($id) > 1} {
2325 } elseif {$nparents($id) > 1} {
2264 mergediff $id
2326 mergediff $id
2265 }
2327 }
2266 }
2328 }
2267
2329
2268 proc selnextline {dir} {
2330 proc selnextline {dir} {
2269 global selectedline
2331 global selectedline
2270 if {![info exists selectedline]} return
2332 if {![info exists selectedline]} return
2271 set l [expr $selectedline + $dir]
2333 set l [expr $selectedline + $dir]
2272 unmarkmatches
2334 unmarkmatches
2273 selectline $l 1
2335 selectline $l 1
2274 }
2336 }
2275
2337
2276 proc unselectline {} {
2338 proc unselectline {} {
2277 global selectedline
2339 global selectedline
2278
2340
2279 catch {unset selectedline}
2341 catch {unset selectedline}
2280 allcanvs delete secsel
2342 allcanvs delete secsel
2281 }
2343 }
2282
2344
2283 proc addtohistory {cmd} {
2345 proc addtohistory {cmd} {
2284 global history historyindex
2346 global history historyindex
2285
2347
2286 if {$historyindex > 0
2348 if {$historyindex > 0
2287 && [lindex $history [expr {$historyindex - 1}]] == $cmd} {
2349 && [lindex $history [expr {$historyindex - 1}]] == $cmd} {
2288 return
2350 return
2289 }
2351 }
2290
2352
2291 if {$historyindex < [llength $history]} {
2353 if {$historyindex < [llength $history]} {
2292 set history [lreplace $history $historyindex end $cmd]
2354 set history [lreplace $history $historyindex end $cmd]
2293 } else {
2355 } else {
2294 lappend history $cmd
2356 lappend history $cmd
2295 }
2357 }
2296 incr historyindex
2358 incr historyindex
2297 if {$historyindex > 1} {
2359 if {$historyindex > 1} {
2298 .ctop.top.bar.leftbut conf -state normal
2360 .ctop.top.bar.leftbut conf -state normal
2299 } else {
2361 } else {
2300 .ctop.top.bar.leftbut conf -state disabled
2362 .ctop.top.bar.leftbut conf -state disabled
2301 }
2363 }
2302 .ctop.top.bar.rightbut conf -state disabled
2364 .ctop.top.bar.rightbut conf -state disabled
2303 }
2365 }
2304
2366
2305 proc goback {} {
2367 proc goback {} {
2306 global history historyindex
2368 global history historyindex
2307
2369
2308 if {$historyindex > 1} {
2370 if {$historyindex > 1} {
2309 incr historyindex -1
2371 incr historyindex -1
2310 set cmd [lindex $history [expr {$historyindex - 1}]]
2372 set cmd [lindex $history [expr {$historyindex - 1}]]
2311 eval $cmd
2373 eval $cmd
2312 .ctop.top.bar.rightbut conf -state normal
2374 .ctop.top.bar.rightbut conf -state normal
2313 }
2375 }
2314 if {$historyindex <= 1} {
2376 if {$historyindex <= 1} {
2315 .ctop.top.bar.leftbut conf -state disabled
2377 .ctop.top.bar.leftbut conf -state disabled
2316 }
2378 }
2317 }
2379 }
2318
2380
2319 proc goforw {} {
2381 proc goforw {} {
2320 global history historyindex
2382 global history historyindex
2321
2383
2322 if {$historyindex < [llength $history]} {
2384 if {$historyindex < [llength $history]} {
2323 set cmd [lindex $history $historyindex]
2385 set cmd [lindex $history $historyindex]
2324 incr historyindex
2386 incr historyindex
2325 eval $cmd
2387 eval $cmd
2326 .ctop.top.bar.leftbut conf -state normal
2388 .ctop.top.bar.leftbut conf -state normal
2327 }
2389 }
2328 if {$historyindex >= [llength $history]} {
2390 if {$historyindex >= [llength $history]} {
2329 .ctop.top.bar.rightbut conf -state disabled
2391 .ctop.top.bar.rightbut conf -state disabled
2330 }
2392 }
2331 }
2393 }
2332
2394
2333 proc mergediff {id} {
2395 proc mergediff {id} {
2334 global parents diffmergeid diffmergegca mergefilelist diffpindex
2396 global parents diffmergeid diffmergegca mergefilelist diffpindex
2335
2397
2336 set diffmergeid $id
2398 set diffmergeid $id
2337 set diffpindex -1
2399 set diffpindex -1
2338 set diffmergegca [findgca $parents($id)]
2400 set diffmergegca [findgca $parents($id)]
2339 if {[info exists mergefilelist($id)]} {
2401 if {[info exists mergefilelist($id)]} {
2340 if {$mergefilelist($id) ne {}} {
2402 if {$mergefilelist($id) ne {}} {
2341 showmergediff
2403 showmergediff
2342 }
2404 }
2343 } else {
2405 } else {
2344 contmergediff {}
2406 contmergediff {}
2345 }
2407 }
2346 }
2408 }
2347
2409
2348 proc findgca {ids} {
2410 proc findgca {ids} {
2349 global env
2411 global env
2350 set gca {}
2412 set gca {}
2351 foreach id $ids {
2413 foreach id $ids {
2352 if {$gca eq {}} {
2414 if {$gca eq {}} {
2353 set gca $id
2415 set gca $id
2354 } else {
2416 } else {
2355 if {[catch {
2417 if {[catch {
2356 set gca [exec $env(HG) --config ui.report_untrusted=false debug-merge-base $gca $id]
2418 set gca [exec $env(HG) --config ui.report_untrusted=false debug-merge-base $gca $id]
2357 } err]} {
2419 } err]} {
2358 return {}
2420 return {}
2359 }
2421 }
2360 }
2422 }
2361 }
2423 }
2362 return $gca
2424 return $gca
2363 }
2425 }
2364
2426
2365 proc contmergediff {ids} {
2427 proc contmergediff {ids} {
2366 global diffmergeid diffpindex parents nparents diffmergegca
2428 global diffmergeid diffpindex parents nparents diffmergegca
2367 global treediffs mergefilelist diffids treepending
2429 global treediffs mergefilelist diffids treepending
2368
2430
2369 # diff the child against each of the parents, and diff
2431 # diff the child against each of the parents, and diff
2370 # each of the parents against the GCA.
2432 # each of the parents against the GCA.
2371 while 1 {
2433 while 1 {
2372 if {[lindex $ids 0] == $diffmergeid && $diffmergegca ne {}} {
2434 if {[lindex $ids 0] == $diffmergeid && $diffmergegca ne {}} {
2373 set ids [list [lindex $ids 1] $diffmergegca]
2435 set ids [list [lindex $ids 1] $diffmergegca]
2374 } else {
2436 } else {
2375 if {[incr diffpindex] >= $nparents($diffmergeid)} break
2437 if {[incr diffpindex] >= $nparents($diffmergeid)} break
2376 set p [lindex $parents($diffmergeid) $diffpindex]
2438 set p [lindex $parents($diffmergeid) $diffpindex]
2377 set ids [list $diffmergeid $p]
2439 set ids [list $diffmergeid $p]
2378 }
2440 }
2379 if {![info exists treediffs($ids)]} {
2441 if {![info exists treediffs($ids)]} {
2380 set diffids $ids
2442 set diffids $ids
2381 if {![info exists treepending]} {
2443 if {![info exists treepending]} {
2382 gettreediffs $ids
2444 gettreediffs $ids
2383 }
2445 }
2384 return
2446 return
2385 }
2447 }
2386 }
2448 }
2387
2449
2388 # If a file in some parent is different from the child and also
2450 # If a file in some parent is different from the child and also
2389 # different from the GCA, then it's interesting.
2451 # different from the GCA, then it's interesting.
2390 # If we don't have a GCA, then a file is interesting if it is
2452 # If we don't have a GCA, then a file is interesting if it is
2391 # different from the child in all the parents.
2453 # different from the child in all the parents.
2392 if {$diffmergegca ne {}} {
2454 if {$diffmergegca ne {}} {
2393 set files {}
2455 set files {}
2394 foreach p $parents($diffmergeid) {
2456 foreach p $parents($diffmergeid) {
2395 set gcadiffs $treediffs([list $p $diffmergegca])
2457 set gcadiffs $treediffs([list $p $diffmergegca])
2396 foreach f $treediffs([list $diffmergeid $p]) {
2458 foreach f $treediffs([list $diffmergeid $p]) {
2397 if {[lsearch -exact $files $f] < 0
2459 if {[lsearch -exact $files $f] < 0
2398 && [lsearch -exact $gcadiffs $f] >= 0} {
2460 && [lsearch -exact $gcadiffs $f] >= 0} {
2399 lappend files $f
2461 lappend files $f
2400 }
2462 }
2401 }
2463 }
2402 }
2464 }
2403 set files [lsort $files]
2465 set files [lsort $files]
2404 } else {
2466 } else {
2405 set p [lindex $parents($diffmergeid) 0]
2467 set p [lindex $parents($diffmergeid) 0]
2406 set files $treediffs([list $diffmergeid $p])
2468 set files $treediffs([list $diffmergeid $p])
2407 for {set i 1} {$i < $nparents($diffmergeid) && $files ne {}} {incr i} {
2469 for {set i 1} {$i < $nparents($diffmergeid) && $files ne {}} {incr i} {
2408 set p [lindex $parents($diffmergeid) $i]
2470 set p [lindex $parents($diffmergeid) $i]
2409 set df $treediffs([list $diffmergeid $p])
2471 set df $treediffs([list $diffmergeid $p])
2410 set nf {}
2472 set nf {}
2411 foreach f $files {
2473 foreach f $files {
2412 if {[lsearch -exact $df $f] >= 0} {
2474 if {[lsearch -exact $df $f] >= 0} {
2413 lappend nf $f
2475 lappend nf $f
2414 }
2476 }
2415 }
2477 }
2416 set files $nf
2478 set files $nf
2417 }
2479 }
2418 }
2480 }
2419
2481
2420 set mergefilelist($diffmergeid) $files
2482 set mergefilelist($diffmergeid) $files
2421 if {$files ne {}} {
2483 if {$files ne {}} {
2422 showmergediff
2484 showmergediff
2423 }
2485 }
2424 }
2486 }
2425
2487
2426 proc showmergediff {} {
2488 proc showmergediff {} {
2427 global cflist diffmergeid mergefilelist parents
2489 global cflist diffmergeid mergefilelist parents
2428 global diffopts diffinhunk currentfile currenthunk filelines
2490 global diffopts diffinhunk currentfile currenthunk filelines
2429 global diffblocked groupfilelast mergefds groupfilenum grouphunks
2491 global diffblocked groupfilelast mergefds groupfilenum grouphunks
2430 global env
2492 global env
2431
2493
2432 set files $mergefilelist($diffmergeid)
2494 set files $mergefilelist($diffmergeid)
2433 foreach f $files {
2495 foreach f $files {
2434 $cflist insert end $f
2496 $cflist insert end $f
2435 }
2497 }
2436 set env(GIT_DIFF_OPTS) $diffopts
2498 set env(GIT_DIFF_OPTS) $diffopts
2437 set flist {}
2499 set flist {}
2438 catch {unset currentfile}
2500 catch {unset currentfile}
2439 catch {unset currenthunk}
2501 catch {unset currenthunk}
2440 catch {unset filelines}
2502 catch {unset filelines}
2441 catch {unset groupfilenum}
2503 catch {unset groupfilenum}
2442 catch {unset grouphunks}
2504 catch {unset grouphunks}
2443 set groupfilelast -1
2505 set groupfilelast -1
2444 foreach p $parents($diffmergeid) {
2506 foreach p $parents($diffmergeid) {
2445 set cmd [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -p $p $diffmergeid]
2507 set cmd [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -p $p $diffmergeid]
2446 set cmd [concat $cmd $mergefilelist($diffmergeid)]
2508 set cmd [concat $cmd $mergefilelist($diffmergeid)]
2447 if {[catch {set f [open $cmd r]} err]} {
2509 if {[catch {set f [open $cmd r]} err]} {
2448 error_popup "Error getting diffs: $err"
2510 error_popup "Error getting diffs: $err"
2449 foreach f $flist {
2511 foreach f $flist {
2450 catch {close $f}
2512 catch {close $f}
2451 }
2513 }
2452 return
2514 return
2453 }
2515 }
2454 lappend flist $f
2516 lappend flist $f
2455 set ids [list $diffmergeid $p]
2517 set ids [list $diffmergeid $p]
2456 set mergefds($ids) $f
2518 set mergefds($ids) $f
2457 set diffinhunk($ids) 0
2519 set diffinhunk($ids) 0
2458 set diffblocked($ids) 0
2520 set diffblocked($ids) 0
2459 fconfigure $f -blocking 0
2521 fconfigure $f -blocking 0
2460 fileevent $f readable [list getmergediffline $f $ids $diffmergeid]
2522 fileevent $f readable [list getmergediffline $f $ids $diffmergeid]
2461 }
2523 }
2462 }
2524 }
2463
2525
2464 proc getmergediffline {f ids id} {
2526 proc getmergediffline {f ids id} {
2465 global diffmergeid diffinhunk diffoldlines diffnewlines
2527 global diffmergeid diffinhunk diffoldlines diffnewlines
2466 global currentfile currenthunk
2528 global currentfile currenthunk
2467 global diffoldstart diffnewstart diffoldlno diffnewlno
2529 global diffoldstart diffnewstart diffoldlno diffnewlno
2468 global diffblocked mergefilelist
2530 global diffblocked mergefilelist
2469 global noldlines nnewlines difflcounts filelines
2531 global noldlines nnewlines difflcounts filelines
2470
2532
2471 set n [gets $f line]
2533 set n [gets $f line]
2472 if {$n < 0} {
2534 if {$n < 0} {
2473 if {![eof $f]} return
2535 if {![eof $f]} return
2474 }
2536 }
2475
2537
2476 if {!([info exists diffmergeid] && $diffmergeid == $id)} {
2538 if {!([info exists diffmergeid] && $diffmergeid == $id)} {
2477 if {$n < 0} {
2539 if {$n < 0} {
2478 close $f
2540 close $f
2479 }
2541 }
2480 return
2542 return
2481 }
2543 }
2482
2544
2483 if {$diffinhunk($ids) != 0} {
2545 if {$diffinhunk($ids) != 0} {
2484 set fi $currentfile($ids)
2546 set fi $currentfile($ids)
2485 if {$n > 0 && [regexp {^[-+ \\]} $line match]} {
2547 if {$n > 0 && [regexp {^[-+ \\]} $line match]} {
2486 # continuing an existing hunk
2548 # continuing an existing hunk
2487 set line [string range $line 1 end]
2549 set line [string range $line 1 end]
2488 set p [lindex $ids 1]
2550 set p [lindex $ids 1]
2489 if {$match eq "-" || $match eq " "} {
2551 if {$match eq "-" || $match eq " "} {
2490 set filelines($p,$fi,$diffoldlno($ids)) $line
2552 set filelines($p,$fi,$diffoldlno($ids)) $line
2491 incr diffoldlno($ids)
2553 incr diffoldlno($ids)
2492 }
2554 }
2493 if {$match eq "+" || $match eq " "} {
2555 if {$match eq "+" || $match eq " "} {
2494 set filelines($id,$fi,$diffnewlno($ids)) $line
2556 set filelines($id,$fi,$diffnewlno($ids)) $line
2495 incr diffnewlno($ids)
2557 incr diffnewlno($ids)
2496 }
2558 }
2497 if {$match eq " "} {
2559 if {$match eq " "} {
2498 if {$diffinhunk($ids) == 2} {
2560 if {$diffinhunk($ids) == 2} {
2499 lappend difflcounts($ids) \
2561 lappend difflcounts($ids) \
2500 [list $noldlines($ids) $nnewlines($ids)]
2562 [list $noldlines($ids) $nnewlines($ids)]
2501 set noldlines($ids) 0
2563 set noldlines($ids) 0
2502 set diffinhunk($ids) 1
2564 set diffinhunk($ids) 1
2503 }
2565 }
2504 incr noldlines($ids)
2566 incr noldlines($ids)
2505 } elseif {$match eq "-" || $match eq "+"} {
2567 } elseif {$match eq "-" || $match eq "+"} {
2506 if {$diffinhunk($ids) == 1} {
2568 if {$diffinhunk($ids) == 1} {
2507 lappend difflcounts($ids) [list $noldlines($ids)]
2569 lappend difflcounts($ids) [list $noldlines($ids)]
2508 set noldlines($ids) 0
2570 set noldlines($ids) 0
2509 set nnewlines($ids) 0
2571 set nnewlines($ids) 0
2510 set diffinhunk($ids) 2
2572 set diffinhunk($ids) 2
2511 }
2573 }
2512 if {$match eq "-"} {
2574 if {$match eq "-"} {
2513 incr noldlines($ids)
2575 incr noldlines($ids)
2514 } else {
2576 } else {
2515 incr nnewlines($ids)
2577 incr nnewlines($ids)
2516 }
2578 }
2517 }
2579 }
2518 # and if it's \ No newline at end of line, then what?
2580 # and if it's \ No newline at end of line, then what?
2519 return
2581 return
2520 }
2582 }
2521 # end of a hunk
2583 # end of a hunk
2522 if {$diffinhunk($ids) == 1 && $noldlines($ids) != 0} {
2584 if {$diffinhunk($ids) == 1 && $noldlines($ids) != 0} {
2523 lappend difflcounts($ids) [list $noldlines($ids)]
2585 lappend difflcounts($ids) [list $noldlines($ids)]
2524 } elseif {$diffinhunk($ids) == 2
2586 } elseif {$diffinhunk($ids) == 2
2525 && ($noldlines($ids) != 0 || $nnewlines($ids) != 0)} {
2587 && ($noldlines($ids) != 0 || $nnewlines($ids) != 0)} {
2526 lappend difflcounts($ids) [list $noldlines($ids) $nnewlines($ids)]
2588 lappend difflcounts($ids) [list $noldlines($ids) $nnewlines($ids)]
2527 }
2589 }
2528 set currenthunk($ids) [list $currentfile($ids) \
2590 set currenthunk($ids) [list $currentfile($ids) \
2529 $diffoldstart($ids) $diffnewstart($ids) \
2591 $diffoldstart($ids) $diffnewstart($ids) \
2530 $diffoldlno($ids) $diffnewlno($ids) \
2592 $diffoldlno($ids) $diffnewlno($ids) \
2531 $difflcounts($ids)]
2593 $difflcounts($ids)]
2532 set diffinhunk($ids) 0
2594 set diffinhunk($ids) 0
2533 # -1 = need to block, 0 = unblocked, 1 = is blocked
2595 # -1 = need to block, 0 = unblocked, 1 = is blocked
2534 set diffblocked($ids) -1
2596 set diffblocked($ids) -1
2535 processhunks
2597 processhunks
2536 if {$diffblocked($ids) == -1} {
2598 if {$diffblocked($ids) == -1} {
2537 fileevent $f readable {}
2599 fileevent $f readable {}
2538 set diffblocked($ids) 1
2600 set diffblocked($ids) 1
2539 }
2601 }
2540 }
2602 }
2541
2603
2542 if {$n < 0} {
2604 if {$n < 0} {
2543 # eof
2605 # eof
2544 if {!$diffblocked($ids)} {
2606 if {!$diffblocked($ids)} {
2545 close $f
2607 close $f
2546 set currentfile($ids) [llength $mergefilelist($diffmergeid)]
2608 set currentfile($ids) [llength $mergefilelist($diffmergeid)]
2547 set currenthunk($ids) [list $currentfile($ids) 0 0 0 0 {}]
2609 set currenthunk($ids) [list $currentfile($ids) 0 0 0 0 {}]
2548 processhunks
2610 processhunks
2549 }
2611 }
2550 } elseif {[regexp {^diff --git a/(.*) b/} $line match fname]} {
2612 } elseif {[regexp {^diff --git a/(.*) b/} $line match fname]} {
2551 # start of a new file
2613 # start of a new file
2552 set currentfile($ids) \
2614 set currentfile($ids) \
2553 [lsearch -exact $mergefilelist($diffmergeid) $fname]
2615 [lsearch -exact $mergefilelist($diffmergeid) $fname]
2554 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
2616 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
2555 $line match f1l f1c f2l f2c rest]} {
2617 $line match f1l f1c f2l f2c rest]} {
2556 if {[info exists currentfile($ids)] && $currentfile($ids) >= 0} {
2618 if {[info exists currentfile($ids)] && $currentfile($ids) >= 0} {
2557 # start of a new hunk
2619 # start of a new hunk
2558 if {$f1l == 0 && $f1c == 0} {
2620 if {$f1l == 0 && $f1c == 0} {
2559 set f1l 1
2621 set f1l 1
2560 }
2622 }
2561 if {$f2l == 0 && $f2c == 0} {
2623 if {$f2l == 0 && $f2c == 0} {
2562 set f2l 1
2624 set f2l 1
2563 }
2625 }
2564 set diffinhunk($ids) 1
2626 set diffinhunk($ids) 1
2565 set diffoldstart($ids) $f1l
2627 set diffoldstart($ids) $f1l
2566 set diffnewstart($ids) $f2l
2628 set diffnewstart($ids) $f2l
2567 set diffoldlno($ids) $f1l
2629 set diffoldlno($ids) $f1l
2568 set diffnewlno($ids) $f2l
2630 set diffnewlno($ids) $f2l
2569 set difflcounts($ids) {}
2631 set difflcounts($ids) {}
2570 set noldlines($ids) 0
2632 set noldlines($ids) 0
2571 set nnewlines($ids) 0
2633 set nnewlines($ids) 0
2572 }
2634 }
2573 }
2635 }
2574 }
2636 }
2575
2637
2576 proc processhunks {} {
2638 proc processhunks {} {
2577 global diffmergeid parents nparents currenthunk
2639 global diffmergeid parents nparents currenthunk
2578 global mergefilelist diffblocked mergefds
2640 global mergefilelist diffblocked mergefds
2579 global grouphunks grouplinestart grouplineend groupfilenum
2641 global grouphunks grouplinestart grouplineend groupfilenum
2580
2642
2581 set nfiles [llength $mergefilelist($diffmergeid)]
2643 set nfiles [llength $mergefilelist($diffmergeid)]
2582 while 1 {
2644 while 1 {
2583 set fi $nfiles
2645 set fi $nfiles
2584 set lno 0
2646 set lno 0
2585 # look for the earliest hunk
2647 # look for the earliest hunk
2586 foreach p $parents($diffmergeid) {
2648 foreach p $parents($diffmergeid) {
2587 set ids [list $diffmergeid $p]
2649 set ids [list $diffmergeid $p]
2588 if {![info exists currenthunk($ids)]} return
2650 if {![info exists currenthunk($ids)]} return
2589 set i [lindex $currenthunk($ids) 0]
2651 set i [lindex $currenthunk($ids) 0]
2590 set l [lindex $currenthunk($ids) 2]
2652 set l [lindex $currenthunk($ids) 2]
2591 if {$i < $fi || ($i == $fi && $l < $lno)} {
2653 if {$i < $fi || ($i == $fi && $l < $lno)} {
2592 set fi $i
2654 set fi $i
2593 set lno $l
2655 set lno $l
2594 set pi $p
2656 set pi $p
2595 }
2657 }
2596 }
2658 }
2597
2659
2598 if {$fi < $nfiles} {
2660 if {$fi < $nfiles} {
2599 set ids [list $diffmergeid $pi]
2661 set ids [list $diffmergeid $pi]
2600 set hunk $currenthunk($ids)
2662 set hunk $currenthunk($ids)
2601 unset currenthunk($ids)
2663 unset currenthunk($ids)
2602 if {$diffblocked($ids) > 0} {
2664 if {$diffblocked($ids) > 0} {
2603 fileevent $mergefds($ids) readable \
2665 fileevent $mergefds($ids) readable \
2604 [list getmergediffline $mergefds($ids) $ids $diffmergeid]
2666 [list getmergediffline $mergefds($ids) $ids $diffmergeid]
2605 }
2667 }
2606 set diffblocked($ids) 0
2668 set diffblocked($ids) 0
2607
2669
2608 if {[info exists groupfilenum] && $groupfilenum == $fi
2670 if {[info exists groupfilenum] && $groupfilenum == $fi
2609 && $lno <= $grouplineend} {
2671 && $lno <= $grouplineend} {
2610 # add this hunk to the pending group
2672 # add this hunk to the pending group
2611 lappend grouphunks($pi) $hunk
2673 lappend grouphunks($pi) $hunk
2612 set endln [lindex $hunk 4]
2674 set endln [lindex $hunk 4]
2613 if {$endln > $grouplineend} {
2675 if {$endln > $grouplineend} {
2614 set grouplineend $endln
2676 set grouplineend $endln
2615 }
2677 }
2616 continue
2678 continue
2617 }
2679 }
2618 }
2680 }
2619
2681
2620 # succeeding stuff doesn't belong in this group, so
2682 # succeeding stuff doesn't belong in this group, so
2621 # process the group now
2683 # process the group now
2622 if {[info exists groupfilenum]} {
2684 if {[info exists groupfilenum]} {
2623 processgroup
2685 processgroup
2624 unset groupfilenum
2686 unset groupfilenum
2625 unset grouphunks
2687 unset grouphunks
2626 }
2688 }
2627
2689
2628 if {$fi >= $nfiles} break
2690 if {$fi >= $nfiles} break
2629
2691
2630 # start a new group
2692 # start a new group
2631 set groupfilenum $fi
2693 set groupfilenum $fi
2632 set grouphunks($pi) [list $hunk]
2694 set grouphunks($pi) [list $hunk]
2633 set grouplinestart $lno
2695 set grouplinestart $lno
2634 set grouplineend [lindex $hunk 4]
2696 set grouplineend [lindex $hunk 4]
2635 }
2697 }
2636 }
2698 }
2637
2699
2638 proc processgroup {} {
2700 proc processgroup {} {
2639 global groupfilelast groupfilenum difffilestart
2701 global groupfilelast groupfilenum difffilestart
2640 global mergefilelist diffmergeid ctext filelines
2702 global mergefilelist diffmergeid ctext filelines
2641 global parents diffmergeid diffoffset
2703 global parents diffmergeid diffoffset
2642 global grouphunks grouplinestart grouplineend nparents
2704 global grouphunks grouplinestart grouplineend nparents
2643 global mergemax
2705 global mergemax
2644
2706
2645 $ctext conf -state normal
2707 $ctext conf -state normal
2646 set id $diffmergeid
2708 set id $diffmergeid
2647 set f $groupfilenum
2709 set f $groupfilenum
2648 if {$groupfilelast != $f} {
2710 if {$groupfilelast != $f} {
2649 $ctext insert end "\n"
2711 $ctext insert end "\n"
2650 set here [$ctext index "end - 1c"]
2712 set here [$ctext index "end - 1c"]
2651 set difffilestart($f) $here
2713 set difffilestart($f) $here
2652 set mark fmark.[expr {$f + 1}]
2714 set mark fmark.[expr {$f + 1}]
2653 $ctext mark set $mark $here
2715 $ctext mark set $mark $here
2654 $ctext mark gravity $mark left
2716 $ctext mark gravity $mark left
2655 set header [lindex $mergefilelist($id) $f]
2717 set header [lindex $mergefilelist($id) $f]
2656 set l [expr {(78 - [string length $header]) / 2}]
2718 set l [expr {(78 - [string length $header]) / 2}]
2657 set pad [string range "----------------------------------------" 1 $l]
2719 set pad [string range "----------------------------------------" 1 $l]
2658 $ctext insert end "$pad $header $pad\n" filesep
2720 $ctext insert end "$pad $header $pad\n" filesep
2659 set groupfilelast $f
2721 set groupfilelast $f
2660 foreach p $parents($id) {
2722 foreach p $parents($id) {
2661 set diffoffset($p) 0
2723 set diffoffset($p) 0
2662 }
2724 }
2663 }
2725 }
2664
2726
2665 $ctext insert end "@@" msep
2727 $ctext insert end "@@" msep
2666 set nlines [expr {$grouplineend - $grouplinestart}]
2728 set nlines [expr {$grouplineend - $grouplinestart}]
2667 set events {}
2729 set events {}
2668 set pnum 0
2730 set pnum 0
2669 foreach p $parents($id) {
2731 foreach p $parents($id) {
2670 set startline [expr {$grouplinestart + $diffoffset($p)}]
2732 set startline [expr {$grouplinestart + $diffoffset($p)}]
2671 set ol $startline
2733 set ol $startline
2672 set nl $grouplinestart
2734 set nl $grouplinestart
2673 if {[info exists grouphunks($p)]} {
2735 if {[info exists grouphunks($p)]} {
2674 foreach h $grouphunks($p) {
2736 foreach h $grouphunks($p) {
2675 set l [lindex $h 2]
2737 set l [lindex $h 2]
2676 if {$nl < $l} {
2738 if {$nl < $l} {
2677 for {} {$nl < $l} {incr nl} {
2739 for {} {$nl < $l} {incr nl} {
2678 set filelines($p,$f,$ol) $filelines($id,$f,$nl)
2740 set filelines($p,$f,$ol) $filelines($id,$f,$nl)
2679 incr ol
2741 incr ol
2680 }
2742 }
2681 }
2743 }
2682 foreach chunk [lindex $h 5] {
2744 foreach chunk [lindex $h 5] {
2683 if {[llength $chunk] == 2} {
2745 if {[llength $chunk] == 2} {
2684 set olc [lindex $chunk 0]
2746 set olc [lindex $chunk 0]
2685 set nlc [lindex $chunk 1]
2747 set nlc [lindex $chunk 1]
2686 set nnl [expr {$nl + $nlc}]
2748 set nnl [expr {$nl + $nlc}]
2687 lappend events [list $nl $nnl $pnum $olc $nlc]
2749 lappend events [list $nl $nnl $pnum $olc $nlc]
2688 incr ol $olc
2750 incr ol $olc
2689 set nl $nnl
2751 set nl $nnl
2690 } else {
2752 } else {
2691 incr ol [lindex $chunk 0]
2753 incr ol [lindex $chunk 0]
2692 incr nl [lindex $chunk 0]
2754 incr nl [lindex $chunk 0]
2693 }
2755 }
2694 }
2756 }
2695 }
2757 }
2696 }
2758 }
2697 if {$nl < $grouplineend} {
2759 if {$nl < $grouplineend} {
2698 for {} {$nl < $grouplineend} {incr nl} {
2760 for {} {$nl < $grouplineend} {incr nl} {
2699 set filelines($p,$f,$ol) $filelines($id,$f,$nl)
2761 set filelines($p,$f,$ol) $filelines($id,$f,$nl)
2700 incr ol
2762 incr ol
2701 }
2763 }
2702 }
2764 }
2703 set nlines [expr {$ol - $startline}]
2765 set nlines [expr {$ol - $startline}]
2704 $ctext insert end " -$startline,$nlines" msep
2766 $ctext insert end " -$startline,$nlines" msep
2705 incr pnum
2767 incr pnum
2706 }
2768 }
2707
2769
2708 set nlines [expr {$grouplineend - $grouplinestart}]
2770 set nlines [expr {$grouplineend - $grouplinestart}]
2709 $ctext insert end " +$grouplinestart,$nlines @@\n" msep
2771 $ctext insert end " +$grouplinestart,$nlines @@\n" msep
2710
2772
2711 set events [lsort -integer -index 0 $events]
2773 set events [lsort -integer -index 0 $events]
2712 set nevents [llength $events]
2774 set nevents [llength $events]
2713 set nmerge $nparents($diffmergeid)
2775 set nmerge $nparents($diffmergeid)
2714 set l $grouplinestart
2776 set l $grouplinestart
2715 for {set i 0} {$i < $nevents} {set i $j} {
2777 for {set i 0} {$i < $nevents} {set i $j} {
2716 set nl [lindex $events $i 0]
2778 set nl [lindex $events $i 0]
2717 while {$l < $nl} {
2779 while {$l < $nl} {
2718 $ctext insert end " $filelines($id,$f,$l)\n"
2780 $ctext insert end " $filelines($id,$f,$l)\n"
2719 incr l
2781 incr l
2720 }
2782 }
2721 set e [lindex $events $i]
2783 set e [lindex $events $i]
2722 set enl [lindex $e 1]
2784 set enl [lindex $e 1]
2723 set j $i
2785 set j $i
2724 set active {}
2786 set active {}
2725 while 1 {
2787 while 1 {
2726 set pnum [lindex $e 2]
2788 set pnum [lindex $e 2]
2727 set olc [lindex $e 3]
2789 set olc [lindex $e 3]
2728 set nlc [lindex $e 4]
2790 set nlc [lindex $e 4]
2729 if {![info exists delta($pnum)]} {
2791 if {![info exists delta($pnum)]} {
2730 set delta($pnum) [expr {$olc - $nlc}]
2792 set delta($pnum) [expr {$olc - $nlc}]
2731 lappend active $pnum
2793 lappend active $pnum
2732 } else {
2794 } else {
2733 incr delta($pnum) [expr {$olc - $nlc}]
2795 incr delta($pnum) [expr {$olc - $nlc}]
2734 }
2796 }
2735 if {[incr j] >= $nevents} break
2797 if {[incr j] >= $nevents} break
2736 set e [lindex $events $j]
2798 set e [lindex $events $j]
2737 if {[lindex $e 0] >= $enl} break
2799 if {[lindex $e 0] >= $enl} break
2738 if {[lindex $e 1] > $enl} {
2800 if {[lindex $e 1] > $enl} {
2739 set enl [lindex $e 1]
2801 set enl [lindex $e 1]
2740 }
2802 }
2741 }
2803 }
2742 set nlc [expr {$enl - $l}]
2804 set nlc [expr {$enl - $l}]
2743 set ncol mresult
2805 set ncol mresult
2744 set bestpn -1
2806 set bestpn -1
2745 if {[llength $active] == $nmerge - 1} {
2807 if {[llength $active] == $nmerge - 1} {
2746 # no diff for one of the parents, i.e. it's identical
2808 # no diff for one of the parents, i.e. it's identical
2747 for {set pnum 0} {$pnum < $nmerge} {incr pnum} {
2809 for {set pnum 0} {$pnum < $nmerge} {incr pnum} {
2748 if {![info exists delta($pnum)]} {
2810 if {![info exists delta($pnum)]} {
2749 if {$pnum < $mergemax} {
2811 if {$pnum < $mergemax} {
2750 lappend ncol m$pnum
2812 lappend ncol m$pnum
2751 } else {
2813 } else {
2752 lappend ncol mmax
2814 lappend ncol mmax
2753 }
2815 }
2754 break
2816 break
2755 }
2817 }
2756 }
2818 }
2757 } elseif {[llength $active] == $nmerge} {
2819 } elseif {[llength $active] == $nmerge} {
2758 # all parents are different, see if one is very similar
2820 # all parents are different, see if one is very similar
2759 set bestsim 30
2821 set bestsim 30
2760 for {set pnum 0} {$pnum < $nmerge} {incr pnum} {
2822 for {set pnum 0} {$pnum < $nmerge} {incr pnum} {
2761 set sim [similarity $pnum $l $nlc $f \
2823 set sim [similarity $pnum $l $nlc $f \
2762 [lrange $events $i [expr {$j-1}]]]
2824 [lrange $events $i [expr {$j-1}]]]
2763 if {$sim > $bestsim} {
2825 if {$sim > $bestsim} {
2764 set bestsim $sim
2826 set bestsim $sim
2765 set bestpn $pnum
2827 set bestpn $pnum
2766 }
2828 }
2767 }
2829 }
2768 if {$bestpn >= 0} {
2830 if {$bestpn >= 0} {
2769 lappend ncol m$bestpn
2831 lappend ncol m$bestpn
2770 }
2832 }
2771 }
2833 }
2772 set pnum -1
2834 set pnum -1
2773 foreach p $parents($id) {
2835 foreach p $parents($id) {
2774 incr pnum
2836 incr pnum
2775 if {![info exists delta($pnum)] || $pnum == $bestpn} continue
2837 if {![info exists delta($pnum)] || $pnum == $bestpn} continue
2776 set olc [expr {$nlc + $delta($pnum)}]
2838 set olc [expr {$nlc + $delta($pnum)}]
2777 set ol [expr {$l + $diffoffset($p)}]
2839 set ol [expr {$l + $diffoffset($p)}]
2778 incr diffoffset($p) $delta($pnum)
2840 incr diffoffset($p) $delta($pnum)
2779 unset delta($pnum)
2841 unset delta($pnum)
2780 for {} {$olc > 0} {incr olc -1} {
2842 for {} {$olc > 0} {incr olc -1} {
2781 $ctext insert end "-$filelines($p,$f,$ol)\n" m$pnum
2843 $ctext insert end "-$filelines($p,$f,$ol)\n" m$pnum
2782 incr ol
2844 incr ol
2783 }
2845 }
2784 }
2846 }
2785 set endl [expr {$l + $nlc}]
2847 set endl [expr {$l + $nlc}]
2786 if {$bestpn >= 0} {
2848 if {$bestpn >= 0} {
2787 # show this pretty much as a normal diff
2849 # show this pretty much as a normal diff
2788 set p [lindex $parents($id) $bestpn]
2850 set p [lindex $parents($id) $bestpn]
2789 set ol [expr {$l + $diffoffset($p)}]
2851 set ol [expr {$l + $diffoffset($p)}]
2790 incr diffoffset($p) $delta($bestpn)
2852 incr diffoffset($p) $delta($bestpn)
2791 unset delta($bestpn)
2853 unset delta($bestpn)
2792 for {set k $i} {$k < $j} {incr k} {
2854 for {set k $i} {$k < $j} {incr k} {
2793 set e [lindex $events $k]
2855 set e [lindex $events $k]
2794 if {[lindex $e 2] != $bestpn} continue
2856 if {[lindex $e 2] != $bestpn} continue
2795 set nl [lindex $e 0]
2857 set nl [lindex $e 0]
2796 set ol [expr {$ol + $nl - $l}]
2858 set ol [expr {$ol + $nl - $l}]
2797 for {} {$l < $nl} {incr l} {
2859 for {} {$l < $nl} {incr l} {
2798 $ctext insert end "+$filelines($id,$f,$l)\n" $ncol
2860 $ctext insert end "+$filelines($id,$f,$l)\n" $ncol
2799 }
2861 }
2800 set c [lindex $e 3]
2862 set c [lindex $e 3]
2801 for {} {$c > 0} {incr c -1} {
2863 for {} {$c > 0} {incr c -1} {
2802 $ctext insert end "-$filelines($p,$f,$ol)\n" m$bestpn
2864 $ctext insert end "-$filelines($p,$f,$ol)\n" m$bestpn
2803 incr ol
2865 incr ol
2804 }
2866 }
2805 set nl [lindex $e 1]
2867 set nl [lindex $e 1]
2806 for {} {$l < $nl} {incr l} {
2868 for {} {$l < $nl} {incr l} {
2807 $ctext insert end "+$filelines($id,$f,$l)\n" mresult
2869 $ctext insert end "+$filelines($id,$f,$l)\n" mresult
2808 }
2870 }
2809 }
2871 }
2810 }
2872 }
2811 for {} {$l < $endl} {incr l} {
2873 for {} {$l < $endl} {incr l} {
2812 $ctext insert end "+$filelines($id,$f,$l)\n" $ncol
2874 $ctext insert end "+$filelines($id,$f,$l)\n" $ncol
2813 }
2875 }
2814 }
2876 }
2815 while {$l < $grouplineend} {
2877 while {$l < $grouplineend} {
2816 $ctext insert end " $filelines($id,$f,$l)\n"
2878 $ctext insert end " $filelines($id,$f,$l)\n"
2817 incr l
2879 incr l
2818 }
2880 }
2819 $ctext conf -state disabled
2881 $ctext conf -state disabled
2820 }
2882 }
2821
2883
2822 proc similarity {pnum l nlc f events} {
2884 proc similarity {pnum l nlc f events} {
2823 global diffmergeid parents diffoffset filelines
2885 global diffmergeid parents diffoffset filelines
2824
2886
2825 set id $diffmergeid
2887 set id $diffmergeid
2826 set p [lindex $parents($id) $pnum]
2888 set p [lindex $parents($id) $pnum]
2827 set ol [expr {$l + $diffoffset($p)}]
2889 set ol [expr {$l + $diffoffset($p)}]
2828 set endl [expr {$l + $nlc}]
2890 set endl [expr {$l + $nlc}]
2829 set same 0
2891 set same 0
2830 set diff 0
2892 set diff 0
2831 foreach e $events {
2893 foreach e $events {
2832 if {[lindex $e 2] != $pnum} continue
2894 if {[lindex $e 2] != $pnum} continue
2833 set nl [lindex $e 0]
2895 set nl [lindex $e 0]
2834 set ol [expr {$ol + $nl - $l}]
2896 set ol [expr {$ol + $nl - $l}]
2835 for {} {$l < $nl} {incr l} {
2897 for {} {$l < $nl} {incr l} {
2836 incr same [string length $filelines($id,$f,$l)]
2898 incr same [string length $filelines($id,$f,$l)]
2837 incr same
2899 incr same
2838 }
2900 }
2839 set oc [lindex $e 3]
2901 set oc [lindex $e 3]
2840 for {} {$oc > 0} {incr oc -1} {
2902 for {} {$oc > 0} {incr oc -1} {
2841 incr diff [string length $filelines($p,$f,$ol)]
2903 incr diff [string length $filelines($p,$f,$ol)]
2842 incr diff
2904 incr diff
2843 incr ol
2905 incr ol
2844 }
2906 }
2845 set nl [lindex $e 1]
2907 set nl [lindex $e 1]
2846 for {} {$l < $nl} {incr l} {
2908 for {} {$l < $nl} {incr l} {
2847 incr diff [string length $filelines($id,$f,$l)]
2909 incr diff [string length $filelines($id,$f,$l)]
2848 incr diff
2910 incr diff
2849 }
2911 }
2850 }
2912 }
2851 for {} {$l < $endl} {incr l} {
2913 for {} {$l < $endl} {incr l} {
2852 incr same [string length $filelines($id,$f,$l)]
2914 incr same [string length $filelines($id,$f,$l)]
2853 incr same
2915 incr same
2854 }
2916 }
2855 if {$same == 0} {
2917 if {$same == 0} {
2856 return 0
2918 return 0
2857 }
2919 }
2858 return [expr {200 * $same / (2 * $same + $diff)}]
2920 return [expr {200 * $same / (2 * $same + $diff)}]
2859 }
2921 }
2860
2922
2861 proc startdiff {ids} {
2923 proc startdiff {ids} {
2862 global treediffs diffids treepending diffmergeid
2924 global treediffs diffids treepending diffmergeid
2863
2925
2864 set diffids $ids
2926 set diffids $ids
2865 catch {unset diffmergeid}
2927 catch {unset diffmergeid}
2866 if {![info exists treediffs($ids)]} {
2928 if {![info exists treediffs($ids)]} {
2867 if {![info exists treepending]} {
2929 if {![info exists treepending]} {
2868 gettreediffs $ids
2930 gettreediffs $ids
2869 }
2931 }
2870 } else {
2932 } else {
2871 addtocflist $ids
2933 addtocflist $ids
2872 }
2934 }
2873 }
2935 }
2874
2936
2875 proc addtocflist {ids} {
2937 proc addtocflist {ids} {
2876 global treediffs cflist
2938 global treediffs cflist
2877 foreach f $treediffs($ids) {
2939 foreach f $treediffs($ids) {
2878 $cflist insert end $f
2940 $cflist insert end $f
2879 }
2941 }
2880 getblobdiffs $ids
2942 getblobdiffs $ids
2881 }
2943 }
2882
2944
2883 proc gettreediffs {ids} {
2945 proc gettreediffs {ids} {
2884 global treediff parents treepending env
2946 global treediff parents treepending env
2885 set treepending $ids
2947 set treepending $ids
2886 set treediff {}
2948 set treediff {}
2887 set id [lindex $ids 0]
2949 set id [lindex $ids 0]
2888 set p [lindex $ids 1]
2950 set p [lindex $ids 1]
2889 if [catch {set gdtf [open "|{$env(HG)} --config ui.report_untrusted=false debug-diff-tree -r $p $id" r]}] return
2951 if [catch {set gdtf [open "|{$env(HG)} --config ui.report_untrusted=false debug-diff-tree -r $p $id" r]}] return
2890 fconfigure $gdtf -blocking 0
2952 fconfigure $gdtf -blocking 0
2891 fileevent $gdtf readable [list gettreediffline $gdtf $ids]
2953 fileevent $gdtf readable [list gettreediffline $gdtf $ids]
2892 }
2954 }
2893
2955
2894 proc gettreediffline {gdtf ids} {
2956 proc gettreediffline {gdtf ids} {
2895 global treediff treediffs treepending diffids diffmergeid
2957 global treediff treediffs treepending diffids diffmergeid
2896
2958
2897 set n [gets $gdtf line]
2959 set n [gets $gdtf line]
2898 if {$n < 0} {
2960 if {$n < 0} {
2899 if {![eof $gdtf]} return
2961 if {![eof $gdtf]} return
2900 close $gdtf
2962 close $gdtf
2901 set treediffs($ids) $treediff
2963 set treediffs($ids) $treediff
2902 unset treepending
2964 unset treepending
2903 if {$ids != $diffids} {
2965 if {$ids != $diffids} {
2904 gettreediffs $diffids
2966 gettreediffs $diffids
2905 } else {
2967 } else {
2906 if {[info exists diffmergeid]} {
2968 if {[info exists diffmergeid]} {
2907 contmergediff $ids
2969 contmergediff $ids
2908 } else {
2970 } else {
2909 addtocflist $ids
2971 addtocflist $ids
2910 }
2972 }
2911 }
2973 }
2912 return
2974 return
2913 }
2975 }
2914 set tab1 [expr [string first "\t" $line] + 1]
2976 set tab1 [expr [string first "\t" $line] + 1]
2915 set tab2 [expr [string first "\t" $line $tab1] - 1]
2977 set tab2 [expr [string first "\t" $line $tab1] - 1]
2916 set file [string range $line $tab1 $tab2]
2978 set file [string range $line $tab1 $tab2]
2917 lappend treediff $file
2979 lappend treediff $file
2918 }
2980 }
2919
2981
2920 proc getblobdiffs {ids} {
2982 proc getblobdiffs {ids} {
2921 global diffopts blobdifffd diffids env curdifftag curtagstart
2983 global diffopts blobdifffd diffids env curdifftag curtagstart
2922 global difffilestart nextupdate diffinhdr treediffs
2984 global difffilestart nextupdate diffinhdr treediffs
2923
2985
2924 set id [lindex $ids 0]
2986 set id [lindex $ids 0]
2925 set p [lindex $ids 1]
2987 set p [lindex $ids 1]
2926 set env(GIT_DIFF_OPTS) $diffopts
2988 set env(GIT_DIFF_OPTS) $diffopts
2927 set cmd [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -r -p -C $p $id]
2989 set cmd [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -r -p -C $p $id]
2928 if {[catch {set bdf [open $cmd r]} err]} {
2990 if {[catch {set bdf [open $cmd r]} err]} {
2929 puts "error getting diffs: $err"
2991 puts "error getting diffs: $err"
2930 return
2992 return
2931 }
2993 }
2932 set diffinhdr 0
2994 set diffinhdr 0
2933 fconfigure $bdf -blocking 0
2995 fconfigure $bdf -blocking 0
2934 set blobdifffd($ids) $bdf
2996 set blobdifffd($ids) $bdf
2935 set curdifftag Comments
2997 set curdifftag Comments
2936 set curtagstart 0.0
2998 set curtagstart 0.0
2937 catch {unset difffilestart}
2999 catch {unset difffilestart}
2938 fileevent $bdf readable [list getblobdiffline $bdf $diffids]
3000 fileevent $bdf readable [list getblobdiffline $bdf $diffids]
2939 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
3001 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
2940 }
3002 }
2941
3003
2942 proc getblobdiffline {bdf ids} {
3004 proc getblobdiffline {bdf ids} {
2943 global diffids blobdifffd ctext curdifftag curtagstart
3005 global diffids blobdifffd ctext curdifftag curtagstart
2944 global diffnexthead diffnextnote difffilestart
3006 global diffnexthead diffnextnote difffilestart
2945 global nextupdate diffinhdr treediffs
3007 global nextupdate diffinhdr treediffs
2946 global gaudydiff
3008 global gaudydiff
2947
3009
2948 set n [gets $bdf line]
3010 set n [gets $bdf line]
2949 if {$n < 0} {
3011 if {$n < 0} {
2950 if {[eof $bdf]} {
3012 if {[eof $bdf]} {
2951 close $bdf
3013 close $bdf
2952 if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
3014 if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
2953 $ctext tag add $curdifftag $curtagstart end
3015 $ctext tag add $curdifftag $curtagstart end
2954 }
3016 }
2955 }
3017 }
2956 return
3018 return
2957 }
3019 }
2958 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
3020 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
2959 return
3021 return
2960 }
3022 }
2961 regsub -all "\r" $line "" line
3023 regsub -all "\r" $line "" line
2962 $ctext conf -state normal
3024 $ctext conf -state normal
2963 if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} {
3025 if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} {
2964 # start of a new file
3026 # start of a new file
2965 $ctext insert end "\n"
3027 $ctext insert end "\n"
2966 $ctext tag add $curdifftag $curtagstart end
3028 $ctext tag add $curdifftag $curtagstart end
2967 set curtagstart [$ctext index "end - 1c"]
3029 set curtagstart [$ctext index "end - 1c"]
2968 set header $newname
3030 set header $newname
2969 set here [$ctext index "end - 1c"]
3031 set here [$ctext index "end - 1c"]
2970 set i [lsearch -exact $treediffs($diffids) $fname]
3032 set i [lsearch -exact $treediffs($diffids) $fname]
2971 if {$i >= 0} {
3033 if {$i >= 0} {
2972 set difffilestart($i) $here
3034 set difffilestart($i) $here
2973 incr i
3035 incr i
2974 $ctext mark set fmark.$i $here
3036 $ctext mark set fmark.$i $here
2975 $ctext mark gravity fmark.$i left
3037 $ctext mark gravity fmark.$i left
2976 }
3038 }
2977 if {$newname != $fname} {
3039 if {$newname != $fname} {
2978 set i [lsearch -exact $treediffs($diffids) $newname]
3040 set i [lsearch -exact $treediffs($diffids) $newname]
2979 if {$i >= 0} {
3041 if {$i >= 0} {
2980 set difffilestart($i) $here
3042 set difffilestart($i) $here
2981 incr i
3043 incr i
2982 $ctext mark set fmark.$i $here
3044 $ctext mark set fmark.$i $here
2983 $ctext mark gravity fmark.$i left
3045 $ctext mark gravity fmark.$i left
2984 }
3046 }
2985 }
3047 }
2986 set curdifftag "f:$fname"
3048 set curdifftag "f:$fname"
2987 $ctext tag delete $curdifftag
3049 $ctext tag delete $curdifftag
2988 set l [expr {(78 - [string length $header]) / 2}]
3050 set l [expr {(78 - [string length $header]) / 2}]
2989 set pad [string range "----------------------------------------" 1 $l]
3051 set pad [string range "----------------------------------------" 1 $l]
2990 $ctext insert end "$pad $header $pad\n" filesep
3052 $ctext insert end "$pad $header $pad\n" filesep
2991 set diffinhdr 1
3053 set diffinhdr 1
2992 } elseif {[regexp {^(---|\+\+\+)} $line]} {
3054 } elseif {[regexp {^(---|\+\+\+)} $line]} {
2993 set diffinhdr 0
3055 set diffinhdr 0
2994 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
3056 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
2995 $line match f1l f1c f2l f2c rest]} {
3057 $line match f1l f1c f2l f2c rest]} {
2996 if {$gaudydiff} {
3058 if {$gaudydiff} {
2997 $ctext insert end "\t" hunksep
3059 $ctext insert end "\t" hunksep
2998 $ctext insert end " $f1l " d0 " $f2l " d1
3060 $ctext insert end " $f1l " d0 " $f2l " d1
2999 $ctext insert end " $rest \n" hunksep
3061 $ctext insert end " $rest \n" hunksep
3000 } else {
3062 } else {
3001 $ctext insert end "$line\n" hunksep
3063 $ctext insert end "$line\n" hunksep
3002 }
3064 }
3003 set diffinhdr 0
3065 set diffinhdr 0
3004 } else {
3066 } else {
3005 set x [string range $line 0 0]
3067 set x [string range $line 0 0]
3006 if {$x == "-" || $x == "+"} {
3068 if {$x == "-" || $x == "+"} {
3007 set tag [expr {$x == "+"}]
3069 set tag [expr {$x == "+"}]
3008 if {$gaudydiff} {
3070 if {$gaudydiff} {
3009 set line [string range $line 1 end]
3071 set line [string range $line 1 end]
3010 }
3072 }
3011 $ctext insert end "$line\n" d$tag
3073 $ctext insert end "$line\n" d$tag
3012 } elseif {$x == " "} {
3074 } elseif {$x == " "} {
3013 if {$gaudydiff} {
3075 if {$gaudydiff} {
3014 set line [string range $line 1 end]
3076 set line [string range $line 1 end]
3015 }
3077 }
3016 $ctext insert end "$line\n"
3078 $ctext insert end "$line\n"
3017 } elseif {$diffinhdr || $x == "\\"} {
3079 } elseif {$diffinhdr || $x == "\\"} {
3018 # e.g. "\ No newline at end of file"
3080 # e.g. "\ No newline at end of file"
3019 $ctext insert end "$line\n" filesep
3081 $ctext insert end "$line\n" filesep
3020 } elseif {$line != ""} {
3082 } elseif {$line != ""} {
3021 # Something else we don't recognize
3083 # Something else we don't recognize
3022 if {$curdifftag != "Comments"} {
3084 if {$curdifftag != "Comments"} {
3023 $ctext insert end "\n"
3085 $ctext insert end "\n"
3024 $ctext tag add $curdifftag $curtagstart end
3086 $ctext tag add $curdifftag $curtagstart end
3025 set curtagstart [$ctext index "end - 1c"]
3087 set curtagstart [$ctext index "end - 1c"]
3026 set curdifftag Comments
3088 set curdifftag Comments
3027 }
3089 }
3028 $ctext insert end "$line\n" filesep
3090 $ctext insert end "$line\n" filesep
3029 }
3091 }
3030 }
3092 }
3031 $ctext conf -state disabled
3093 $ctext conf -state disabled
3032 if {[clock clicks -milliseconds] >= $nextupdate} {
3094 if {[clock clicks -milliseconds] >= $nextupdate} {
3033 incr nextupdate 100
3095 incr nextupdate 100
3034 fileevent $bdf readable {}
3096 fileevent $bdf readable {}
3035 update
3097 update
3036 fileevent $bdf readable "getblobdiffline $bdf {$ids}"
3098 fileevent $bdf readable "getblobdiffline $bdf {$ids}"
3037 }
3099 }
3038 }
3100 }
3039
3101
3040 proc nextfile {} {
3102 proc nextfile {} {
3041 global difffilestart ctext
3103 global difffilestart ctext
3042 set here [$ctext index @0,0]
3104 set here [$ctext index @0,0]
3043 for {set i 0} {[info exists difffilestart($i)]} {incr i} {
3105 for {set i 0} {[info exists difffilestart($i)]} {incr i} {
3044 if {[$ctext compare $difffilestart($i) > $here]} {
3106 if {[$ctext compare $difffilestart($i) > $here]} {
3045 if {![info exists pos]
3107 if {![info exists pos]
3046 || [$ctext compare $difffilestart($i) < $pos]} {
3108 || [$ctext compare $difffilestart($i) < $pos]} {
3047 set pos $difffilestart($i)
3109 set pos $difffilestart($i)
3048 }
3110 }
3049 }
3111 }
3050 }
3112 }
3051 if {[info exists pos]} {
3113 if {[info exists pos]} {
3052 $ctext yview $pos
3114 $ctext yview $pos
3053 }
3115 }
3054 }
3116 }
3055
3117
3056 proc listboxsel {} {
3118 proc listboxsel {} {
3057 global ctext cflist currentid
3119 global ctext cflist currentid
3058 if {![info exists currentid]} return
3120 if {![info exists currentid]} return
3059 set sel [lsort [$cflist curselection]]
3121 set sel [lsort [$cflist curselection]]
3060 if {$sel eq {}} return
3122 if {$sel eq {}} return
3061 set first [lindex $sel 0]
3123 set first [lindex $sel 0]
3062 catch {$ctext yview fmark.$first}
3124 catch {$ctext yview fmark.$first}
3063 }
3125 }
3064
3126
3065 proc setcoords {} {
3127 proc setcoords {} {
3066 global linespc charspc canvx0 canvy0 mainfont
3128 global linespc charspc canvx0 canvy0 mainfont
3067 global xspc1 xspc2 lthickness
3129 global xspc1 xspc2 lthickness
3068
3130
3069 set linespc [font metrics $mainfont -linespace]
3131 set linespc [font metrics $mainfont -linespace]
3070 set charspc [font measure $mainfont "m"]
3132 set charspc [font measure $mainfont "m"]
3071 set canvy0 [expr 3 + 0.5 * $linespc]
3133 set canvy0 [expr 3 + 0.5 * $linespc]
3072 set canvx0 [expr 3 + 0.5 * $linespc]
3134 set canvx0 [expr 3 + 0.5 * $linespc]
3073 set lthickness [expr {int($linespc / 9) + 1}]
3135 set lthickness [expr {int($linespc / 9) + 1}]
3074 set xspc1(0) $linespc
3136 set xspc1(0) $linespc
3075 set xspc2 $linespc
3137 set xspc2 $linespc
3076 }
3138 }
3077
3139
3078 proc redisplay {} {
3140 proc redisplay {} {
3079 global stopped redisplaying phase
3141 global stopped redisplaying phase
3080 if {$stopped > 1} return
3142 if {$stopped > 1} return
3081 if {$phase == "getcommits"} return
3143 if {$phase == "getcommits"} return
3082 set redisplaying 1
3144 set redisplaying 1
3083 if {$phase == "drawgraph" || $phase == "incrdraw"} {
3145 if {$phase == "drawgraph" || $phase == "incrdraw"} {
3084 set stopped 1
3146 set stopped 1
3085 } else {
3147 } else {
3086 drawgraph
3148 drawgraph
3087 }
3149 }
3088 }
3150 }
3089
3151
3090 proc incrfont {inc} {
3152 proc incrfont {inc} {
3091 global mainfont namefont textfont ctext canv phase
3153 global mainfont namefont textfont ctext canv phase
3092 global stopped entries
3154 global stopped entries curidfont
3093 unmarkmatches
3155 unmarkmatches
3094 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
3156 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
3157 set curidfont [lreplace $curidfont 1 1 [expr {[lindex $curidfont 1] + $inc}]]
3095 set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]]
3158 set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]]
3096 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
3159 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
3097 setcoords
3160 setcoords
3098 $ctext conf -font $textfont
3161 $ctext conf -font $textfont
3099 $ctext tag conf filesep -font [concat $textfont bold]
3162 $ctext tag conf filesep -font [concat $textfont bold]
3100 foreach e $entries {
3163 foreach e $entries {
3101 $e conf -font $mainfont
3164 $e conf -font $mainfont
3102 }
3165 }
3103 if {$phase == "getcommits"} {
3166 if {$phase == "getcommits"} {
3104 $canv itemconf textitems -font $mainfont
3167 $canv itemconf textitems -font $mainfont
3105 }
3168 }
3106 redisplay
3169 redisplay
3107 }
3170 }
3108
3171
3109 proc clearsha1 {} {
3172 proc clearsha1 {} {
3110 global sha1entry sha1string
3173 global sha1entry sha1string
3111 if {[string length $sha1string] == 40} {
3174 if {[string length $sha1string] == 40} {
3112 $sha1entry delete 0 end
3175 $sha1entry delete 0 end
3113 }
3176 }
3114 }
3177 }
3115
3178
3116 proc sha1change {n1 n2 op} {
3179 proc sha1change {n1 n2 op} {
3117 global sha1string currentid sha1but
3180 global sha1string currentid sha1but
3118 if {$sha1string == {}
3181 if {$sha1string == {}
3119 || ([info exists currentid] && $sha1string == $currentid)} {
3182 || ([info exists currentid] && $sha1string == $currentid)} {
3120 set state disabled
3183 set state disabled
3121 } else {
3184 } else {
3122 set state normal
3185 set state normal
3123 }
3186 }
3124 if {[$sha1but cget -state] == $state} return
3187 if {[$sha1but cget -state] == $state} return
3125 if {$state == "normal"} {
3188 if {$state == "normal"} {
3126 $sha1but conf -state normal -relief raised -text "Goto: "
3189 $sha1but conf -state normal -relief raised -text "Goto: "
3127 } else {
3190 } else {
3128 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
3191 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
3129 }
3192 }
3130 }
3193 }
3131
3194
3132 proc gotocommit {} {
3195 proc gotocommit {} {
3133 global sha1string currentid idline tagids
3196 global sha1string currentid idline tagids
3134 global lineid numcommits
3197 global lineid numcommits
3135
3198
3136 if {$sha1string == {}
3199 if {$sha1string == {}
3137 || ([info exists currentid] && $sha1string == $currentid)} return
3200 || ([info exists currentid] && $sha1string == $currentid)} return
3138 if {[info exists tagids($sha1string)]} {
3201 if {[info exists tagids($sha1string)]} {
3139 set id $tagids($sha1string)
3202 set id $tagids($sha1string)
3140 } else {
3203 } else {
3141 set id [string tolower $sha1string]
3204 set id [string tolower $sha1string]
3142 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
3205 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
3143 set matches {}
3206 set matches {}
3144 for {set l 0} {$l < $numcommits} {incr l} {
3207 for {set l 0} {$l < $numcommits} {incr l} {
3145 if {[string match $id* $lineid($l)]} {
3208 if {[string match $id* $lineid($l)]} {
3146 lappend matches $lineid($l)
3209 lappend matches $lineid($l)
3147 }
3210 }
3148 }
3211 }
3149 if {$matches ne {}} {
3212 if {$matches ne {}} {
3150 if {[llength $matches] > 1} {
3213 if {[llength $matches] > 1} {
3151 error_popup "Short SHA1 id $id is ambiguous"
3214 error_popup "Short SHA1 id $id is ambiguous"
3152 return
3215 return
3153 }
3216 }
3154 set id [lindex $matches 0]
3217 set id [lindex $matches 0]
3155 }
3218 }
3156 }
3219 }
3157 }
3220 }
3158 if {[info exists idline($id)]} {
3221 if {[info exists idline($id)]} {
3159 selectline $idline($id) 1
3222 selectline $idline($id) 1
3160 return
3223 return
3161 }
3224 }
3162 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
3225 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
3163 set type "SHA1 id"
3226 set type "SHA1 id"
3164 } else {
3227 } else {
3165 set type "Tag"
3228 set type "Tag"
3166 }
3229 }
3167 error_popup "$type $sha1string is not known"
3230 error_popup "$type $sha1string is not known"
3168 }
3231 }
3169
3232
3170 proc lineenter {x y id} {
3233 proc lineenter {x y id} {
3171 global hoverx hovery hoverid hovertimer
3234 global hoverx hovery hoverid hovertimer
3172 global commitinfo canv
3235 global commitinfo canv
3173
3236
3174 if {![info exists commitinfo($id)]} return
3237 if {![info exists commitinfo($id)]} return
3175 set hoverx $x
3238 set hoverx $x
3176 set hovery $y
3239 set hovery $y
3177 set hoverid $id
3240 set hoverid $id
3178 if {[info exists hovertimer]} {
3241 if {[info exists hovertimer]} {
3179 after cancel $hovertimer
3242 after cancel $hovertimer
3180 }
3243 }
3181 set hovertimer [after 500 linehover]
3244 set hovertimer [after 500 linehover]
3182 $canv delete hover
3245 $canv delete hover
3183 }
3246 }
3184
3247
3185 proc linemotion {x y id} {
3248 proc linemotion {x y id} {
3186 global hoverx hovery hoverid hovertimer
3249 global hoverx hovery hoverid hovertimer
3187
3250
3188 if {[info exists hoverid] && $id == $hoverid} {
3251 if {[info exists hoverid] && $id == $hoverid} {
3189 set hoverx $x
3252 set hoverx $x
3190 set hovery $y
3253 set hovery $y
3191 if {[info exists hovertimer]} {
3254 if {[info exists hovertimer]} {
3192 after cancel $hovertimer
3255 after cancel $hovertimer
3193 }
3256 }
3194 set hovertimer [after 500 linehover]
3257 set hovertimer [after 500 linehover]
3195 }
3258 }
3196 }
3259 }
3197
3260
3198 proc lineleave {id} {
3261 proc lineleave {id} {
3199 global hoverid hovertimer canv
3262 global hoverid hovertimer canv
3200
3263
3201 if {[info exists hoverid] && $id == $hoverid} {
3264 if {[info exists hoverid] && $id == $hoverid} {
3202 $canv delete hover
3265 $canv delete hover
3203 if {[info exists hovertimer]} {
3266 if {[info exists hovertimer]} {
3204 after cancel $hovertimer
3267 after cancel $hovertimer
3205 unset hovertimer
3268 unset hovertimer
3206 }
3269 }
3207 unset hoverid
3270 unset hoverid
3208 }
3271 }
3209 }
3272 }
3210
3273
3211 proc linehover {} {
3274 proc linehover {} {
3212 global hoverx hovery hoverid hovertimer
3275 global hoverx hovery hoverid hovertimer
3213 global canv linespc lthickness
3276 global canv linespc lthickness
3214 global commitinfo mainfont
3277 global commitinfo mainfont
3215
3278
3216 set text [lindex $commitinfo($hoverid) 0]
3279 set text [lindex $commitinfo($hoverid) 0]
3217 set ymax [lindex [$canv cget -scrollregion] 3]
3280 set ymax [lindex [$canv cget -scrollregion] 3]
3218 if {$ymax == {}} return
3281 if {$ymax == {}} return
3219 set yfrac [lindex [$canv yview] 0]
3282 set yfrac [lindex [$canv yview] 0]
3220 set x [expr {$hoverx + 2 * $linespc}]
3283 set x [expr {$hoverx + 2 * $linespc}]
3221 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
3284 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
3222 set x0 [expr {$x - 2 * $lthickness}]
3285 set x0 [expr {$x - 2 * $lthickness}]
3223 set y0 [expr {$y - 2 * $lthickness}]
3286 set y0 [expr {$y - 2 * $lthickness}]
3224 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
3287 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
3225 set y1 [expr {$y + $linespc + 2 * $lthickness}]
3288 set y1 [expr {$y + $linespc + 2 * $lthickness}]
3226 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
3289 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
3227 -fill \#ffff80 -outline black -width 1 -tags hover]
3290 -fill \#ffff80 -outline black -width 1 -tags hover]
3228 $canv raise $t
3291 $canv raise $t
3229 set t [$canv create text $x $y -anchor nw -text $text -tags hover]
3292 set t [$canv create text $x $y -anchor nw -text $text -tags hover]
3230 $canv raise $t
3293 $canv raise $t
3231 }
3294 }
3232
3295
3233 proc clickisonarrow {id y} {
3296 proc clickisonarrow {id y} {
3234 global mainline mainlinearrow sidelines lthickness
3297 global mainline mainlinearrow sidelines lthickness
3235
3298
3236 set thresh [expr {2 * $lthickness + 6}]
3299 set thresh [expr {2 * $lthickness + 6}]
3237 if {[info exists mainline($id)]} {
3300 if {[info exists mainline($id)]} {
3238 if {$mainlinearrow($id) ne "none"} {
3301 if {$mainlinearrow($id) ne "none"} {
3239 if {abs([lindex $mainline($id) 1] - $y) < $thresh} {
3302 if {abs([lindex $mainline($id) 1] - $y) < $thresh} {
3240 return "up"
3303 return "up"
3241 }
3304 }
3242 }
3305 }
3243 }
3306 }
3244 if {[info exists sidelines($id)]} {
3307 if {[info exists sidelines($id)]} {
3245 foreach ls $sidelines($id) {
3308 foreach ls $sidelines($id) {
3246 set coords [lindex $ls 0]
3309 set coords [lindex $ls 0]
3247 set arrow [lindex $ls 2]
3310 set arrow [lindex $ls 2]
3248 if {$arrow eq "first" || $arrow eq "both"} {
3311 if {$arrow eq "first" || $arrow eq "both"} {
3249 if {abs([lindex $coords 1] - $y) < $thresh} {
3312 if {abs([lindex $coords 1] - $y) < $thresh} {
3250 return "up"
3313 return "up"
3251 }
3314 }
3252 }
3315 }
3253 if {$arrow eq "last" || $arrow eq "both"} {
3316 if {$arrow eq "last" || $arrow eq "both"} {
3254 if {abs([lindex $coords end] - $y) < $thresh} {
3317 if {abs([lindex $coords end] - $y) < $thresh} {
3255 return "down"
3318 return "down"
3256 }
3319 }
3257 }
3320 }
3258 }
3321 }
3259 }
3322 }
3260 return {}
3323 return {}
3261 }
3324 }
3262
3325
3263 proc arrowjump {id dirn y} {
3326 proc arrowjump {id dirn y} {
3264 global mainline sidelines canv
3327 global mainline sidelines canv
3265
3328
3266 set yt {}
3329 set yt {}
3267 if {$dirn eq "down"} {
3330 if {$dirn eq "down"} {
3268 if {[info exists mainline($id)]} {
3331 if {[info exists mainline($id)]} {
3269 set y1 [lindex $mainline($id) 1]
3332 set y1 [lindex $mainline($id) 1]
3270 if {$y1 > $y} {
3333 if {$y1 > $y} {
3271 set yt $y1
3334 set yt $y1
3272 }
3335 }
3273 }
3336 }
3274 if {[info exists sidelines($id)]} {
3337 if {[info exists sidelines($id)]} {
3275 foreach ls $sidelines($id) {
3338 foreach ls $sidelines($id) {
3276 set y1 [lindex $ls 0 1]
3339 set y1 [lindex $ls 0 1]
3277 if {$y1 > $y && ($yt eq {} || $y1 < $yt)} {
3340 if {$y1 > $y && ($yt eq {} || $y1 < $yt)} {
3278 set yt $y1
3341 set yt $y1
3279 }
3342 }
3280 }
3343 }
3281 }
3344 }
3282 } else {
3345 } else {
3283 if {[info exists sidelines($id)]} {
3346 if {[info exists sidelines($id)]} {
3284 foreach ls $sidelines($id) {
3347 foreach ls $sidelines($id) {
3285 set y1 [lindex $ls 0 end]
3348 set y1 [lindex $ls 0 end]
3286 if {$y1 < $y && ($yt eq {} || $y1 > $yt)} {
3349 if {$y1 < $y && ($yt eq {} || $y1 > $yt)} {
3287 set yt $y1
3350 set yt $y1
3288 }
3351 }
3289 }
3352 }
3290 }
3353 }
3291 }
3354 }
3292 if {$yt eq {}} return
3355 if {$yt eq {}} return
3293 set ymax [lindex [$canv cget -scrollregion] 3]
3356 set ymax [lindex [$canv cget -scrollregion] 3]
3294 if {$ymax eq {} || $ymax <= 0} return
3357 if {$ymax eq {} || $ymax <= 0} return
3295 set view [$canv yview]
3358 set view [$canv yview]
3296 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
3359 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
3297 set yfrac [expr {$yt / $ymax - $yspan / 2}]
3360 set yfrac [expr {$yt / $ymax - $yspan / 2}]
3298 if {$yfrac < 0} {
3361 if {$yfrac < 0} {
3299 set yfrac 0
3362 set yfrac 0
3300 }
3363 }
3301 $canv yview moveto $yfrac
3364 $canv yview moveto $yfrac
3302 }
3365 }
3303
3366
3304 proc lineclick {x y id isnew} {
3367 proc lineclick {x y id isnew} {
3305 global ctext commitinfo children cflist canv thickerline
3368 global ctext commitinfo children cflist canv thickerline
3306
3369
3307 unmarkmatches
3370 unmarkmatches
3308 unselectline
3371 unselectline
3309 normalline
3372 normalline
3310 $canv delete hover
3373 $canv delete hover
3311 # draw this line thicker than normal
3374 # draw this line thicker than normal
3312 drawlines $id 1
3375 drawlines $id 1
3313 set thickerline $id
3376 set thickerline $id
3314 if {$isnew} {
3377 if {$isnew} {
3315 set ymax [lindex [$canv cget -scrollregion] 3]
3378 set ymax [lindex [$canv cget -scrollregion] 3]
3316 if {$ymax eq {}} return
3379 if {$ymax eq {}} return
3317 set yfrac [lindex [$canv yview] 0]
3380 set yfrac [lindex [$canv yview] 0]
3318 set y [expr {$y + $yfrac * $ymax}]
3381 set y [expr {$y + $yfrac * $ymax}]
3319 }
3382 }
3320 set dirn [clickisonarrow $id $y]
3383 set dirn [clickisonarrow $id $y]
3321 if {$dirn ne {}} {
3384 if {$dirn ne {}} {
3322 arrowjump $id $dirn $y
3385 arrowjump $id $dirn $y
3323 return
3386 return
3324 }
3387 }
3325
3388
3326 if {$isnew} {
3389 if {$isnew} {
3327 addtohistory [list lineclick $x $y $id 0]
3390 addtohistory [list lineclick $x $y $id 0]
3328 }
3391 }
3329 # fill the details pane with info about this line
3392 # fill the details pane with info about this line
3330 $ctext conf -state normal
3393 $ctext conf -state normal
3331 $ctext delete 0.0 end
3394 $ctext delete 0.0 end
3332 $ctext tag conf link -foreground blue -underline 1
3395 $ctext tag conf link -foreground blue -underline 1
3333 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
3396 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
3334 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
3397 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
3335 $ctext insert end "Parent:\t"
3398 $ctext insert end "Parent:\t"
3336 $ctext insert end $id [list link link0]
3399 $ctext insert end $id [list link link0]
3337 $ctext tag bind link0 <1> [list selbyid $id]
3400 $ctext tag bind link0 <1> [list selbyid $id]
3338 set info $commitinfo($id)
3401 set info $commitinfo($id)
3339 $ctext insert end "\n\t[lindex $info 0]\n"
3402 $ctext insert end "\n\t[lindex $info 0]\n"
3340 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
3403 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
3341 $ctext insert end "\tDate:\t[lindex $info 2]\n"
3404 $ctext insert end "\tDate:\t[lindex $info 2]\n"
3342 if {[info exists children($id)]} {
3405 if {[info exists children($id)]} {
3343 $ctext insert end "\nChildren:"
3406 $ctext insert end "\nChildren:"
3344 set i 0
3407 set i 0
3345 foreach child $children($id) {
3408 foreach child $children($id) {
3346 incr i
3409 incr i
3347 set info $commitinfo($child)
3410 set info $commitinfo($child)
3348 $ctext insert end "\n\t"
3411 $ctext insert end "\n\t"
3349 $ctext insert end $child [list link link$i]
3412 $ctext insert end $child [list link link$i]
3350 $ctext tag bind link$i <1> [list selbyid $child]
3413 $ctext tag bind link$i <1> [list selbyid $child]
3351 $ctext insert end "\n\t[lindex $info 0]"
3414 $ctext insert end "\n\t[lindex $info 0]"
3352 $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
3415 $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
3353 $ctext insert end "\n\tDate:\t[lindex $info 2]\n"
3416 $ctext insert end "\n\tDate:\t[lindex $info 2]\n"
3354 }
3417 }
3355 }
3418 }
3356 $ctext conf -state disabled
3419 $ctext conf -state disabled
3357
3420
3358 $cflist delete 0 end
3421 $cflist delete 0 end
3359 }
3422 }
3360
3423
3361 proc normalline {} {
3424 proc normalline {} {
3362 global thickerline
3425 global thickerline
3363 if {[info exists thickerline]} {
3426 if {[info exists thickerline]} {
3364 drawlines $thickerline 0
3427 drawlines $thickerline 0
3365 unset thickerline
3428 unset thickerline
3366 }
3429 }
3367 }
3430 }
3368
3431
3369 proc selbyid {id} {
3432 proc selbyid {id} {
3370 global idline
3433 global idline
3371 if {[info exists idline($id)]} {
3434 if {[info exists idline($id)]} {
3372 selectline $idline($id) 1
3435 selectline $idline($id) 1
3373 }
3436 }
3374 }
3437 }
3375
3438
3376 proc mstime {} {
3439 proc mstime {} {
3377 global startmstime
3440 global startmstime
3378 if {![info exists startmstime]} {
3441 if {![info exists startmstime]} {
3379 set startmstime [clock clicks -milliseconds]
3442 set startmstime [clock clicks -milliseconds]
3380 }
3443 }
3381 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
3444 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
3382 }
3445 }
3383
3446
3384 proc rowmenu {x y id} {
3447 proc rowmenu {x y id} {
3385 global rowctxmenu idline selectedline rowmenuid hgvdiff
3448 global rowctxmenu idline selectedline rowmenuid hgvdiff
3386
3449
3387 if {![info exists selectedline] || $idline($id) eq $selectedline} {
3450 if {![info exists selectedline] || $idline($id) eq $selectedline} {
3388 set state disabled
3451 set state disabled
3389 } else {
3452 } else {
3390 set state normal
3453 set state normal
3391 }
3454 }
3392 $rowctxmenu entryconfigure 0 -state $state
3455 $rowctxmenu entryconfigure 0 -state $state
3393 $rowctxmenu entryconfigure 1 -state $state
3456 $rowctxmenu entryconfigure 1 -state $state
3394 $rowctxmenu entryconfigure 2 -state $state
3457 $rowctxmenu entryconfigure 2 -state $state
3395 if { $hgvdiff ne "" } {
3458 if { $hgvdiff ne "" } {
3396 $rowctxmenu entryconfigure 6 -state $state
3459 $rowctxmenu entryconfigure 6 -state $state
3397 }
3460 }
3398 set rowmenuid $id
3461 set rowmenuid $id
3399 tk_popup $rowctxmenu $x $y
3462 tk_popup $rowctxmenu $x $y
3400 }
3463 }
3401
3464
3402 proc diffvssel {dirn} {
3465 proc diffvssel {dirn} {
3403 global rowmenuid selectedline lineid
3466 global rowmenuid selectedline lineid
3404
3467
3405 if {![info exists selectedline]} return
3468 if {![info exists selectedline]} return
3406 if {$dirn} {
3469 if {$dirn} {
3407 set oldid $lineid($selectedline)
3470 set oldid $lineid($selectedline)
3408 set newid $rowmenuid
3471 set newid $rowmenuid
3409 } else {
3472 } else {
3410 set oldid $rowmenuid
3473 set oldid $rowmenuid
3411 set newid $lineid($selectedline)
3474 set newid $lineid($selectedline)
3412 }
3475 }
3413 addtohistory [list doseldiff $oldid $newid]
3476 addtohistory [list doseldiff $oldid $newid]
3414 doseldiff $oldid $newid
3477 doseldiff $oldid $newid
3415 }
3478 }
3416
3479
3417 proc doseldiff {oldid newid} {
3480 proc doseldiff {oldid newid} {
3418 global ctext cflist
3481 global ctext cflist
3419 global commitinfo
3482 global commitinfo
3420
3483
3421 $ctext conf -state normal
3484 $ctext conf -state normal
3422 $ctext delete 0.0 end
3485 $ctext delete 0.0 end
3423 $ctext mark set fmark.0 0.0
3486 $ctext mark set fmark.0 0.0
3424 $ctext mark gravity fmark.0 left
3487 $ctext mark gravity fmark.0 left
3425 $cflist delete 0 end
3488 $cflist delete 0 end
3426 $cflist insert end "Top"
3489 $cflist insert end "Top"
3427 $ctext insert end "From "
3490 $ctext insert end "From "
3428 $ctext tag conf link -foreground blue -underline 1
3491 $ctext tag conf link -foreground blue -underline 1
3429 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
3492 $ctext tag bind link <Enter> { %W configure -cursor hand2 }
3430 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
3493 $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
3431 $ctext tag bind link0 <1> [list selbyid $oldid]
3494 $ctext tag bind link0 <1> [list selbyid $oldid]
3432 $ctext insert end $oldid [list link link0]
3495 $ctext insert end $oldid [list link link0]
3433 $ctext insert end "\n "
3496 $ctext insert end "\n "
3434 $ctext insert end [lindex $commitinfo($oldid) 0]
3497 $ctext insert end [lindex $commitinfo($oldid) 0]
3435 $ctext insert end "\n\nTo "
3498 $ctext insert end "\n\nTo "
3436 $ctext tag bind link1 <1> [list selbyid $newid]
3499 $ctext tag bind link1 <1> [list selbyid $newid]
3437 $ctext insert end $newid [list link link1]
3500 $ctext insert end $newid [list link link1]
3438 $ctext insert end "\n "
3501 $ctext insert end "\n "
3439 $ctext insert end [lindex $commitinfo($newid) 0]
3502 $ctext insert end [lindex $commitinfo($newid) 0]
3440 $ctext insert end "\n"
3503 $ctext insert end "\n"
3441 $ctext conf -state disabled
3504 $ctext conf -state disabled
3442 $ctext tag delete Comments
3505 $ctext tag delete Comments
3443 $ctext tag remove found 1.0 end
3506 $ctext tag remove found 1.0 end
3444 startdiff [list $newid $oldid]
3507 startdiff [list $newid $oldid]
3445 }
3508 }
3446
3509
3447 proc mkpatch {} {
3510 proc mkpatch {} {
3448 global rowmenuid currentid commitinfo patchtop patchnum
3511 global rowmenuid currentid commitinfo patchtop patchnum
3449
3512
3450 if {![info exists currentid]} return
3513 if {![info exists currentid]} return
3451 set oldid $currentid
3514 set oldid $currentid
3452 set oldhead [lindex $commitinfo($oldid) 0]
3515 set oldhead [lindex $commitinfo($oldid) 0]
3453 set newid $rowmenuid
3516 set newid $rowmenuid
3454 set newhead [lindex $commitinfo($newid) 0]
3517 set newhead [lindex $commitinfo($newid) 0]
3455 set top .patch
3518 set top .patch
3456 set patchtop $top
3519 set patchtop $top
3457 catch {destroy $top}
3520 catch {destroy $top}
3458 toplevel $top
3521 toplevel $top
3459 label $top.title -text "Generate patch"
3522 label $top.title -text "Generate patch"
3460 grid $top.title - -pady 10
3523 grid $top.title - -pady 10
3461 label $top.from -text "From:"
3524 label $top.from -text "From:"
3462 entry $top.fromsha1 -width 40 -relief flat
3525 entry $top.fromsha1 -width 40 -relief flat
3463 $top.fromsha1 insert 0 $oldid
3526 $top.fromsha1 insert 0 $oldid
3464 $top.fromsha1 conf -state readonly
3527 $top.fromsha1 conf -state readonly
3465 grid $top.from $top.fromsha1 -sticky w
3528 grid $top.from $top.fromsha1 -sticky w
3466 entry $top.fromhead -width 60 -relief flat
3529 entry $top.fromhead -width 60 -relief flat
3467 $top.fromhead insert 0 $oldhead
3530 $top.fromhead insert 0 $oldhead
3468 $top.fromhead conf -state readonly
3531 $top.fromhead conf -state readonly
3469 grid x $top.fromhead -sticky w
3532 grid x $top.fromhead -sticky w
3470 label $top.to -text "To:"
3533 label $top.to -text "To:"
3471 entry $top.tosha1 -width 40 -relief flat
3534 entry $top.tosha1 -width 40 -relief flat
3472 $top.tosha1 insert 0 $newid
3535 $top.tosha1 insert 0 $newid
3473 $top.tosha1 conf -state readonly
3536 $top.tosha1 conf -state readonly
3474 grid $top.to $top.tosha1 -sticky w
3537 grid $top.to $top.tosha1 -sticky w
3475 entry $top.tohead -width 60 -relief flat
3538 entry $top.tohead -width 60 -relief flat
3476 $top.tohead insert 0 $newhead
3539 $top.tohead insert 0 $newhead
3477 $top.tohead conf -state readonly
3540 $top.tohead conf -state readonly
3478 grid x $top.tohead -sticky w
3541 grid x $top.tohead -sticky w
3479 button $top.rev -text "Reverse" -command mkpatchrev -padx 5
3542 button $top.rev -text "Reverse" -command mkpatchrev -padx 5
3480 grid $top.rev x -pady 10
3543 grid $top.rev x -pady 10
3481 label $top.flab -text "Output file:"
3544 label $top.flab -text "Output file:"
3482 entry $top.fname -width 60
3545 entry $top.fname -width 60
3483 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
3546 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
3484 incr patchnum
3547 incr patchnum
3485 grid $top.flab $top.fname -sticky w
3548 grid $top.flab $top.fname -sticky w
3486 frame $top.buts
3549 frame $top.buts
3487 button $top.buts.gen -text "Generate" -command mkpatchgo
3550 button $top.buts.gen -text "Generate" -command mkpatchgo
3488 button $top.buts.can -text "Cancel" -command mkpatchcan
3551 button $top.buts.can -text "Cancel" -command mkpatchcan
3489 grid $top.buts.gen $top.buts.can
3552 grid $top.buts.gen $top.buts.can
3490 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3553 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3491 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3554 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3492 grid $top.buts - -pady 10 -sticky ew
3555 grid $top.buts - -pady 10 -sticky ew
3493 focus $top.fname
3556 focus $top.fname
3494 }
3557 }
3495
3558
3496 proc mkpatchrev {} {
3559 proc mkpatchrev {} {
3497 global patchtop
3560 global patchtop
3498
3561
3499 set oldid [$patchtop.fromsha1 get]
3562 set oldid [$patchtop.fromsha1 get]
3500 set oldhead [$patchtop.fromhead get]
3563 set oldhead [$patchtop.fromhead get]
3501 set newid [$patchtop.tosha1 get]
3564 set newid [$patchtop.tosha1 get]
3502 set newhead [$patchtop.tohead get]
3565 set newhead [$patchtop.tohead get]
3503 foreach e [list fromsha1 fromhead tosha1 tohead] \
3566 foreach e [list fromsha1 fromhead tosha1 tohead] \
3504 v [list $newid $newhead $oldid $oldhead] {
3567 v [list $newid $newhead $oldid $oldhead] {
3505 $patchtop.$e conf -state normal
3568 $patchtop.$e conf -state normal
3506 $patchtop.$e delete 0 end
3569 $patchtop.$e delete 0 end
3507 $patchtop.$e insert 0 $v
3570 $patchtop.$e insert 0 $v
3508 $patchtop.$e conf -state readonly
3571 $patchtop.$e conf -state readonly
3509 }
3572 }
3510 }
3573 }
3511
3574
3512 proc mkpatchgo {} {
3575 proc mkpatchgo {} {
3513 global patchtop env
3576 global patchtop env
3514
3577
3515 set oldid [$patchtop.fromsha1 get]
3578 set oldid [$patchtop.fromsha1 get]
3516 set newid [$patchtop.tosha1 get]
3579 set newid [$patchtop.tosha1 get]
3517 set fname [$patchtop.fname get]
3580 set fname [$patchtop.fname get]
3518 if {[catch {exec $env(HG) --config ui.report_untrusted=false debug-diff-tree -p $oldid $newid >$fname &} err]} {
3581 if {[catch {exec $env(HG) --config ui.report_untrusted=false debug-diff-tree -p $oldid $newid >$fname &} err]} {
3519 error_popup "Error creating patch: $err"
3582 error_popup "Error creating patch: $err"
3520 }
3583 }
3521 catch {destroy $patchtop}
3584 catch {destroy $patchtop}
3522 unset patchtop
3585 unset patchtop
3523 }
3586 }
3524
3587
3525 proc mkpatchcan {} {
3588 proc mkpatchcan {} {
3526 global patchtop
3589 global patchtop
3527
3590
3528 catch {destroy $patchtop}
3591 catch {destroy $patchtop}
3529 unset patchtop
3592 unset patchtop
3530 }
3593 }
3531
3594
3532 proc mktag {} {
3595 proc mktag {} {
3533 global rowmenuid mktagtop commitinfo
3596 global rowmenuid mktagtop commitinfo
3534
3597
3535 set top .maketag
3598 set top .maketag
3536 set mktagtop $top
3599 set mktagtop $top
3537 catch {destroy $top}
3600 catch {destroy $top}
3538 toplevel $top
3601 toplevel $top
3539 label $top.title -text "Create tag"
3602 label $top.title -text "Create tag"
3540 grid $top.title - -pady 10
3603 grid $top.title - -pady 10
3541 label $top.id -text "ID:"
3604 label $top.id -text "ID:"
3542 entry $top.sha1 -width 40 -relief flat
3605 entry $top.sha1 -width 40 -relief flat
3543 $top.sha1 insert 0 $rowmenuid
3606 $top.sha1 insert 0 $rowmenuid
3544 $top.sha1 conf -state readonly
3607 $top.sha1 conf -state readonly
3545 grid $top.id $top.sha1 -sticky w
3608 grid $top.id $top.sha1 -sticky w
3546 entry $top.head -width 60 -relief flat
3609 entry $top.head -width 60 -relief flat
3547 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
3610 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
3548 $top.head conf -state readonly
3611 $top.head conf -state readonly
3549 grid x $top.head -sticky w
3612 grid x $top.head -sticky w
3550 label $top.tlab -text "Tag name:"
3613 label $top.tlab -text "Tag name:"
3551 entry $top.tag -width 60
3614 entry $top.tag -width 60
3552 grid $top.tlab $top.tag -sticky w
3615 grid $top.tlab $top.tag -sticky w
3553 frame $top.buts
3616 frame $top.buts
3554 button $top.buts.gen -text "Create" -command mktaggo
3617 button $top.buts.gen -text "Create" -command mktaggo
3555 button $top.buts.can -text "Cancel" -command mktagcan
3618 button $top.buts.can -text "Cancel" -command mktagcan
3556 grid $top.buts.gen $top.buts.can
3619 grid $top.buts.gen $top.buts.can
3557 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3620 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3558 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3621 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3559 grid $top.buts - -pady 10 -sticky ew
3622 grid $top.buts - -pady 10 -sticky ew
3560 focus $top.tag
3623 focus $top.tag
3561 }
3624 }
3562
3625
3563 proc domktag {} {
3626 proc domktag {} {
3564 global mktagtop env tagids idtags
3627 global mktagtop env tagids idtags
3565
3628
3566 set id [$mktagtop.sha1 get]
3629 set id [$mktagtop.sha1 get]
3567 set tag [$mktagtop.tag get]
3630 set tag [$mktagtop.tag get]
3568 if {$tag == {}} {
3631 if {$tag == {}} {
3569 error_popup "No tag name specified"
3632 error_popup "No tag name specified"
3570 return
3633 return
3571 }
3634 }
3572 if {[info exists tagids($tag)]} {
3635 if {[info exists tagids($tag)]} {
3573 error_popup "Tag \"$tag\" already exists"
3636 error_popup "Tag \"$tag\" already exists"
3574 return
3637 return
3575 }
3638 }
3576 if {[catch {
3639 if {[catch {
3577 set out [exec $env(HG) --config ui.report_untrusted=false tag -r $id $tag]
3640 set out [exec $env(HG) --config ui.report_untrusted=false tag -r $id $tag]
3578 } err]} {
3641 } err]} {
3579 error_popup "Error creating tag: $err"
3642 error_popup "Error creating tag: $err"
3580 return
3643 return
3581 }
3644 }
3582
3645
3583 set tagids($tag) $id
3646 set tagids($tag) $id
3584 lappend idtags($id) $tag
3647 lappend idtags($id) $tag
3585 redrawtags $id
3648 redrawtags $id
3586 }
3649 }
3587
3650
3588 proc redrawtags {id} {
3651 proc redrawtags {id} {
3589 global canv linehtag idline idpos selectedline
3652 global canv linehtag idline idpos selectedline
3590
3653
3591 if {![info exists idline($id)]} return
3654 if {![info exists idline($id)]} return
3592 $canv delete tag.$id
3655 $canv delete tag.$id
3593 set xt [eval drawtags $id $idpos($id)]
3656 set xt [eval drawtags $id $idpos($id)]
3594 $canv coords $linehtag($idline($id)) $xt [lindex $idpos($id) 2]
3657 $canv coords $linehtag($idline($id)) $xt [lindex $idpos($id) 2]
3595 if {[info exists selectedline] && $selectedline == $idline($id)} {
3658 if {[info exists selectedline] && $selectedline == $idline($id)} {
3596 selectline $selectedline 0
3659 selectline $selectedline 0
3597 }
3660 }
3598 }
3661 }
3599
3662
3600 proc mktagcan {} {
3663 proc mktagcan {} {
3601 global mktagtop
3664 global mktagtop
3602
3665
3603 catch {destroy $mktagtop}
3666 catch {destroy $mktagtop}
3604 unset mktagtop
3667 unset mktagtop
3605 }
3668 }
3606
3669
3607 proc mktaggo {} {
3670 proc mktaggo {} {
3608 domktag
3671 domktag
3609 mktagcan
3672 mktagcan
3610 }
3673 }
3611
3674
3612 proc writecommit {} {
3675 proc writecommit {} {
3613 global rowmenuid wrcomtop commitinfo wrcomcmd
3676 global rowmenuid wrcomtop commitinfo wrcomcmd
3614
3677
3615 set top .writecommit
3678 set top .writecommit
3616 set wrcomtop $top
3679 set wrcomtop $top
3617 catch {destroy $top}
3680 catch {destroy $top}
3618 toplevel $top
3681 toplevel $top
3619 label $top.title -text "Write commit to file"
3682 label $top.title -text "Write commit to file"
3620 grid $top.title - -pady 10
3683 grid $top.title - -pady 10
3621 label $top.id -text "ID:"
3684 label $top.id -text "ID:"
3622 entry $top.sha1 -width 40 -relief flat
3685 entry $top.sha1 -width 40 -relief flat
3623 $top.sha1 insert 0 $rowmenuid
3686 $top.sha1 insert 0 $rowmenuid
3624 $top.sha1 conf -state readonly
3687 $top.sha1 conf -state readonly
3625 grid $top.id $top.sha1 -sticky w
3688 grid $top.id $top.sha1 -sticky w
3626 entry $top.head -width 60 -relief flat
3689 entry $top.head -width 60 -relief flat
3627 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
3690 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
3628 $top.head conf -state readonly
3691 $top.head conf -state readonly
3629 grid x $top.head -sticky w
3692 grid x $top.head -sticky w
3630 label $top.clab -text "Command:"
3693 label $top.clab -text "Command:"
3631 entry $top.cmd -width 60 -textvariable wrcomcmd
3694 entry $top.cmd -width 60 -textvariable wrcomcmd
3632 grid $top.clab $top.cmd -sticky w -pady 10
3695 grid $top.clab $top.cmd -sticky w -pady 10
3633 label $top.flab -text "Output file:"
3696 label $top.flab -text "Output file:"
3634 entry $top.fname -width 60
3697 entry $top.fname -width 60
3635 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
3698 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
3636 grid $top.flab $top.fname -sticky w
3699 grid $top.flab $top.fname -sticky w
3637 frame $top.buts
3700 frame $top.buts
3638 button $top.buts.gen -text "Write" -command wrcomgo
3701 button $top.buts.gen -text "Write" -command wrcomgo
3639 button $top.buts.can -text "Cancel" -command wrcomcan
3702 button $top.buts.can -text "Cancel" -command wrcomcan
3640 grid $top.buts.gen $top.buts.can
3703 grid $top.buts.gen $top.buts.can
3641 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3704 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3642 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3705 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3643 grid $top.buts - -pady 10 -sticky ew
3706 grid $top.buts - -pady 10 -sticky ew
3644 focus $top.fname
3707 focus $top.fname
3645 }
3708 }
3646
3709
3647 proc wrcomgo {} {
3710 proc wrcomgo {} {
3648 global wrcomtop
3711 global wrcomtop
3649
3712
3650 set id [$wrcomtop.sha1 get]
3713 set id [$wrcomtop.sha1 get]
3651 set cmd "echo $id | [$wrcomtop.cmd get]"
3714 set cmd "echo $id | [$wrcomtop.cmd get]"
3652 set fname [$wrcomtop.fname get]
3715 set fname [$wrcomtop.fname get]
3653 if {[catch {exec sh -c $cmd > $fname &} err]} {
3716 if {[catch {exec sh -c $cmd > $fname &} err]} {
3654 error_popup "Error writing commit: $err"
3717 error_popup "Error writing commit: $err"
3655 }
3718 }
3656 catch {destroy $wrcomtop}
3719 catch {destroy $wrcomtop}
3657 unset wrcomtop
3720 unset wrcomtop
3658 }
3721 }
3659
3722
3660 proc wrcomcan {} {
3723 proc wrcomcan {} {
3661 global wrcomtop
3724 global wrcomtop
3662
3725
3663 catch {destroy $wrcomtop}
3726 catch {destroy $wrcomtop}
3664 unset wrcomtop
3727 unset wrcomtop
3665 }
3728 }
3666
3729
3667 proc listrefs {id} {
3730 proc listrefs {id} {
3668 global idtags idheads idotherrefs
3731 global idtags idheads idotherrefs
3669
3732
3670 set x {}
3733 set x {}
3671 if {[info exists idtags($id)]} {
3734 if {[info exists idtags($id)]} {
3672 set x $idtags($id)
3735 set x $idtags($id)
3673 }
3736 }
3674 set y {}
3737 set y {}
3675 if {[info exists idheads($id)]} {
3738 if {[info exists idheads($id)]} {
3676 set y $idheads($id)
3739 set y $idheads($id)
3677 }
3740 }
3678 set z {}
3741 set z {}
3679 if {[info exists idotherrefs($id)]} {
3742 if {[info exists idotherrefs($id)]} {
3680 set z $idotherrefs($id)
3743 set z $idotherrefs($id)
3681 }
3744 }
3682 return [list $x $y $z]
3745 return [list $x $y $z]
3683 }
3746 }
3684
3747
3685 proc rereadrefs {} {
3748 proc rereadrefs {} {
3686 global idtags idheads idotherrefs
3749 global idtags idheads idotherrefs
3687 global tagids headids otherrefids
3750 global tagids headids otherrefids
3688
3751
3689 set refids [concat [array names idtags] \
3752 set refids [concat [array names idtags] \
3690 [array names idheads] [array names idotherrefs]]
3753 [array names idheads] [array names idotherrefs]]
3691 foreach id $refids {
3754 foreach id $refids {
3692 if {![info exists ref($id)]} {
3755 if {![info exists ref($id)]} {
3693 set ref($id) [listrefs $id]
3756 set ref($id) [listrefs $id]
3694 }
3757 }
3695 }
3758 }
3696 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
3759 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
3697 catch {unset $v}
3760 catch {unset $v}
3698 }
3761 }
3699 readrefs
3762 readrefs
3700 set refids [lsort -unique [concat $refids [array names idtags] \
3763 set refids [lsort -unique [concat $refids [array names idtags] \
3701 [array names idheads] [array names idotherrefs]]]
3764 [array names idheads] [array names idotherrefs]]]
3702 foreach id $refids {
3765 foreach id $refids {
3703 set v [listrefs $id]
3766 set v [listrefs $id]
3704 if {![info exists ref($id)] || $ref($id) != $v} {
3767 if {![info exists ref($id)] || $ref($id) != $v} {
3705 redrawtags $id
3768 redrawtags $id
3706 }
3769 }
3707 }
3770 }
3708 }
3771 }
3709
3772
3710 proc vdiff {withparent} {
3773 proc vdiff {withparent} {
3711 global env rowmenuid selectedline lineid hgvdiff
3774 global env rowmenuid selectedline lineid hgvdiff
3712
3775
3713 if {![info exists rowmenuid]} return
3776 if {![info exists rowmenuid]} return
3714 set curid $rowmenuid
3777 set curid $rowmenuid
3715
3778
3716 if {$withparent} {
3779 if {$withparent} {
3717 set parents [exec $env(HG) --config ui.report_untrusted=false parents --rev $curid --template "{node}\n"]
3780 set parents [exec $env(HG) --config ui.report_untrusted=false parents --rev $curid --template "{node}\n"]
3718 set firstparent [lindex [split $parents "\n"] 0]
3781 set firstparent [lindex [split $parents "\n"] 0]
3719 set otherid $firstparent
3782 set otherid $firstparent
3720 } else {
3783 } else {
3721 if {![info exists selectedline]} return
3784 if {![info exists selectedline]} return
3722 set otherid $lineid($selectedline)
3785 set otherid $lineid($selectedline)
3723 }
3786 }
3724 set range "$otherid:$curid"
3787 set range "$otherid:$curid"
3725 if {[catch {exec $env(HG) --config ui.report_untrusted=false $hgvdiff -r $range} err]} {
3788 if {[catch {exec $env(HG) --config ui.report_untrusted=false $hgvdiff -r $range} err]} {
3726 # Ignore errors, this is just visualization
3789 # Ignore errors, this is just visualization
3727 }
3790 }
3728 }
3791 }
3729
3792
3730 proc showtag {tag isnew} {
3793 proc showtag {tag isnew} {
3731 global ctext cflist tagcontents tagids linknum
3794 global ctext cflist tagcontents tagids linknum
3732
3795
3733 if {$isnew} {
3796 if {$isnew} {
3734 addtohistory [list showtag $tag 0]
3797 addtohistory [list showtag $tag 0]
3735 }
3798 }
3736 $ctext conf -state normal
3799 $ctext conf -state normal
3737 $ctext delete 0.0 end
3800 $ctext delete 0.0 end
3738 set linknum 0
3801 set linknum 0
3739 if {[info exists tagcontents($tag)]} {
3802 if {[info exists tagcontents($tag)]} {
3740 set text $tagcontents($tag)
3803 set text $tagcontents($tag)
3741 } else {
3804 } else {
3742 set text "Tag: $tag\nId: $tagids($tag)"
3805 set text "Tag: $tag\nId: $tagids($tag)"
3743 }
3806 }
3744 appendwithlinks $text
3807 appendwithlinks $text
3745 $ctext conf -state disabled
3808 $ctext conf -state disabled
3746 $cflist delete 0 end
3809 $cflist delete 0 end
3747 }
3810 }
3748
3811
3749 proc doquit {} {
3812 proc doquit {} {
3750 global stopped
3813 global stopped
3751 set stopped 100
3814 set stopped 100
3752 destroy .
3815 destroy .
3753 }
3816 }
3754
3817
3755 proc getconfig {} {
3818 proc getconfig {} {
3756 global env
3819 global env
3757
3820
3758 set lines [exec $env(HG) debug-config]
3821 set lines [exec $env(HG) debug-config]
3759 regsub -all "\r\n" $lines "\n" config
3822 regsub -all "\r\n" $lines "\n" config
3760 set config {}
3823 set config {}
3761 foreach line [split $lines "\n"] {
3824 foreach line [split $lines "\n"] {
3762 regsub "^(k|v)=" $line "" line
3825 regsub "^(k|v)=" $line "" line
3763 lappend config $line
3826 lappend config $line
3764 }
3827 }
3765 return $config
3828 return $config
3766 }
3829 }
3767
3830
3768 # defaults...
3831 # defaults...
3769 set datemode 0
3832 set datemode 0
3770 set boldnames 0
3833 set boldnames 0
3771 set diffopts "-U 5 -p"
3834 set diffopts "-U 5 -p"
3772 set wrcomcmd "\"\$HG\" --config ui.report_untrusted=false debug-diff-tree --stdin -p --pretty"
3835 set wrcomcmd "\"\$HG\" --config ui.report_untrusted=false debug-diff-tree --stdin -p --pretty"
3773
3836
3774 set mainfont {Helvetica 9}
3837 set mainfont {Helvetica 9}
3838 set curidfont {}
3775 set textfont {Courier 9}
3839 set textfont {Courier 9}
3776 set findmergefiles 0
3840 set findmergefiles 0
3777 set gaudydiff 0
3841 set gaudydiff 0
3778 set maxgraphpct 50
3842 set maxgraphpct 50
3779 set maxwidth 16
3843 set maxwidth 16
3780
3844
3781 set colors {green red blue magenta darkgrey brown orange}
3845 set colors {green red blue magenta darkgrey brown orange}
3846 set authorcolors {
3847 deeppink mediumorchid blue burlywood4 goldenrod slateblue red2 navy dimgrey
3848 }
3782
3849
3783 catch {source ~/.gitk}
3850 catch {source ~/.gitk}
3784
3851
3852 if {$curidfont == ""} { # initialize late based on current mainfont
3853 set curidfont "$mainfont bold italic underline"
3854 }
3855
3785 set namefont $mainfont
3856 set namefont $mainfont
3786 if {$boldnames} {
3857 if {$boldnames} {
3787 lappend namefont bold
3858 lappend namefont bold
3788 }
3859 }
3789
3860
3790 set revtreeargs {}
3861 set revtreeargs {}
3791 foreach arg $argv {
3862 foreach arg $argv {
3792 switch -regexp -- $arg {
3863 switch -regexp -- $arg {
3793 "^$" { }
3864 "^$" { }
3794 "^-b" { set boldnames 1 }
3865 "^-b" { set boldnames 1 }
3795 "^-d" { set datemode 1 }
3866 "^-d" { set datemode 1 }
3796 default {
3867 default {
3797 lappend revtreeargs $arg
3868 lappend revtreeargs $arg
3798 }
3869 }
3799 }
3870 }
3800 }
3871 }
3801
3872
3802 set history {}
3873 set history {}
3803 set historyindex 0
3874 set historyindex 0
3804
3875
3805 set stopped 0
3876 set stopped 0
3806 set redisplaying 0
3877 set redisplaying 0
3807 set stuffsaved 0
3878 set stuffsaved 0
3808 set patchnum 0
3879 set patchnum 0
3809
3880
3810 array set config [getconfig]
3881 array set config [getconfig]
3811 set hgvdiff $config(vdiff)
3882 set hgvdiff $config(vdiff)
3812 setcoords
3883 setcoords
3813 makewindow
3884 makewindow
3814 readrefs
3885 readrefs
3815 set hgroot [exec $env(HG) root]
3886 set hgroot [exec $env(HG) root]
3816 wm title . "hgk $hgroot"
3887 wm title . "hgk $hgroot"
3817 getcommits $revtreeargs
3888 getcommits $revtreeargs
General Comments 0
You need to be logged in to leave comments. Login now