︙ | | |
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
-
+
+
|
#-----------------------------------------------
# $Revision$
#-----------------------------------------------
# the next line restarts using wish \
exec wish "$0" "$@"
set debug 1
set diffver "Version 1.9.4b 2002-04-24"
set diffver "Version 1.9.4b 2002-05-14"
set tmpcnt 0
set tmpfiles {}
set thisscript [file join [pwd] [info script]]
set thisdir [file dirname $thisscript]
set ::diff(cvsExists) [expr {![string equal [auto_execok cvs] ""]}]
set ::diff(diffexe) diff
set ::diff(diffutil) [expr {![catch {package require DiffUtil}]}]
if {[info exists env(TEMP)]} {
set ::diff(tmpdir) $env(TEMP)
} elseif {[info exists env(TMP)]} {
set ::diff(tmpdir) $env(TMP)
} else {
if {$tcl_platform(platform) == "windows"} {
|
︙ | | |
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
-
+
|
auto_reset
set ::diff(cvsExists) [expr {![string equal [auto_execok cvs] ""]}]
}
}
proc cleanupAndExit {} {
if {$::diff(diffexe) != "diff"} {
file delete $::diff(diffexe)
catch {file delete $::diff(diffexe)}
}
cleartmp
exit
}
# Format a line number
proc myforml {lineNo} {
|
︙ | | |
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
-
+
|
set name [file join $::diff(tmpdir) "tmpd[pid]a$::tmpcnt"]
lappend ::tmpfiles $name
return $name
}
proc cleartmp {} {
foreach f $::tmpfiles {
file delete $f
catch {file delete $f}
}
set ::tmpfiles {}
}
# 2nd stage line parsing
# Recursively look for common substrings in strings s1 and s2
##syntax compareMidString x x n n x?
|
︙ | | |
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
+
+
+
+
+
+
+
+
+
+
|
compareMidString $left1 $left2 left1 left2 $test
compareMidString $right1 $right2 right1 right2 $test
set res1 [concat $left1 [list $mid1] $right1]
set res2 [concat $left2 [list $mid2] $right2]
}
}
proc compareLinesX {line1 line2 res1Name res2Name {test 0}} {
global Pref
upvar $res1Name res1
upvar $res2Name res2
set args "$Pref(ignore)\
[expr {($Pref(lineparsewords) && !$test) ? "-word" : ""}]"
eval DiffUtil::compareLines $args \$line1 \$line2 res1 res2
}
# Compare two lines to find inequalities to highlight.
# The return value is, for each line, a list where the first, third etc.
# element is equal between the lines. The second, fourth etc. will be
# highlighted.
##syntax compareLines x x n n x?
proc compareLines {line1 line2 res1Name res2Name {test 0}} {
|
︙ | | |
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
|
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
|
}
set t1 $s1
set t2 $s2
}
}
# Make the result
if {$leftp1 > $t1} {
if {$leftp1 > $t1 && $leftp2 > $t2} {
set res1 [list $line1]
set res2 [list $line2]
} else {
set right1 [string range $line1 [expr {$t1 + 1}] end]
set mid1 [string range $line1 $leftp1 $t1]
set left1 [string range $line1 0 [expr {$leftp1 - 1}]]
set res1 [list $left1 $mid1 $right1]
}
if {$leftp2 > $t2} {
set res2 [list $line2]
} else {
set right2 [string range $line2 [expr {$t2 + 1}] end]
set mid2 [string range $line2 $leftp2 $t2]
set left2 [string range $line2 0 [expr {$leftp2 - 1}]]
set res2 [list $left2 $mid2 $right2]
}
if {$Pref(extralineparse) != 0 && $leftp1 <= $t1 && $leftp2 <= $t2} {
compareMidString $mid1 $mid2 mid1 mid2 $test
# Replace middle element in res* with list elements from mid*
#set res1 [eval lreplace \$res1 1 1 $mid1]
#set res2 [eval lreplace \$res2 1 1 $mid2]
# This makes use of pure-list optimisation in eval
set res1 [eval [linsert $mid1 0 lreplace $res1 1 1]]
set res2 [eval [linsert $mid2 0 lreplace $res2 1 1]]
if {$Pref(extralineparse) != 0 && $mid1 != "" && $mid2 != ""} {
compareMidString $mid1 $mid2 mid1 mid2 $test
# Replace middle element in res* with list elements from mid*
#set res1 [eval lreplace \$res1 1 1 $mid1]
#set res2 [eval lreplace \$res2 1 1 $mid2]
# This makes use of pure-list optimisation in eval
set res1 [eval [linsert $mid1 0 lreplace $res1 1 1]]
set res2 [eval [linsert $mid2 0 lreplace $res2 1 1]]
}
}
}
# Compare two lines and rate how much they resemble each other.
# This has never worked well. Some day I'll sit down, think this through,
# and come up with a better algorithm.
proc compareLines2 {line1 line2} {
compareLines $line1 $line2 res1 res2 1
if {$::diff(diffutil)} {
compareLinesX $line1 $line2 xres1 xres2 1
if {$res1 != $xres1 || $res2 != $xres2} {
tk_messageBox -title "Rate Mismatch!" \
-message ":$res1:\n:$res2:\n:$xres1:\n:$xres2:"
}
}
# Collect identical pieces and different pieces
set sames {}
set diffs1 {}
set diffs2 {}
foreach {same diff} $res1 {
lappend sames $same
if {$diff != ""} {
|
︙ | | |
631
632
633
634
635
636
637
638
639
640
641
642
643
644
|
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
|
+
+
+
+
+
+
+
|
# Insert one line in each text widget.
# Mark them as changed, and optionally parse them.
proc insertMatchingLines {line1 line2} {
global doingLine1 doingLine2 Pref
if {$Pref(parse) != 0} {
compareLines $line1 $line2 res1 res2
if {$::diff(diffutil)} {
compareLinesX $line1 $line2 xres1 xres2
if {$res1 != $xres1 || $res2 != $xres2} {
tk_messageBox -title Mismatch! \
-message ":$res1:\n:$res2:\n:$xres1:\n:$xres2:"
}
}
set dotag 0
set n [maxabs [llength $res1] [llength $res2]]
.ft1.tl insert end [myforml $doingLine1] "hl$::HighLightCount change"
.ft2.tl insert end [myforml $doingLine2] "hl$::HighLightCount change"
set new1 new1
set new2 new2
set change change
|
︙ | | |
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
|
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
|
+
+
+
+
+
|
.ft1.tl insert end "\n"
.ft2.tl insert end "\n"
}
# Process the block
if {$n1 == $n2 && ($n1 == 1 || $Pref(parse) < 2)} {
# Never do block parsing for one line blocks.
# If block parsing is turned off, only do line parsing for
# blocks of equal size.
for {set t 0} {$t < $n1} {incr t} {
gets $ch1 textline1
gets $ch2 textline2
insertMatchingLines $textline1 $textline2
}
lappend changesList $mapMax $n1 change $line1 $n1 $line2 $n2
incr mapMax $n1
} else {
if {$n1 != 0 && $n2 != 0 && $Pref(parse) >= 2 && \
($n1 * $n2 < 1000 || $Pref(parse) == 3)} {
# Full block parsing
set block1 {}
for {set t 0} {$t < $n1} {incr t} {
gets $ch1 apa
lappend block1 $apa
}
set block2 {}
for {set t 0} {$t < $n2} {incr t} {
gets $ch2 apa
lappend block2 $apa
}
set apa [insertMatchingBlocks $block1 $block2]
lappend changesList $mapMax $apa change \
$line1 $n1 $line2 $n2
incr mapMax $apa
} else {
# No extra parsing at all.
for {set t 0} {$t < $n1} {incr t} {
gets $ch1 apa
insert 1 $doingLine1 $apa $tag1
incr doingLine1
}
for {set t 0} {$t < $n2} {incr t} {
gets $ch2 apa
|
︙ | | |
953
954
955
956
957
958
959
960
961
962
963
964
965
966
|
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
|
+
|
global diff Pref
cleartmp
set diff(rightFile) $diff(conflictFile)
set diff(leftFile) $diff(conflictFile)
}
# Display one chunk from a patch file
proc displayOnePatch {leftLines rightLines leftLine rightLine} {
emptyline 1
emptyline 2
set leftlen [llength $leftLines]
set rightlen [llength $rightLines]
|
︙ | | |
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
|
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
|
+
+
+
|
return
} else {
enableRedo
}
busyCursor
# Clear up everything before starting processing
foreach w {.ft1.tl .ft1.tt .ft2.tl .ft2.tt} {
$w configure -state normal
$w delete 1.0 end
}
set changesList {}
set mapMax 0
set ::HighLightCount 0
highLightChange -1
drawMap -1
# Display a star during diff execution, to know when the internal
# processing starts, and when the label is "valid".
set ::diff(eqLabel) "*"
update idletasks
if {$diff(mode) == "patch"} {
displayPatch
drawMap -1
|
︙ | | |
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
|
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
|
+
+
+
+
-
-
+
+
+
+
|
} elseif {$diff(mode) == "RCS" || $diff(mode) == "CVS"} {
prepareRCS
} elseif {[string match "conflict*" $diff(mode)]} {
prepareConflict
}
# Run diff and parse the result.
if {$::diff(diffutil)} {
set differr [catch {eval DiffUtil::diffFiles $Pref(ignore) \
\$diff(leftFile) \$diff(rightFile)} diffres]
} else {
set differr [catch {eval exec \$::diff(diffexe) $Pref(dopt) $Pref(ignore) \
\$diff(leftFile) \$diff(rightFile)} diffres]
set differr [catch {eval exec \$::diff(diffexe) \
$Pref(dopt) $Pref(ignore) \
\$diff(leftFile) \$diff(rightFile)} diffres]
}
set apa [split $diffres "\n"]
set result {}
foreach i $apa {
if {[string match {[0-9]*} $i]} {
lappend result $i
}
|
︙ | | |
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
|
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
|
+
|
return
} else {
set ::diff(eqLabel) "="
}
} else {
set ::diff(eqLabel) " "
}
# Update the equal label immediately for better feedback
update idletasks
set ch1 [open $diff(leftFile)]
set ch2 [open $diff(rightFile)]
if {$::tcl_platform(platform) == "windows" && $Pref(crlf)} {
fconfigure $ch1 -translation crlf
fconfigure $ch2 -translation crlf
|
︙ | | |
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
|
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
|
-
+
|
set max 0.0
foreach w {.ft1.tl .ft1.tt .ft2.tl .ft2.tt} {
if {[$w index end] > $max} {
set max [$w index end]
}
}
foreach w {.ft1.tl .ft1.tt .ft2.tl .ft2.tt} {
set d [expr {int($max - [$w index end])}]
set d [expr {int($max) - int([$w index end])}]
for {set t 0} {$t < $d} {incr t} {
$w insert end \n
}
}
close $ch1
close $ch2
|
︙ | | |
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
|
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
|
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
-
+
-
-
-
+
+
+
+
-
+
+
+
-
-
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
+
-
-
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
radiobutton $w.f.rb4 -text "RL" -value 21 -variable curMergeSel \
-command selectMerge
bind $w <Key-Left> {focus .merge ; set curMergeSel 1 ; selectMerge}
bind $w <Key-Right> {focus .merge ; set curMergeSel 2 ; selectMerge}
button $w.f.bl -text "All L" -command {selectMergeAll 1}
button $w.f.br -text "All R" -command {selectMergeAll 2}
checkbutton $w.f.bm -text "Pure" -variable diff(mode) \
-onvalue "conflictPure" -offvalue "conflict" -command {doDiff}
button $w.f.b1 -text "Prev" -command {nextMerge -1}
button $w.f.b2 -text "Next" -command {nextMerge 1}
bind $w <Key-Down> {focus .merge ; nextMerge 1}
bind $w <Key-Up> {focus .merge ; nextMerge -1}
button $w.f.bs -text "Save" -command saveMerge
button $w.f.bq -text "Close" -command closeMerge
wm protocol $w WM_CLOSE_WINDOW closeMerge
grid $w.f.rb1 $w.f.rb2 $w.f.rb3 $w.f.rb4 x $w.f.b1 $w.f.b2 x \
$w.f.bl $w.f.br x $w.f.bm x $w.f.bs $w.f.bq
$w.f.bl $w.f.br x x x $w.f.bs $w.f.bq
grid columnconfigure $w.f {4 7 10 12} -minsize 10
grid columnconfigure $w.f 10 -weight 1
if {[string match conflict* $::diff(mode)]} {
checkbutton $w.f.bm -text "Pure" -variable diff(mode) \
-onvalue "conflictPure" -offvalue "conflict" -command {doDiff}
grid $w.f.bm -row 0 -column 11
}
text $w.t -width 80 -height 20 -xscrollcommand "$w.sbx set" \
-yscrollcommand "$w.sby set" -font myfont
scrollbar $w.sbx -orient horizontal -command "$w.t xview"
scrollbar $w.sby -orient vertical -command "$w.t yview"
grid $w.f - -sticky news -row 0
grid $w.t $w.sby -sticky news
grid $w.sbx x -sticky we
grid columnconfigure $w 0 -weight 1
grid rowconfigure $w 1 -weight 1
collectMergeData
fillMergeWindow
}
#####################################
# Searching
#####################################
namespace eval textSearch {
if {![info exists ::textSearch::widgets]} {
variable widgets {}
}
variable isearchW ""
variable isearchLast ""
variable searchCase 0
variable searchIndex 1.0
variable searchString ""
}
# Setup a text widget for searching
proc startIncrementalSearch {w} {
proc textSearch::enableSearch {w} {
variable widgets
if {[winfo class $w] != "Text"} {
error "Only text widgets can be searched!"
}
if {![info exists ::diff(isearch)]} {
set ::diff(isearch) ""
set ::diff(isearchlast) ""
}
bind ISearch <Control-Key-s> "textSearch::startIncrementalSearch %W"
bindtags $w "ISearch [bindtags $w]"
if {[lsearch $widgets $w] < 0} {
lappend widgets $w
}
set top [winfo toplevel $w]
bind $top <Control-Key-f> textSearch::search
bind $top <Key-F3> textSearch::searchNext
bind $top <Control-Key-F3> textSearch::searchPrev
}
# Add searching to a menu
proc textSearch::searchMenu {menu} {
$menu add command -label "Find" -accelerator "Ctrl+f" \
-command ::textSearch::search
$menu add command -label "Find Next" -accelerator "F3" \
-command ::textSearch::searchNext
$menu add command -label "Find Prev" -accelerator "Ctrl+F3" \
-command ::textSearch::searchPrev
}
# Start an incremental search
proc textSearch::startIncrementalSearch {w} {
variable isearchW
# This shouldn't happen
if {$::diff(isearch) != ""} {
endIncrementalSearch $w
if {$isearchW != ""} {
endIncrementalSearch
}
set ::diff(isearch) $w
set isearchW $w
# Setup all bindings for incremental search
bind MyText <Control-Key-s> "isearchAgain %W ; break"
bind MyText <FocusOut> "endIncrementalSearch %W"
bind MyText <Key> "isearchKey %W %A %s %K"
bind MyText <Key-Escape> "endIncrementalSearch %W ; break"
bind MyText <Control-Key-g> "endIncrementalSearch %W ; break"
bind ISearch <Control-Key-s> "textSearch::isearchAgain %W ; break"
bind ISearch <Key-Delete> "textSearch::isearchBack %W ; break"
bind ISearch <Key-BackSpace> "textSearch::isearchBack %W ; break"
bind ISearch <Key> "textSearch::isearchKey %W %A %s %K"
bind ISearch <Key-Escape> "textSearch::endIncrementalSearch ; break"
bind ISearch <Control-Key-g> "textSearch::endIncrementalSearch ; break"
bind MyText <Key-Delete> "isearchBack %W ; break"
bind MyText <Key-BackSpace> "isearchBack %W ; break"
bind ISearch <FocusOut> "textSearch::endIncrementalSearch"
# Initialise variables
set ::diff(isearchstring) ""
set ::diff(isearchhistory) {}
set ::diff(isearchindex) [$w index insert]
set ::diff(statusLabel) "i"
set ::textSearch::isearchString ""
set ::textSearch::isearchHistory {}
set ::textSearch::isearchIndex [$w index insert]
set ::textSearch::statusLabel "i"
}
# Highlight a match
proc isearchShow {w index string} {
proc textSearch::isearchShow {w index string} {
$w tag remove sel 1.0 end
$w tag add sel $index "$index + [string length $string] chars"
$w mark set insert $index
$w see $index
set ::diff(isearchindex) $index
set ::diff(isearchstring) $string
set ::diff(isearchlast) $string
set ::textSearch::isearchIndex $index
set ::textSearch::isearchString $string
set ::textSearch::isearchLast $string
}
# Search the widget
proc isearchSearch {w str ix} {
proc textSearch::isearchSearch {w str ix} {
# If the search string is all lower case, search case insensitive
if {[string equal [string tolower $str] $str]} {
set found [$w search -nocase $str $ix]
} else {
set found [$w search $str $ix]
}
return $found
}
# Search for next match
proc isearchAgain {w} {
if {$w != $::diff(isearch)} {
proc textSearch::isearchAgain {w} {
variable isearchW
if {$w != $isearchW} {
bell
endIncrementalSearch $::diff(isearch)
endIncrementalSearch
return
}
set str $::diff(isearchstring)
set str $::textSearch::isearchString
if {$str == ""} {
set str $::diff(isearchlast)
set str $::textSearch::isearchLast
}
set found [isearchSearch $w $str "$::diff(isearchindex) + 1 char"]
set found [isearchSearch $w $str "$::textSearch::isearchIndex + 1 char"]
if {$found == ""} {
bell
return
}
lappend ::diff(isearchhistory) $::diff(isearchindex) \
$::diff(isearchstring)
lappend ::textSearch::isearchHistory $::textSearch::isearchIndex \
$::textSearch::isearchString
isearchShow $w $found $str
}
# A key has been pressed during incremental search
proc isearchKey {w key state sym} {
if {$w != $::diff(isearch)} {
proc textSearch::isearchKey {w key state sym} {
variable isearchW
if {$w != $isearchW} {
bell
endIncrementalSearch $::diff(isearch)
endIncrementalSearch
return -code break
}
if {$key == ""} {
# Ignore the Control and Shift keys
if {[string match Contr* $sym]} {return -code break}
if {[string match Shift* $sym]} {return -code break}
# Ignore any Control-ed key
if {$state == 4} {return -code break}
# Break isearch on other non-ascii keys, and let it through
bell
endIncrementalSearch $::diff(isearch)
endIncrementalSearch
return
}
set str $::diff(isearchstring)
set str $::textSearch::isearchString
append str $key
set found [isearchSearch $w $str $::diff(isearchindex)]
set found [isearchSearch $w $str $::textSearch::isearchIndex]
if {$found == ""} {
bell
return -code break
}
lappend ::diff(isearchhistory) $::diff(isearchindex) \
$::diff(isearchstring)
lappend ::textSearch::isearchHistory $::textSearch::isearchIndex \
$::textSearch::isearchString
isearchShow $w $found $str
return -code break
}
# Go backwards in the isearch stack
proc textSearch::isearchBack {w} {
variable isearchW
if {$w != $isearchW} {
bell
endIncrementalSearch
return
}
if {[llength $::textSearch::isearchHistory] < 2} {
bell
return
}
set str [lindex $::textSearch::isearchHistory end]
set found [lindex $::textSearch::isearchHistory end-1]
set ::textSearch::isearchHistory \
[lrange $::textSearch::isearchHistory 0 end-2]
isearchShow $w $found $str
}
# End an incremental search
proc textSearch::endIncrementalSearch {} {
set ::textSearch::isearchW ""
set ::textSearch::statusLabel ""
# Remove all bindings from ISearch
foreach b [bind ISearch] {
bind ISearch $b ""
}
bind ISearch <Control-Key-s> "textSearch::startIncrementalSearch %W"
}
# Dialog functions from "Practical Programming in Tcl And Tk" by Welch.
proc textSearch::DialogCreate {top title args} {
variable dialog
if {[winfo exists $top]} {
switch -- [wm state $top] {
normal {
# Raise a buried window
raise $top
proc isearchBack {w} {
if {$w != $::diff(isearch)} {
bell
endIncrementalSearch $::diff(isearch)
return
}
if {[llength $::diff(isearchhistory)] < 2} {
bell
return
}
set str [lindex $::diff(isearchhistory) end]
set found [lindex $::diff(isearchhistory) end-1]
set ::diff(isearchhistory) [lrange $::diff(isearchhistory) 0 end-2]
isearchShow $w $found $str
}
proc endIncrementalSearch {w} {
set ::diff(isearch) ""
set ::diff(statusLabel) ""
}
withdrawn -
iconified {
# Open and restore geometry
wm deiconify $top
catch {wm geometry $top $dialog(geo,$top)}
}
}
return 0
} else {
eval {toplevel $top} $args
wm title $top $title
return 1
}
}
proc textSearch::DialogWait {top varName {focus {}}} {
upvar $varName var
# Poke the variable if the user nukes the window
bind $top <Destroy> [list set $varName $var]
# Grab focus for the dialog
if {[string length $focus] == 0} {
set focus $top
}
set old [focus -displayof $top]
focus $focus
catch {tkwait visibility $top}
catch {grab $top}
# Wait for the dialog to complete
tkwait variable $varName
catch {grab release $top}
focus $old
}
proc textSearch::DialogDismiss {top} {
variable dialog
# Save current size and position
catch {
# window may have been deleted
set dialog(geo,$top) [wm geometry $top]
wm withdraw $top
}
}
# Ask for a search string
proc textSearch::FindDialog {string} {
variable prompt
set f .prompt
if {[DialogCreate $f "Find" -borderwidth 10]} {
message $f.msg -text $string -aspect 1000
entry $f.entry -textvariable ::textSearch::prompt(result)
checkbutton $f.case -text "Match Case" -anchor w\
-variable ::textSearch::searchCase
button $f.ok -text OK -width 7 \
-command {set ::textSearch::prompt(ok) 1}
button $f.cancel -text Cancel -width 7 \
-command {set ::textSearch::prompt(ok) 0}
grid $f.msg - - -sticky w
grid $f.entry - - -sticky we
grid $f.case - - -sticky w
grid $f.ok x $f.cancel -sticky wes
grid columnconfigure $f {0 2} -weight 1
grid columnconfigure $f 1 -minsize 10 -weight 2
grid rowconfigure $f 3 -weight 1
bind $f.entry <Key-Return> {set ::textSearch::prompt(ok) 1 ; break}
bind $f.entry <Key-Escape> {set ::textSearch::prompt(ok) 0 ; break}
}
set prompt(ok) 0
DialogWait $f ::textSearch::prompt(ok) $f.entry
DialogDismiss $f
if {$prompt(ok)} {
return $prompt(result)
} else {
return {}
}
}
# "Normal" search
proc textSearch::search {} {
variable searchString
variable searchWin
variable widgets
variable searchCase
variable searchIndex
set searchWin [lindex $widgets 0]
set foc [focus -displayof .]
if {[lsearch $widgets $foc] >= 0} {
set searchWin $foc
}
set searchString [FindDialog "Please enter string to find"]
if {$searchString == ""} return
if {$searchCase} {
set searchPos [$searchWin search -count cnt $searchString @0,0]
} else {
set searchPos [$searchWin search -count cnt -nocase $searchString @0,0]
}
if {$searchPos == ""} {
tk_messageBox -message "Search string not found!" -type ok \
-title Search
return
}
$searchWin see $searchPos
$searchWin tag remove sel 1.0 end
$searchWin tag add sel $searchPos "$searchPos + $cnt chars"
set searchIndex $searchPos
}
# Search again
proc textSearch::searchNext {} {
variable searchString
variable searchWin
variable searchCase
variable searchIndex
if {$searchString == ""} return
if {$searchCase} {
set searchPos [$searchWin search -count cnt \
$searchString "$searchIndex + 1 chars"]
} else {
set searchPos [$searchWin search -count cnt -nocase \
$searchString "$searchIndex + 1 chars"]
}
# Remove all bindings from MyText
foreach b [bind MyText] {
bind MyText $b ""
}
bind MyText <Control-Key-s> "startIncrementalSearch %W"
if {$searchPos == "" || $searchPos == $searchIndex} {
tk_messageBox -message "String not found!" -type ok -title Search
return
}
$searchWin see $searchPos
$searchWin tag remove sel 1.0 end
$searchWin tag add sel $searchPos "$searchPos + $cnt chars"
set searchIndex $searchPos
}
# Search backwards
proc textSearch::searchPrev {} {
variable searchString
variable searchWin
variable searchCase
variable searchIndex
if {$searchString == ""} return
if {$searchCase} {
set searchPos [$searchWin search -count cnt -backwards \
$searchString "$searchIndex - 1 chars"]
} else {
set searchPos [$searchWin search -count cnt -backwards \
-nocase \
$searchString "$searchIndex - 1 chars"]
}
if {$searchPos == "" || $searchPos == $searchIndex} {
tk_messageBox -message "String not found!" -type ok -title Search
return
}
$searchWin see $searchPos
$searchWin tag remove sel 1.0 end
$searchWin tag add sel $searchPos "$searchPos + $cnt chars"
set searchIndex $searchPos
}
#####################################
# Printing stuff
#####################################
# Format a line number for printing
|
︙ | | |
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
|
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
|
-
-
+
-
+
|
}
# Main print function
proc printDiffs {{quiet 0}} {
busyCursor
update idletasks
set tmpFile [file nativename ~/tcldiff.enscript]
set tmpFile2 [file nativename ~/tcldifftmp.ps]
if {$::diff(printFile) != ""} {
set tmpFile3 [file nativename $::diff(printFile)]
set tmpFile2 [file nativename $::diff(printFile)]
} else {
set tmpFile3 [file nativename ~/tcldiff.ps]
set tmpFile2 [file nativename ~/tcldiff.ps]
}
set lines1 {}
set lines2 {}
set tdump1 [.ft1.tt dump -tag -text 1.0 end]
set tdump2 [.ft2.tt dump -tag -text 1.0 end]
|
︙ | | |
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
|
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
|
-
+
-
+
|
}
set rfile [file tail $rfile]$rrest
lappend enscriptCmd "--header=$lfile|Page \$% of \$=|$rfile"
if {$::prettyPrint != ""} {
lappend enscriptCmd -E$::prettyPrint
}
lappend enscriptCmd -p $tmpFile3 $tmpFile
lappend enscriptCmd -p $tmpFile2 $tmpFile
if {[catch {eval exec $enscriptCmd} result]} {
if {[string index $result 0] != "\["} {
tk_messageBox -message "Enscript error: $result"
return
}
}
normalCursor
if {!$quiet} {
destroy .dp
toplevel .dp
wm title .dp "Diff Print"
button .dp.b -text Close -command {destroy .dp}
label .dp.l -anchor w -justify left -text "The following files have\
been created:\n\n$tmpFile\nInput file to enscript.\
\n\n$tmpFile3\nCreated with\
\n\n$tmpFile2\nCreated with\
'[lrange $enscriptCmd 0 end-3] \\\n \
[lrange $enscriptCmd end-2 end]'" \
-font "Courier 8"
pack .dp.b -side bottom
pack .dp.l -side top
}
}
|
︙ | | |
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
|
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
|
-
-
-
+
-
-
|
.mo.mp add separator
.mo.mp add checkbutton -label "Use 2nd stage" \
-variable Pref(extralineparse)
.mo.mp add checkbutton -label "Mark last" -variable Pref(marklast)
menubutton .ms -text Search -underline 0 -menu .ms.m
menu .ms.m
.ms.m add command -label "Find" -accelerator "Ctrl+f" -command Search
.ms.m add command -label "Find Next" -accelerator "F3" \
-command SearchNext
textSearch::searchMenu .ms.m
.ms.m add command -label "Find Prev" -accelerator "Ctrl+F3" \
-command SearchPrev
menubutton .mh -text Help -underline 0 -menu .mh.m
menu .mh.m
.mh.m add command -label "Help" -command makeHelpWin
.mh.m add command -label "About" -command makeAboutWin
button .bfn -text "Next Diff" -relief raised -command {findDiff 1}
|
︙ | | |
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
|
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
|
-
-
-
+
+
+
-
+
|
text .ft2.tt -height 60 -width 80 -wrap none -yscrollcommand my_yscroll \
-xscrollcommand ".sbx2 set" -font myfont -borderwidth 0 -padx 0 \
-highlightthickness 0
pack .ft2.tl -side left -fill y
pack .ft2.tt -side right -fill both -expand 1
scrollbar .sbx2 -orient horizontal -command ".ft2.tt xview"
bind MyText <Control-Key-s> "startIncrementalSearch %W"
bindtags .ft1.tt "MyText [bindtags .ft1.tt]"
bindtags .ft2.tt "MyText [bindtags .ft2.tt]"
# Set up a tag for incremental search bindings
textSearch::enableSearch .ft1.tt
textSearch::enableSearch .ft2.tt
label .le -textvariable ::diff(eqLabel) -width 1
label .ls -textvariable ::diff(statusLabel) -width 1 -pady 0 -padx 0
label .ls -textvariable ::textSearch::statusLabel -width 1 -pady 0 -padx 0
canvas .c -width 6 -bd 0 -selectborderwidth 0 -highlightthickness 0
applyColor
.ft1.tt tag configure last -underline 1
.ft2.tt tag configure last -underline 1
foreach w {.ft1.tt .ft1.tl .ft2.tt .ft2.tl} {
bind $w <ButtonPress-3> "zoomRow %W %X %Y %x %y"
|
︙ | | |
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
|
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
|
-
-
-
|
bind .c <Configure> {drawMap %h}
bind . <Key-Up> {scroll -1 u}
bind . <Key-Down> {scroll 1 u}
bind . <Key-Prior> {scroll -1 p}
bind . <Key-Next> {scroll 1 p}
bind . <Key-Escape> {focus .}
bind . <Control-Key-f> {Search}
bind . <Key-F3> {SearchNext}
bind . <Control-Key-F3> {SearchPrev}
pack .mf .mo .ms .mh -in .f -side left
pack .bfn .bfp .eo .lo -in .f -side right
if {$debug == 1} {
menubutton .md -text Debug -menu .md.m -relief ridge
menu .md.m
if {$tcl_platform(platform) == "windows"} {
|
︙ | | |
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
|
3737
3738
3739
3740
3741
3742
3743
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
if {![winfo exists .f]} {
getOptions
makeDiffWin
update idletasks
parseCommandLine
}
# Searching contributed by Ulf Nilsson
# FIXA, test this properly and incorporate into the rest of the file
# Dialog functions from "Practical Programming in Tcl And Tk" by Welch.
proc Dialog_Create {top title args} {
global dialog
if {[winfo exists $top]} {
switch -- [wm state $top] {
normal {
# Raise a buried window
raise $top
}
withdrawn -
iconified {
# Open and restore geometry
wm deiconify $top
catch {wm geometry $top $dialog(geo,$top)}
}
}
return 0
} else {
eval {toplevel $top} $args
wm title $top $title
return 1
}
}
proc Dialog_Wait {top varName {focus {}}} {
upvar $varName var
# Poke the variable if the user nukes the window
bind $top <Destroy> [list set $varName $var]
# Grab focus for the dialog
if {[string length $focus] == 0} {
set focus $top
}
set old [focus -displayof $top]
focus $focus
catch {tkwait visibility $top}
catch {grab $top}
# Wait for the dialog to complete
tkwait variable $varName
catch {grab release $top}
focus $old
}
proc Dialog_Dismiss {top} {
global dialog
# Save current size and position
catch {
# window may have been deleted
set dialog(geo,$top) [wm geometry $top]
wm withdraw $top
}
}
proc Find_Dialog { string } {
global prompt CaseSensitive
set f .prompt
if {[Dialog_Create $f "Find" -borderwidth 10]} {
message $f.msg -text $string -aspect 1000
entry $f.entry -textvariable prompt(result)
checkbutton $f.case -text "Match Case" -variable ::diff(searchcase)
pack $f.case -side right
set b [frame $f.buttons]
pack $f.msg $f.entry $f.buttons -side top -fill x
pack $f.entry -pady 5
button $b.ok -text OK -command {set prompt(ok) 1}
button $b.cancel -text Cancel \
-command {set prompt(ok) 0}
pack $b.ok -side left
pack $b.cancel -side right
bind $f.entry <Return> {set prompt(ok) 1 ; break}
bind $f.entry <Key-Escape> {set prompt(ok) 0 ; break}
}
set prompt(ok) 0
Dialog_Wait $f prompt(ok) $f.entry
Dialog_Dismiss $f
if {$prompt(ok)} {
return $prompt(result)
} else {
return {}
}
}
proc Search {} {
if {![info exists diff(searchcase)]} {
set ::diff(searchcase) 0
set ::diff(searchindex) 1.0
set ::diff(searchstring) ""
}
set ::diff(searchwin) .ft1.tt
if {[focus -displayof .] == ".ft2.tt"} {
set ::diff(searchwin) .ft2.tt
}
set ::diff(searchstring) [Find_Dialog "Please enter string to find"]
if {$::diff(searchcase)} {
set searchpos [$::diff(searchwin) search -count cnt \
$::diff(searchstring) @0,0]
} else {
set searchpos [$::diff(searchwin) search -count cnt -nocase \
$::diff(searchstring) @0,0]
}
if {$searchpos == ""} {
tk_messageBox -message "Search string not found!" -type ok -title Diff
return
}
$::diff(searchwin) see $searchpos
$::diff(searchwin) tag remove sel 1.0 end
$::diff(searchwin) tag add sel $searchpos "$searchpos + $cnt chars"
set ::diff(searchindex) $searchpos
}
proc SearchNext {} {
if {$::diff(searchcase)} {
set searchpos [$::diff(searchwin) search -count cnt \
$::diff(searchstring) "$::diff(searchindex) + 1 chars"]
} else {
set searchpos [$::diff(searchwin) search -count cnt -nocase \
$::diff(searchstring) "$::diff(searchindex) + 1 chars"]
}
if {$searchpos == "" || $searchpos == $::diff(searchindex)} {
tk_messageBox -message "String not found!" -type ok -title Diff
return
}
$::diff(searchwin) see $searchpos
$::diff(searchwin) tag remove sel 1.0 end
$::diff(searchwin) tag add sel $searchpos "$searchpos + $cnt chars"
set ::diff(searchindex) $searchpos
}
proc SearchPrev {} {
if {$::diff(searchcase)} {
set searchpos [$::diff(searchwin) search -count cnt -backwards \
$::diff(searchstring) "$::diff(searchindex) - 1 chars"]
} else {
set searchpos [$::diff(searchwin) search -count cnt -backwards \
-nocase \
$::diff(searchstring) "$::diff(searchindex) - 1 chars"]
}
if {$searchpos == "" || $searchpos == $::diff(searchindex)} {
tk_messageBox -message "String not found!" -type ok -title Diff
return
}
$::diff(searchwin) see $searchpos
$::diff(searchwin) tag remove sel 1.0 end
$::diff(searchwin) tag add sel $searchpos "$searchpos + $cnt chars"
set ::diff(searchindex) $searchpos
}
|