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