]> git.ipfire.org Git - thirdparty/git.git/blame - gitk
Fixed GPF in fast-import caused by unterminated linked list.
[thirdparty/git.git] / gitk
CommitLineData
1db95b00
PM
1#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
9e026d39 3exec wish "$0" -- "$@"
1db95b00
PM
4
5# Copyright (C) 2005 Paul Mackerras. All rights reserved.
6# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
73b6a6cb
JH
10proc gitdir {} {
11 global env
12 if {[info exists env(GIT_DIR)]} {
13 return $env(GIT_DIR)
14 } else {
15 return ".git"
16 }
17}
18
da7c24dd 19proc start_rev_list {view} {
466e4fdd 20 global startmsecs nextupdate ncmupdate
9f1afe05 21 global commfd leftover tclencoding datemode
098dd8a3 22 global viewargs viewfiles commitidx
9ccbdfbf 23
9ccbdfbf 24 set startmsecs [clock clicks -milliseconds]
2ed49d54 25 set nextupdate [expr {$startmsecs + 100}]
b664550c 26 set ncmupdate 1
da7c24dd 27 set commitidx($view) 0
098dd8a3 28 set args $viewargs($view)
da7c24dd
PM
29 if {$viewfiles($view) ne {}} {
30 set args [concat $args "--" $viewfiles($view)]
a8aaf19c 31 }
9f1afe05
PM
32 set order "--topo-order"
33 if {$datemode} {
34 set order "--date-order"
35 }
418c4c7b 36 if {[catch {
8974c6f9 37 set fd [open [concat | git rev-list --header $order \
da7c24dd 38 --parents --boundary --default HEAD $args] r]
418c4c7b 39 } err]} {
8974c6f9 40 puts stderr "Error executing git rev-list: $err"
1d10f36d
PM
41 exit 1
42 }
da7c24dd
PM
43 set commfd($view) $fd
44 set leftover($view) {}
45 fconfigure $fd -blocking 0 -translation lf
fd8ccbec 46 if {$tclencoding != {}} {
da7c24dd 47 fconfigure $fd -encoding $tclencoding
fd8ccbec 48 }
da7c24dd
PM
49 fileevent $fd readable [list getcommitlines $fd $view]
50 nowbusy $view
38ad0910
PM
51}
52
22626ef4 53proc stop_rev_list {} {
da7c24dd 54 global commfd curview
22626ef4 55
da7c24dd
PM
56 if {![info exists commfd($curview)]} return
57 set fd $commfd($curview)
22626ef4 58 catch {
da7c24dd 59 set pid [pid $fd]
22626ef4
PM
60 exec kill $pid
61 }
da7c24dd
PM
62 catch {close $fd}
63 unset commfd($curview)
22626ef4
PM
64}
65
a8aaf19c 66proc getcommits {} {
da7c24dd 67 global phase canv mainfont curview
38ad0910 68
38ad0910 69 set phase getcommits
da7c24dd
PM
70 initlayout
71 start_rev_list $curview
098dd8a3 72 show_status "Reading commits..."
1d10f36d
PM
73}
74
da7c24dd 75proc getcommitlines {fd view} {
8ed16484 76 global commitlisted nextupdate
da7c24dd 77 global leftover commfd
8ed16484 78 global displayorder commitidx commitrow commitdata
da7c24dd
PM
79 global parentlist childlist children curview hlview
80 global vparentlist vchildlist vdisporder vcmitlisted
9ccbdfbf 81
da7c24dd 82 set stuff [read $fd]
b490a991 83 if {$stuff == {}} {
da7c24dd 84 if {![eof $fd]} return
098dd8a3 85 global viewname
da7c24dd 86 unset commfd($view)
098dd8a3 87 notbusy $view
f0654861 88 # set it blocking so we wait for the process to terminate
da7c24dd 89 fconfigure $fd -blocking 1
098dd8a3
PM
90 if {[catch {close $fd} err]} {
91 set fv {}
92 if {$view != $curview} {
93 set fv " for the \"$viewname($view)\" view"
da7c24dd 94 }
098dd8a3
PM
95 if {[string range $err 0 4] == "usage"} {
96 set err "Gitk: error reading commits$fv:\
8974c6f9 97 bad arguments to git rev-list."
098dd8a3
PM
98 if {$viewname($view) eq "Command line"} {
99 append err \
8974c6f9 100 " (Note: arguments to gitk are passed to git rev-list\
098dd8a3
PM
101 to allow selection of commits to be displayed.)"
102 }
103 } else {
104 set err "Error reading commits$fv: $err"
105 }
106 error_popup $err
1d10f36d 107 }
098dd8a3
PM
108 if {$view == $curview} {
109 after idle finishcommits
9a40c50c 110 }
098dd8a3 111 return
9a40c50c 112 }
b490a991 113 set start 0
8f7d0cec 114 set gotsome 0
b490a991
PM
115 while 1 {
116 set i [string first "\0" $stuff $start]
117 if {$i < 0} {
da7c24dd 118 append leftover($view) [string range $stuff $start end]
9f1afe05 119 break
9ccbdfbf 120 }
b490a991 121 if {$start == 0} {
da7c24dd 122 set cmit $leftover($view)
8f7d0cec 123 append cmit [string range $stuff 0 [expr {$i - 1}]]
da7c24dd 124 set leftover($view) {}
8f7d0cec
PM
125 } else {
126 set cmit [string range $stuff $start [expr {$i - 1}]]
b490a991
PM
127 }
128 set start [expr {$i + 1}]
e5ea701b
PM
129 set j [string first "\n" $cmit]
130 set ok 0
16c1ff96 131 set listed 1
e5ea701b
PM
132 if {$j >= 0} {
133 set ids [string range $cmit 0 [expr {$j - 1}]]
16c1ff96
PM
134 if {[string range $ids 0 0] == "-"} {
135 set listed 0
136 set ids [string range $ids 1 end]
137 }
e5ea701b
PM
138 set ok 1
139 foreach id $ids {
8f7d0cec 140 if {[string length $id] != 40} {
e5ea701b
PM
141 set ok 0
142 break
143 }
144 }
145 }
146 if {!$ok} {
7e952e79
PM
147 set shortcmit $cmit
148 if {[string length $shortcmit] > 80} {
149 set shortcmit "[string range $shortcmit 0 80]..."
150 }
8974c6f9 151 error_popup "Can't parse git rev-list output: {$shortcmit}"
b490a991
PM
152 exit 1
153 }
e5ea701b 154 set id [lindex $ids 0]
16c1ff96
PM
155 if {$listed} {
156 set olds [lrange $ids 1 end]
50b44ece 157 set i 0
79b2c75e 158 foreach p $olds {
50b44ece 159 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
da7c24dd 160 lappend children($view,$p) $id
50b44ece
PM
161 }
162 incr i
79b2c75e 163 }
16c1ff96
PM
164 } else {
165 set olds {}
166 }
da7c24dd
PM
167 if {![info exists children($view,$id)]} {
168 set children($view,$id) {}
79b2c75e 169 }
f7a3e8d2 170 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
da7c24dd
PM
171 set commitrow($view,$id) $commitidx($view)
172 incr commitidx($view)
173 if {$view == $curview} {
174 lappend parentlist $olds
175 lappend childlist $children($view,$id)
176 lappend displayorder $id
177 lappend commitlisted $listed
178 } else {
179 lappend vparentlist($view) $olds
180 lappend vchildlist($view) $children($view,$id)
181 lappend vdisporder($view) $id
182 lappend vcmitlisted($view) $listed
183 }
8f7d0cec
PM
184 set gotsome 1
185 }
186 if {$gotsome} {
da7c24dd
PM
187 if {$view == $curview} {
188 layoutmore
189 } elseif {[info exists hlview] && $view == $hlview} {
908c3585 190 vhighlightmore
da7c24dd 191 }
9f1afe05 192 }
9f1afe05 193 if {[clock clicks -milliseconds] >= $nextupdate} {
da7c24dd 194 doupdate
9ccbdfbf
PM
195 }
196}
197
da7c24dd 198proc doupdate {} {
b664550c 199 global commfd nextupdate numcommits ncmupdate
9ccbdfbf 200
da7c24dd
PM
201 foreach v [array names commfd] {
202 fileevent $commfd($v) readable {}
b664550c 203 }
9ccbdfbf 204 update
b664550c
PM
205 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
206 if {$numcommits < 100} {
207 set ncmupdate [expr {$numcommits + 1}]
208 } elseif {$numcommits < 10000} {
209 set ncmupdate [expr {$numcommits + 10}]
210 } else {
211 set ncmupdate [expr {$numcommits + 100}]
212 }
da7c24dd
PM
213 foreach v [array names commfd] {
214 set fd $commfd($v)
215 fileevent $fd readable [list getcommitlines $fd $v]
b664550c 216 }
1db95b00
PM
217}
218
219proc readcommit {id} {
8974c6f9 220 if {[catch {set contents [exec git cat-file commit $id]}]} return
8f7d0cec 221 parsecommit $id $contents 0
b490a991
PM
222}
223
50b44ece 224proc updatecommits {} {
098dd8a3 225 global viewdata curview phase displayorder
908c3585 226 global children commitrow selectedline thickerline
50b44ece 227
22626ef4
PM
228 if {$phase ne {}} {
229 stop_rev_list
230 set phase {}
fd8ccbec 231 }
d94f8cd6 232 set n $curview
da7c24dd
PM
233 foreach id $displayorder {
234 catch {unset children($n,$id)}
235 catch {unset commitrow($n,$id)}
236 }
d94f8cd6 237 set curview -1
908c3585
PM
238 catch {unset selectedline}
239 catch {unset thickerline}
d94f8cd6 240 catch {unset viewdata($n)}
2d71bccc 241 discardallcommits
fd8ccbec 242 readrefs
d94f8cd6 243 showview $n
fd8ccbec
PM
244}
245
8f7d0cec 246proc parsecommit {id contents listed} {
b5c2f306
SV
247 global commitinfo cdate
248
249 set inhdr 1
250 set comment {}
251 set headline {}
252 set auname {}
253 set audate {}
254 set comname {}
255 set comdate {}
232475d3
PM
256 set hdrend [string first "\n\n" $contents]
257 if {$hdrend < 0} {
258 # should never happen...
259 set hdrend [string length $contents]
260 }
261 set header [string range $contents 0 [expr {$hdrend - 1}]]
262 set comment [string range $contents [expr {$hdrend + 2}] end]
263 foreach line [split $header "\n"] {
264 set tag [lindex $line 0]
265 if {$tag == "author"} {
266 set audate [lindex $line end-1]
267 set auname [lrange $line 1 end-2]
268 } elseif {$tag == "committer"} {
269 set comdate [lindex $line end-1]
270 set comname [lrange $line 1 end-2]
1db95b00
PM
271 }
272 }
232475d3
PM
273 set headline {}
274 # take the first line of the comment as the headline
275 set i [string first "\n" $comment]
276 if {$i >= 0} {
277 set headline [string trim [string range $comment 0 $i]]
f6e2869f
PM
278 } else {
279 set headline $comment
232475d3
PM
280 }
281 if {!$listed} {
8974c6f9
TH
282 # git rev-list indents the comment by 4 spaces;
283 # if we got this via git cat-file, add the indentation
232475d3
PM
284 set newcomment {}
285 foreach line [split $comment "\n"] {
286 append newcomment " "
287 append newcomment $line
f6e2869f 288 append newcomment "\n"
232475d3
PM
289 }
290 set comment $newcomment
1db95b00
PM
291 }
292 if {$comdate != {}} {
cfb4563c 293 set cdate($id) $comdate
1db95b00 294 }
e5c2d856
PM
295 set commitinfo($id) [list $headline $auname $audate \
296 $comname $comdate $comment]
1db95b00
PM
297}
298
f7a3e8d2 299proc getcommit {id} {
79b2c75e 300 global commitdata commitinfo
8ed16484 301
f7a3e8d2
PM
302 if {[info exists commitdata($id)]} {
303 parsecommit $id $commitdata($id) 1
8ed16484
PM
304 } else {
305 readcommit $id
306 if {![info exists commitinfo($id)]} {
307 set commitinfo($id) {"No commit information available"}
8ed16484
PM
308 }
309 }
310 return 1
311}
312
887fe3c4 313proc readrefs {} {
106288cb 314 global tagids idtags headids idheads tagcontents
8a48571c 315 global otherrefids idotherrefs mainhead
106288cb 316
b5c2f306
SV
317 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
318 catch {unset $v}
319 }
ce088722 320 set refd [open [list | git ls-remote [gitdir]] r]
36a7cad6
JH
321 while {0 <= [set n [gets $refd line]]} {
322 if {![regexp {^([0-9a-f]{40}) refs/([^^]*)$} $line \
323 match id path]} {
324 continue
c2f6a022 325 }
a970fcf2
JW
326 if {[regexp {^remotes/.*/HEAD$} $path match]} {
327 continue
328 }
36a7cad6
JH
329 if {![regexp {^(tags|heads)/(.*)$} $path match type name]} {
330 set type others
331 set name $path
887fe3c4 332 }
a970fcf2
JW
333 if {[regexp {^remotes/} $path match]} {
334 set type heads
335 }
36a7cad6
JH
336 if {$type == "tags"} {
337 set tagids($name) $id
338 lappend idtags($id) $name
339 set obj {}
340 set type {}
341 set tag {}
342 catch {
8974c6f9 343 set commit [exec git rev-parse "$id^0"]
36a7cad6
JH
344 if {"$commit" != "$id"} {
345 set tagids($name) $commit
346 lappend idtags($commit) $name
347 }
348 }
349 catch {
8974c6f9 350 set tagcontents($name) [exec git cat-file tag "$id"]
f1d83ba3 351 }
36a7cad6
JH
352 } elseif { $type == "heads" } {
353 set headids($name) $id
354 lappend idheads($id) $name
355 } else {
356 set otherrefids($name) $id
357 lappend idotherrefs($id) $name
f1d83ba3
PM
358 }
359 }
36a7cad6 360 close $refd
8a48571c
PM
361 set mainhead {}
362 catch {
363 set thehead [exec git symbolic-ref HEAD]
364 if {[string match "refs/heads/*" $thehead]} {
365 set mainhead [string range $thehead 11 end]
366 }
367 }
887fe3c4
PM
368}
369
e54be9e3 370proc show_error {w top msg} {
df3d83b1
PM
371 message $w.m -text $msg -justify center -aspect 400
372 pack $w.m -side top -fill x -padx 20 -pady 20
e54be9e3 373 button $w.ok -text OK -command "destroy $top"
df3d83b1 374 pack $w.ok -side bottom -fill x
e54be9e3
PM
375 bind $top <Visibility> "grab $top; focus $top"
376 bind $top <Key-Return> "destroy $top"
377 tkwait window $top
df3d83b1
PM
378}
379
098dd8a3
PM
380proc error_popup msg {
381 set w .error
382 toplevel $w
383 wm transient $w .
e54be9e3 384 show_error $w $w $msg
098dd8a3
PM
385}
386
d94f8cd6 387proc makewindow {} {
fdedbcfb
PM
388 global canv canv2 canv3 linespc charspc ctext cflist
389 global textfont mainfont uifont
b74fd579 390 global findtype findtypemenu findloc findstring fstring geometry
887fe3c4 391 global entries sha1entry sha1string sha1but
94a2eede 392 global maincursor textcursor curtextcursor
f1b86294 393 global rowctxmenu mergemax wrapcomment
60f7a7dc 394 global highlight_files gdttype
3ea06f9f 395 global searchstring sstring
f8a2c0d1 396 global bgcolor fgcolor bglist fglist diffcolors
9a40c50c
PM
397
398 menu .bar
399 .bar add cascade -label "File" -menu .bar.file
4840be66 400 .bar configure -font $uifont
9a40c50c 401 menu .bar.file
50b44ece 402 .bar.file add command -label "Update" -command updatecommits
f1d83ba3 403 .bar.file add command -label "Reread references" -command rereadrefs
1d10f36d 404 .bar.file add command -label "Quit" -command doquit
4840be66 405 .bar.file configure -font $uifont
712fcc08
PM
406 menu .bar.edit
407 .bar add cascade -label "Edit" -menu .bar.edit
408 .bar.edit add command -label "Preferences" -command doprefs
4840be66 409 .bar.edit configure -font $uifont
da7c24dd 410
fdedbcfb 411 menu .bar.view -font $uifont
50b44ece 412 .bar add cascade -label "View" -menu .bar.view
da7c24dd
PM
413 .bar.view add command -label "New view..." -command {newview 0}
414 .bar.view add command -label "Edit view..." -command editview \
415 -state disabled
50b44ece
PM
416 .bar.view add command -label "Delete view" -command delview -state disabled
417 .bar.view add separator
a90a6d24
PM
418 .bar.view add radiobutton -label "All files" -command {showview 0} \
419 -variable selectedview -value 0
da7c24dd 420
9a40c50c
PM
421 menu .bar.help
422 .bar add cascade -label "Help" -menu .bar.help
423 .bar.help add command -label "About gitk" -command about
4e95e1f7 424 .bar.help add command -label "Key bindings" -command keys
4840be66 425 .bar.help configure -font $uifont
9a40c50c
PM
426 . configure -menu .bar
427
0fba86b3 428 if {![info exists geometry(canv1)]} {
2ed49d54
JH
429 set geometry(canv1) [expr {45 * $charspc}]
430 set geometry(canv2) [expr {30 * $charspc}]
431 set geometry(canv3) [expr {15 * $charspc}]
432 set geometry(canvh) [expr {25 * $linespc + 4}]
0fba86b3
PM
433 set geometry(ctextw) 80
434 set geometry(ctexth) 30
435 set geometry(cflistw) 30
436 }
0327d27a 437 panedwindow .ctop -orient vertical
0fba86b3
PM
438 if {[info exists geometry(width)]} {
439 .ctop conf -width $geometry(width) -height $geometry(height)
17386066
PM
440 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
441 set geometry(ctexth) [expr {($texth - 8) /
442 [font metrics $textfont -linespace]}]
0fba86b3 443 }
98f350e5
PM
444 frame .ctop.top
445 frame .ctop.top.bar
908c3585
PM
446 frame .ctop.top.lbar
447 pack .ctop.top.lbar -side bottom -fill x
98f350e5
PM
448 pack .ctop.top.bar -side bottom -fill x
449 set cscroll .ctop.top.csb
450 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
451 pack $cscroll -side right -fill y
452 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
453 pack .ctop.top.clist -side top -fill both -expand 1
454 .ctop add .ctop.top
455 set canv .ctop.top.clist.canv
0fba86b3 456 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
f8a2c0d1 457 -background $bgcolor -bd 0 \
9f1afe05 458 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
98f350e5
PM
459 .ctop.top.clist add $canv
460 set canv2 .ctop.top.clist.canv2
0fba86b3 461 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
f8a2c0d1 462 -background $bgcolor -bd 0 -yscrollincr $linespc
98f350e5
PM
463 .ctop.top.clist add $canv2
464 set canv3 .ctop.top.clist.canv3
0fba86b3 465 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
f8a2c0d1 466 -background $bgcolor -bd 0 -yscrollincr $linespc
98f350e5 467 .ctop.top.clist add $canv3
43bddeb4 468 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
f8a2c0d1 469 lappend bglist $canv $canv2 $canv3
98f350e5
PM
470
471 set sha1entry .ctop.top.bar.sha1
887fe3c4
PM
472 set entries $sha1entry
473 set sha1but .ctop.top.bar.sha1label
474 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
4840be66 475 -command gotocommit -width 8 -font $uifont
887fe3c4 476 $sha1but conf -disabledforeground [$sha1but cget -foreground]
98f350e5 477 pack .ctop.top.bar.sha1label -side left
887fe3c4
PM
478 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
479 trace add variable sha1string write sha1change
98f350e5 480 pack $sha1entry -side left -pady 2
d698206c
PM
481
482 image create bitmap bm-left -data {
483 #define left_width 16
484 #define left_height 16
485 static unsigned char left_bits[] = {
486 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
487 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
488 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
489 }
490 image create bitmap bm-right -data {
491 #define right_width 16
492 #define right_height 16
493 static unsigned char right_bits[] = {
494 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
495 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
496 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
497 }
498 button .ctop.top.bar.leftbut -image bm-left -command goback \
499 -state disabled -width 26
500 pack .ctop.top.bar.leftbut -side left -fill y
501 button .ctop.top.bar.rightbut -image bm-right -command goforw \
502 -state disabled -width 26
503 pack .ctop.top.bar.rightbut -side left -fill y
504
4840be66 505 button .ctop.top.bar.findbut -text "Find" -command dofind -font $uifont
98f350e5
PM
506 pack .ctop.top.bar.findbut -side left
507 set findstring {}
df3d83b1 508 set fstring .ctop.top.bar.findstring
887fe3c4 509 lappend entries $fstring
908c3585 510 entry $fstring -width 30 -font $textfont -textvariable findstring
60f7a7dc 511 trace add variable findstring write find_change
df3d83b1 512 pack $fstring -side left -expand 1 -fill x
98f350e5 513 set findtype Exact
b74fd579
PM
514 set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \
515 findtype Exact IgnCase Regexp]
60f7a7dc 516 trace add variable findtype write find_change
4840be66
KP
517 .ctop.top.bar.findtype configure -font $uifont
518 .ctop.top.bar.findtype.menu configure -font $uifont
98f350e5
PM
519 set findloc "All fields"
520 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
60f7a7dc
PM
521 Comments Author Committer
522 trace add variable findloc write find_change
4840be66
KP
523 .ctop.top.bar.findloc configure -font $uifont
524 .ctop.top.bar.findloc.menu configure -font $uifont
98f350e5
PM
525 pack .ctop.top.bar.findloc -side right
526 pack .ctop.top.bar.findtype -side right
b5721c72 527
60f7a7dc 528 label .ctop.top.lbar.flabel -text "Highlight: Commits " \
908c3585
PM
529 -font $uifont
530 pack .ctop.top.lbar.flabel -side left -fill y
60f7a7dc
PM
531 set gdttype "touching paths:"
532 set gm [tk_optionMenu .ctop.top.lbar.gdttype gdttype "touching paths:" \
533 "adding/removing string:"]
534 trace add variable gdttype write hfiles_change
535 $gm conf -font $uifont
536 .ctop.top.lbar.gdttype conf -font $uifont
537 pack .ctop.top.lbar.gdttype -side left -fill y
908c3585
PM
538 entry .ctop.top.lbar.fent -width 25 -font $textfont \
539 -textvariable highlight_files
540 trace add variable highlight_files write hfiles_change
541 lappend entries .ctop.top.lbar.fent
542 pack .ctop.top.lbar.fent -side left -fill x -expand 1
543 label .ctop.top.lbar.vlabel -text " OR in view" -font $uifont
544 pack .ctop.top.lbar.vlabel -side left -fill y
545 global viewhlmenu selectedhlview
546 set viewhlmenu [tk_optionMenu .ctop.top.lbar.vhl selectedhlview None]
547 $viewhlmenu entryconf 0 -command delvhighlight
63b79191
PM
548 $viewhlmenu conf -font $uifont
549 .ctop.top.lbar.vhl conf -font $uifont
908c3585 550 pack .ctop.top.lbar.vhl -side left -fill y
164ff275
PM
551 label .ctop.top.lbar.rlabel -text " OR " -font $uifont
552 pack .ctop.top.lbar.rlabel -side left -fill y
553 global highlight_related
554 set m [tk_optionMenu .ctop.top.lbar.relm highlight_related None \
555 "Descendent" "Not descendent" "Ancestor" "Not ancestor"]
556 $m conf -font $uifont
557 .ctop.top.lbar.relm conf -font $uifont
558 trace add variable highlight_related write vrel_change
559 pack .ctop.top.lbar.relm -side left -fill y
908c3585 560
5ad588de
PM
561 panedwindow .ctop.cdet -orient horizontal
562 .ctop add .ctop.cdet
d2610d11 563 frame .ctop.cdet.left
3ea06f9f
PM
564 frame .ctop.cdet.left.bot
565 pack .ctop.cdet.left.bot -side bottom -fill x
566 button .ctop.cdet.left.bot.search -text "Search" -command dosearch \
567 -font $uifont
568 pack .ctop.cdet.left.bot.search -side left -padx 5
569 set sstring .ctop.cdet.left.bot.sstring
570 entry $sstring -width 20 -font $textfont -textvariable searchstring
571 lappend entries $sstring
572 trace add variable searchstring write incrsearch
573 pack $sstring -side left -expand 1 -fill x
d2610d11 574 set ctext .ctop.cdet.left.ctext
f8a2c0d1
PM
575 text $ctext -background $bgcolor -foreground $fgcolor \
576 -state disabled -font $textfont \
0fba86b3 577 -width $geometry(ctextw) -height $geometry(ctexth) \
3ea06f9f 578 -yscrollcommand scrolltext -wrap none
d2610d11
PM
579 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
580 pack .ctop.cdet.left.sb -side right -fill y
581 pack $ctext -side left -fill both -expand 1
582 .ctop.cdet add .ctop.cdet.left
f8a2c0d1
PM
583 lappend bglist $ctext
584 lappend fglist $ctext
d2610d11 585
f1b86294 586 $ctext tag conf comment -wrap $wrapcomment
f0654861 587 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
f8a2c0d1
PM
588 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
589 $ctext tag conf d0 -fore [lindex $diffcolors 0]
590 $ctext tag conf d1 -fore [lindex $diffcolors 1]
712fcc08
PM
591 $ctext tag conf m0 -fore red
592 $ctext tag conf m1 -fore blue
593 $ctext tag conf m2 -fore green
594 $ctext tag conf m3 -fore purple
595 $ctext tag conf m4 -fore brown
b77b0278
PM
596 $ctext tag conf m5 -fore "#009090"
597 $ctext tag conf m6 -fore magenta
598 $ctext tag conf m7 -fore "#808000"
599 $ctext tag conf m8 -fore "#009000"
600 $ctext tag conf m9 -fore "#ff0080"
601 $ctext tag conf m10 -fore cyan
602 $ctext tag conf m11 -fore "#b07070"
603 $ctext tag conf m12 -fore "#70b0f0"
604 $ctext tag conf m13 -fore "#70f0b0"
605 $ctext tag conf m14 -fore "#f0b070"
606 $ctext tag conf m15 -fore "#ff70b0"
712fcc08 607 $ctext tag conf mmax -fore darkgrey
b77b0278 608 set mergemax 16
712fcc08
PM
609 $ctext tag conf mresult -font [concat $textfont bold]
610 $ctext tag conf msep -font [concat $textfont bold]
611 $ctext tag conf found -back yellow
e5c2d856 612
d2610d11 613 frame .ctop.cdet.right
f8b28a40
PM
614 frame .ctop.cdet.right.mode
615 radiobutton .ctop.cdet.right.mode.patch -text "Patch" \
616 -command reselectline -variable cmitmode -value "patch"
617 radiobutton .ctop.cdet.right.mode.tree -text "Tree" \
618 -command reselectline -variable cmitmode -value "tree"
619 grid .ctop.cdet.right.mode.patch .ctop.cdet.right.mode.tree -sticky ew
620 pack .ctop.cdet.right.mode -side top -fill x
d2610d11 621 set cflist .ctop.cdet.right.cfiles
7fcceed7 622 set indent [font measure $mainfont "nn"]
f8a2c0d1
PM
623 text $cflist -width $geometry(cflistw) \
624 -background $bgcolor -foreground $fgcolor \
625 -font $mainfont \
7fcceed7
PM
626 -tabs [list $indent [expr {2 * $indent}]] \
627 -yscrollcommand ".ctop.cdet.right.sb set" \
628 -cursor [. cget -cursor] \
629 -spacing1 1 -spacing3 1
f8a2c0d1
PM
630 lappend bglist $cflist
631 lappend fglist $cflist
d2610d11
PM
632 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
633 pack .ctop.cdet.right.sb -side right -fill y
634 pack $cflist -side left -fill both -expand 1
89b11d3b
PM
635 $cflist tag configure highlight \
636 -background [$cflist cget -selectbackground]
63b79191 637 $cflist tag configure bold -font [concat $mainfont bold]
d2610d11 638 .ctop.cdet add .ctop.cdet.right
0fba86b3 639 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
d2610d11 640
0327d27a 641 pack .ctop -side top -fill both -expand 1
1db95b00 642
c8dfbcf9
PM
643 bindall <1> {selcanvline %W %x %y}
644 #bindall <B1-Motion> {selcanvline %W %x %y}
cfb4563c
PM
645 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
646 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
be0cd098
PM
647 bindall <2> "canvscan mark %W %x %y"
648 bindall <B2-Motion> "canvscan dragto %W %x %y"
6e5f7203
RN
649 bindkey <Home> selfirstline
650 bindkey <End> sellastline
17386066
PM
651 bind . <Key-Up> "selnextline -1"
652 bind . <Key-Down> "selnextline 1"
4e7d6779
PM
653 bind . <Shift-Key-Up> "next_highlight -1"
654 bind . <Shift-Key-Down> "next_highlight 1"
6e5f7203
RN
655 bindkey <Key-Right> "goforw"
656 bindkey <Key-Left> "goback"
657 bind . <Key-Prior> "selnextpage -1"
658 bind . <Key-Next> "selnextpage 1"
659 bind . <Control-Home> "allcanvs yview moveto 0.0"
660 bind . <Control-End> "allcanvs yview moveto 1.0"
661 bind . <Control-Key-Up> "allcanvs yview scroll -1 units"
662 bind . <Control-Key-Down> "allcanvs yview scroll 1 units"
663 bind . <Control-Key-Prior> "allcanvs yview scroll -1 pages"
664 bind . <Control-Key-Next> "allcanvs yview scroll 1 pages"
cfb4563c
PM
665 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
666 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
667 bindkey <Key-space> "$ctext yview scroll 1 pages"
df3d83b1
PM
668 bindkey p "selnextline -1"
669 bindkey n "selnextline 1"
6e2dda35
RS
670 bindkey z "goback"
671 bindkey x "goforw"
672 bindkey i "selnextline -1"
673 bindkey k "selnextline 1"
674 bindkey j "goback"
675 bindkey l "goforw"
cfb4563c
PM
676 bindkey b "$ctext yview scroll -1 pages"
677 bindkey d "$ctext yview scroll 18 units"
678 bindkey u "$ctext yview scroll -18 units"
b74fd579
PM
679 bindkey / {findnext 1}
680 bindkey <Key-Return> {findnext 0}
df3d83b1 681 bindkey ? findprev
39ad8570 682 bindkey f nextfile
1d10f36d 683 bind . <Control-q> doquit
98f350e5 684 bind . <Control-f> dofind
b74fd579 685 bind . <Control-g> {findnext 0}
1902c270 686 bind . <Control-r> dosearchback
3ea06f9f 687 bind . <Control-s> dosearch
1d10f36d
PM
688 bind . <Control-equal> {incrfont 1}
689 bind . <Control-KP_Add> {incrfont 1}
690 bind . <Control-minus> {incrfont -1}
691 bind . <Control-KP_Subtract> {incrfont -1}
0fba86b3 692 bind . <Destroy> {savestuff %W}
df3d83b1 693 bind . <Button-1> "click %W"
17386066 694 bind $fstring <Key-Return> dofind
887fe3c4 695 bind $sha1entry <Key-Return> gotocommit
ee3dc72e 696 bind $sha1entry <<PasteSelection>> clearsha1
7fcceed7
PM
697 bind $cflist <1> {sel_flist %W %x %y; break}
698 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
f8b28a40 699 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
ea13cba1
PM
700
701 set maincursor [. cget -cursor]
702 set textcursor [$ctext cget -cursor]
94a2eede 703 set curtextcursor $textcursor
84ba7345 704
c8dfbcf9
PM
705 set rowctxmenu .rowctxmenu
706 menu $rowctxmenu -tearoff 0
707 $rowctxmenu add command -label "Diff this -> selected" \
708 -command {diffvssel 0}
709 $rowctxmenu add command -label "Diff selected -> this" \
710 -command {diffvssel 1}
74daedb6 711 $rowctxmenu add command -label "Make patch" -command mkpatch
bdbfbe3d 712 $rowctxmenu add command -label "Create tag" -command mktag
4a2139f5 713 $rowctxmenu add command -label "Write commit to file" -command writecommit
df3d83b1
PM
714}
715
be0cd098
PM
716# mouse-2 makes all windows scan vertically, but only the one
717# the cursor is in scans horizontally
718proc canvscan {op w x y} {
719 global canv canv2 canv3
720 foreach c [list $canv $canv2 $canv3] {
721 if {$c == $w} {
722 $c scan $op $x $y
723 } else {
724 $c scan $op 0 $y
725 }
726 }
727}
728
9f1afe05
PM
729proc scrollcanv {cscroll f0 f1} {
730 $cscroll set $f0 $f1
731 drawfrac $f0 $f1
908c3585 732 flushhighlights
9f1afe05
PM
733}
734
df3d83b1
PM
735# when we make a key binding for the toplevel, make sure
736# it doesn't get triggered when that key is pressed in the
737# find string entry widget.
738proc bindkey {ev script} {
887fe3c4 739 global entries
df3d83b1
PM
740 bind . $ev $script
741 set escript [bind Entry $ev]
742 if {$escript == {}} {
743 set escript [bind Entry <Key>]
744 }
887fe3c4
PM
745 foreach e $entries {
746 bind $e $ev "$escript; break"
747 }
df3d83b1
PM
748}
749
750# set the focus back to the toplevel for any click outside
887fe3c4 751# the entry widgets
df3d83b1 752proc click {w} {
887fe3c4
PM
753 global entries
754 foreach e $entries {
755 if {$w == $e} return
df3d83b1 756 }
887fe3c4 757 focus .
0fba86b3
PM
758}
759
760proc savestuff {w} {
4840be66 761 global canv canv2 canv3 ctext cflist mainfont textfont uifont
712fcc08 762 global stuffsaved findmergefiles maxgraphpct
b8ab2e17 763 global maxwidth showneartags
098dd8a3 764 global viewname viewfiles viewargs viewperm nextviewnum
f1b86294 765 global cmitmode wrapcomment
f8a2c0d1 766 global colors bgcolor fgcolor diffcolors
4ef17537 767
0fba86b3 768 if {$stuffsaved} return
df3d83b1 769 if {![winfo viewable .]} return
0fba86b3
PM
770 catch {
771 set f [open "~/.gitk-new" w]
f0654861
PM
772 puts $f [list set mainfont $mainfont]
773 puts $f [list set textfont $textfont]
4840be66 774 puts $f [list set uifont $uifont]
f0654861 775 puts $f [list set findmergefiles $findmergefiles]
8d858d1a 776 puts $f [list set maxgraphpct $maxgraphpct]
04c13d38 777 puts $f [list set maxwidth $maxwidth]
f8b28a40 778 puts $f [list set cmitmode $cmitmode]
f1b86294 779 puts $f [list set wrapcomment $wrapcomment]
b8ab2e17 780 puts $f [list set showneartags $showneartags]
f8a2c0d1
PM
781 puts $f [list set bgcolor $bgcolor]
782 puts $f [list set fgcolor $fgcolor]
783 puts $f [list set colors $colors]
784 puts $f [list set diffcolors $diffcolors]
0fba86b3
PM
785 puts $f "set geometry(width) [winfo width .ctop]"
786 puts $f "set geometry(height) [winfo height .ctop]"
2ed49d54
JH
787 puts $f "set geometry(canv1) [expr {[winfo width $canv]-2}]"
788 puts $f "set geometry(canv2) [expr {[winfo width $canv2]-2}]"
789 puts $f "set geometry(canv3) [expr {[winfo width $canv3]-2}]"
790 puts $f "set geometry(canvh) [expr {[winfo height $canv]-2}]"
0fba86b3
PM
791 set wid [expr {([winfo width $ctext] - 8) \
792 / [font measure $textfont "0"]}]
0fba86b3 793 puts $f "set geometry(ctextw) $wid"
0fba86b3
PM
794 set wid [expr {([winfo width $cflist] - 11) \
795 / [font measure [$cflist cget -font] "0"]}]
796 puts $f "set geometry(cflistw) $wid"
a90a6d24
PM
797 puts -nonewline $f "set permviews {"
798 for {set v 0} {$v < $nextviewnum} {incr v} {
799 if {$viewperm($v)} {
098dd8a3 800 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
a90a6d24
PM
801 }
802 }
803 puts $f "}"
0fba86b3
PM
804 close $f
805 file rename -force "~/.gitk-new" "~/.gitk"
806 }
807 set stuffsaved 1
1db95b00
PM
808}
809
43bddeb4
PM
810proc resizeclistpanes {win w} {
811 global oldwidth
418c4c7b 812 if {[info exists oldwidth($win)]} {
43bddeb4
PM
813 set s0 [$win sash coord 0]
814 set s1 [$win sash coord 1]
815 if {$w < 60} {
816 set sash0 [expr {int($w/2 - 2)}]
817 set sash1 [expr {int($w*5/6 - 2)}]
818 } else {
819 set factor [expr {1.0 * $w / $oldwidth($win)}]
820 set sash0 [expr {int($factor * [lindex $s0 0])}]
821 set sash1 [expr {int($factor * [lindex $s1 0])}]
822 if {$sash0 < 30} {
823 set sash0 30
824 }
825 if {$sash1 < $sash0 + 20} {
2ed49d54 826 set sash1 [expr {$sash0 + 20}]
43bddeb4
PM
827 }
828 if {$sash1 > $w - 10} {
2ed49d54 829 set sash1 [expr {$w - 10}]
43bddeb4 830 if {$sash0 > $sash1 - 20} {
2ed49d54 831 set sash0 [expr {$sash1 - 20}]
43bddeb4
PM
832 }
833 }
834 }
835 $win sash place 0 $sash0 [lindex $s0 1]
836 $win sash place 1 $sash1 [lindex $s1 1]
837 }
838 set oldwidth($win) $w
839}
840
841proc resizecdetpanes {win w} {
842 global oldwidth
418c4c7b 843 if {[info exists oldwidth($win)]} {
43bddeb4
PM
844 set s0 [$win sash coord 0]
845 if {$w < 60} {
846 set sash0 [expr {int($w*3/4 - 2)}]
847 } else {
848 set factor [expr {1.0 * $w / $oldwidth($win)}]
849 set sash0 [expr {int($factor * [lindex $s0 0])}]
850 if {$sash0 < 45} {
851 set sash0 45
852 }
853 if {$sash0 > $w - 15} {
2ed49d54 854 set sash0 [expr {$w - 15}]
43bddeb4
PM
855 }
856 }
857 $win sash place 0 $sash0 [lindex $s0 1]
858 }
859 set oldwidth($win) $w
860}
861
b5721c72
PM
862proc allcanvs args {
863 global canv canv2 canv3
864 eval $canv $args
865 eval $canv2 $args
866 eval $canv3 $args
867}
868
869proc bindall {event action} {
870 global canv canv2 canv3
871 bind $canv $event $action
872 bind $canv2 $event $action
873 bind $canv3 $event $action
874}
875
9a40c50c
PM
876proc about {} {
877 set w .about
878 if {[winfo exists $w]} {
879 raise $w
880 return
881 }
882 toplevel $w
883 wm title $w "About gitk"
884 message $w.m -text {
9f1afe05 885Gitk - a commit viewer for git
9a40c50c 886
9f1afe05 887