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