Merge tag 'upstream/8.6.3+dfsg' into experimental
Upstream version 8.6.3+dfsg
Sergei Golovan authored 9 years ago
Sergei Golovan committed 6 years ago
0 | 0 | README: Tk |
1 | This is the Tk 8.6.2 source distribution. | |
1 | This is the Tk 8.6.3 source distribution. | |
2 | 2 | http://sourceforge.net/projects/tcl/files/Tcl/ |
3 | 3 | You can get any source release of Tk from the URL above. |
4 | 4 |
7120 | 7120 | 2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper) |
7121 | 7121 | |
7122 | 7122 | --- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tk/ for details |
7123 | ||
7124 | 2014-08-27 (bug) Cocoa: Crash after [$button destroy] (walzer) | |
7125 | ||
7126 | 2014-09-23 (bug) Cocoa: button and scroll display fixes (walzer) | |
7127 | ||
7128 | 2014-09-24 (bug) Cocoa: improved drawing performance (walzer) | |
7129 | ||
7130 | 2014-10-11 (bug)[9e487e] Phony button clicks from browsers to plugin (nijtmans) | |
7131 | ||
7132 | 2014-10-11 (bug)[810c43] [text] elide changes advance epoch (vogel) | |
7133 | ||
7134 | 2014-10-14 (bug)[fb35eb] fix PNG transparency appearance (walton,culler) | |
7135 | ||
7136 | 2014-10-18 (feature)[TIP 432] Win: updated file dialogs (nadkarni) | |
7137 | ||
7138 | 2014-10-26 Support for Windows 10 (nijtmans) | |
7139 | ||
7140 | 2014-10-28 (bug) OSX: Improved ttk notebook tab metrics for Yosemite (walzer) | |
7141 | ||
7142 | 2014-10-30 (bug)[3417012] [scale -digits $bigValue] segfault (vogel) | |
7143 | ||
7144 | 2014-11-07 (bug)[3529885] [scale] handling of negative resolution (vogel) | |
7145 | ||
7146 | --- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tk/ for details |
18 | 18 | .TP |
19 | 19 | \fB\-initialdir\fR \fIdirname\fR |
20 | 20 | Specifies that the directories in \fIdirectory\fR should be displayed |
21 | when the dialog pops up. If this parameter is not specified, then | |
22 | the directories in the current working directory are displayed. If the | |
21 | when the dialog pops up. If this parameter is not specified, | |
22 | the initial directory defaults to the current working directory | |
23 | on non-Windows systems and on Windows systems prior to Vista. | |
24 | On Vista and later systems, the initial directory defaults to the last | |
25 | user-selected directory for the application. If the | |
23 | 26 | parameter specifies a relative path, the return value will convert the |
24 | 27 | relative path to an absolute path. |
25 | 28 | .TP |
64 | 64 | \fB\-initialdir\fR \fIdirectory\fR |
65 | 65 | . |
66 | 66 | Specifies that the files in \fIdirectory\fR should be displayed |
67 | when the dialog pops up. If this parameter is not specified, then | |
68 | the files in the current working directory are displayed. If the | |
67 | when the dialog pops up. If this parameter is not specified, | |
68 | the initial directory defaults to the current working directory | |
69 | on non-Windows systems and on Windows systems prior to Vista. | |
70 | On Vista and later systems, the initial directory defaults to the last | |
71 | user-selected directory for the application. If the | |
69 | 72 | parameter specifies a relative path, the return value will convert the |
70 | 73 | relative path to an absolute path. |
71 | 74 | .TP |
74 | 74 | #define TK_MAJOR_VERSION 8 |
75 | 75 | #define TK_MINOR_VERSION 6 |
76 | 76 | #define TK_RELEASE_LEVEL TCL_FINAL_RELEASE |
77 | #define TK_RELEASE_SERIAL 2 | |
77 | #define TK_RELEASE_SERIAL 3 | |
78 | 78 | |
79 | 79 | #define TK_VERSION "8.6" |
80 | #define TK_PATCH_LEVEL "8.6.2" | |
80 | #define TK_PATCH_LEVEL "8.6.3" | |
81 | 81 | |
82 | 82 | /* |
83 | 83 | * A special definition used to allow this header file to be included from |
1418 | 1418 | } |
1419 | 1419 | } |
1420 | 1420 | UnhookCascadeEntry(mePtr); |
1421 | menuRefPtr = mePtr->childMenuRefPtr; | |
1421 | 1422 | if (menuRefPtr != NULL) { |
1422 | 1423 | if (menuRefPtr->menuPtr == destroyThis) { |
1423 | 1424 | menuRefPtr->menuPtr = NULL; |
1424 | 1425 | } |
1425 | if (destroyThis != NULL) { | |
1426 | TkDestroyMenu(destroyThis); | |
1427 | } | |
1426 | } | |
1427 | if (destroyThis != NULL) { | |
1428 | TkDestroyMenu(destroyThis); | |
1428 | 1429 | } |
1429 | 1430 | } else { |
1430 | 1431 | UnhookCascadeEntry(mePtr); |
799 | 799 | */ |
800 | 800 | |
801 | 801 | numDigits = scalePtr->digits; |
802 | if (numDigits > TCL_MAX_PREC) { | |
803 | numDigits = 0; | |
804 | } | |
802 | 805 | if (numDigits <= 0) { |
803 | 806 | if (scalePtr->resolution > 0) { |
804 | 807 | /* |
879 | 882 | ComputeScaleGeometry( |
880 | 883 | register TkScale *scalePtr) /* Information about widget. */ |
881 | 884 | { |
882 | char valueString[PRINT_CHARS]; | |
885 | char valueString[TCL_DOUBLE_SPACE]; | |
883 | 886 | int tmp, valuePixels, x, y, extraSpace; |
884 | 887 | Tk_FontMetrics fm; |
885 | 888 | |
1295 | 1298 | register TkScale *scalePtr) /* Info about widget. */ |
1296 | 1299 | { |
1297 | 1300 | if (scalePtr->varNamePtr != NULL) { |
1298 | char string[PRINT_CHARS]; | |
1301 | char string[TCL_DOUBLE_SPACE]; | |
1299 | 1302 | |
1300 | 1303 | sprintf(string, scalePtr->format, scalePtr->value); |
1301 | 1304 | scalePtr->flags |= SETTING_VAR; |
214 | 214 | #define SPACING 2 |
215 | 215 | |
216 | 216 | /* |
217 | * How many characters of space to provide when formatting the scale's value: | |
218 | */ | |
219 | ||
220 | #define PRINT_CHARS 150 | |
221 | ||
222 | /* | |
223 | 217 | * Declaration of procedures used in the implementation of the scale widget. |
224 | 218 | */ |
225 | 219 |
168 | 168 | return TCL_ERROR; |
169 | 169 | } |
170 | 170 | tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL); |
171 | if (tagPtr->elide) { | |
172 | /* | |
173 | * Indices are potentially obsolete after adding or removing | |
174 | * elided character ranges, especially indices having "display" | |
175 | * or "any" submodifier, therefore increase the epoch. | |
176 | */ | |
177 | textPtr->sharedTextPtr->stateEpoch++; | |
178 | } | |
171 | 179 | for (i = 4; i < objc; i += 2) { |
172 | 180 | if (TkTextGetObjIndex(interp, textPtr, objv[i], |
173 | 181 | &index1) != TCL_OK) { |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | |
2 | <svg | |
3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
4 | xmlns:cc="http://creativecommons.org/ns#" | |
5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
6 | xmlns:svg="http://www.w3.org/2000/svg" | |
7 | xmlns="http://www.w3.org/2000/svg" | |
8 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
9 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
10 | width="256" | |
11 | height="256" | |
12 | id="svg2" | |
13 | sodipodi:version="0.32" | |
14 | inkscape:version="0.46" | |
15 | version="1.0" | |
16 | sodipodi:docname="lamp.svg" | |
17 | inkscape:output_extension="org.inkscape.output.svg.inkscape" | |
18 | inkscape:export-filename="C:\Users\pat\Documents\SVG\wish\lamp.png" | |
19 | inkscape:export-xdpi="45" | |
20 | inkscape:export-ydpi="45"> | |
21 | <defs | |
22 | id="defs4"> | |
23 | <inkscape:perspective | |
24 | sodipodi:type="inkscape:persp3d" | |
25 | inkscape:vp_x="0 : 526.18109 : 1" | |
26 | inkscape:vp_y="0 : 1000 : 0" | |
27 | inkscape:vp_z="744.09448 : 526.18109 : 1" | |
28 | inkscape:persp3d-origin="372.04724 : 350.78739 : 1" | |
29 | id="perspective10" /> | |
30 | <inkscape:perspective | |
31 | id="perspective4202" | |
32 | inkscape:persp3d-origin="372.04724 : 350.78739 : 1" | |
33 | inkscape:vp_z="744.09448 : 526.18109 : 1" | |
34 | inkscape:vp_y="0 : 1000 : 0" | |
35 | inkscape:vp_x="0 : 526.18109 : 1" | |
36 | sodipodi:type="inkscape:persp3d" /> | |
37 | </defs> | |
38 | <sodipodi:namedview | |
39 | id="base" | |
40 | pagecolor="#ffffff" | |
41 | bordercolor="#666666" | |
42 | borderopacity="1.0" | |
43 | gridtolerance="10000" | |
44 | guidetolerance="10" | |
45 | objecttolerance="10" | |
46 | inkscape:pageopacity="0.0" | |
47 | inkscape:pageshadow="2" | |
48 | inkscape:zoom="1.9765625" | |
49 | inkscape:cx="122.94071" | |
50 | inkscape:cy="132.27976" | |
51 | inkscape:document-units="px" | |
52 | inkscape:current-layer="layer1" | |
53 | showgrid="false" | |
54 | inkscape:window-width="1253" | |
55 | inkscape:window-height="696" | |
56 | inkscape:window-x="155" | |
57 | inkscape:window-y="130" /> | |
58 | <metadata | |
59 | id="metadata7"> | |
60 | <rdf:RDF> | |
61 | <cc:Work | |
62 | rdf:about=""> | |
63 | <dc:format>image/svg+xml</dc:format> | |
64 | <dc:type | |
65 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |
66 | <dc:title>Wish</dc:title> | |
67 | <cc:license | |
68 | rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /> | |
69 | </cc:Work> | |
70 | <cc:License | |
71 | rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"> | |
72 | <cc:permits | |
73 | rdf:resource="http://creativecommons.org/ns#Reproduction" /> | |
74 | <cc:permits | |
75 | rdf:resource="http://creativecommons.org/ns#Distribution" /> | |
76 | <cc:requires | |
77 | rdf:resource="http://creativecommons.org/ns#Notice" /> | |
78 | <cc:requires | |
79 | rdf:resource="http://creativecommons.org/ns#Attribution" /> | |
80 | <cc:prohibits | |
81 | rdf:resource="http://creativecommons.org/ns#CommercialUse" /> | |
82 | <cc:permits | |
83 | rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> | |
84 | <cc:requires | |
85 | rdf:resource="http://creativecommons.org/ns#ShareAlike" /> | |
86 | </cc:License> | |
87 | </rdf:RDF> | |
88 | </metadata> | |
89 | <g | |
90 | inkscape:label="Layer 1" | |
91 | inkscape:groupmode="layer" | |
92 | id="layer1"> | |
93 | <path | |
94 | id="path4244" | |
95 | d="M 415.15644,157.10949 C 415.95395,156.55285 413.63871,156.20026 408.98022,156.16891 C 400.39605,156.11114 394.03714,153.62619 389.90404,148.71428 C 386.80837,145.03529 386.70005,142.56479 389.55139,140.67157 C 392.33793,138.82138 391.59696,137.74624 384.94986,133.99485 C 377.10186,129.56571 367.45876,120.11083 361.01771,110.52982 C 356.2238,103.39891 354.835,102.02199 351.39782,100.99218 C 348.07028,99.995225 347.3807,99.349945 347.3807,97.233135 C 347.3807,95.827615 348.28389,93.409235 349.38778,91.858965 C 350.70625,90.007345 351.00116,88.909055 350.24734,88.657785 C 348.52268,88.082895 349.12369,71.212775 351.01049,67.236642 C 352.72697,63.619426 358.4038,59.341601 362.8807,58.291741 C 368.19851,57.044683 371.3807,54.944074 371.3807,52.68077 C 371.3807,51.505545 370.0325,48.443002 368.38469,45.875118 C 364.6377,40.035936 363.56213,33.352517 365.70314,29.212273 C 368.86873,23.090696 378.69381,16.159436 389.80945,12.206085 C 396.16957,9.9440683 409.19029,7.9006403 416.8807,7.9576143 C 429.56583,8.0515923 430.45121,10.684797 418.52387,12.844573 C 408.41402,14.675243 395.40533,18.738492 389.39058,21.944323 C 382.19817,25.777834 375.3807,32.024842 375.3807,34.781896 C 375.3807,35.961118 376.7307,39.600271 378.3807,42.868903 C 381.7881,49.618923 382.10517,53.281819 379.7158,58.292375 C 377.80005,62.30975 372.62836,64.868903 366.42556,64.868903 C 361.00253,64.868903 357.56106,66.378947 356.20597,69.353051 C 354.65926,72.747705 355.39815,73.177385 359.69504,71.382035 C 364.84442,69.230481 369.94545,69.499889 378.3807,72.368905 C 386.08854,74.990505 393.19753,75.572485 396.42352,73.845985 C 399.16382,72.379425 400.20168,69.980487 401.8714,61.253678 C 402.8156,56.318785 404.11402,52.717225 405.46884,51.27508 C 409.57057,46.908996 417.3263,46.188254 435.8807,48.4489 C 440.51899,49.014024 441.21999,48.798052 445.57071,45.463499 C 448.15021,43.486471 450.93616,41.868903 451.76169,41.868903 C 456.39638,41.868903 453.00898,47.459001 446.28417,50.908252 C 444.30607,51.922844 437.33107,53.551117 430.78417,54.526637 C 415.93531,56.739186 415.13628,57.382184 413.51607,68.422706 C 412.86967,72.827445 411.54206,77.483105 410.53723,78.868905 C 407.37979,83.223475 398.88397,87.099935 391.31007,87.641845 C 382.34323,88.283415 380.33433,87.656565 374.36395,82.354025 C 370.03354,78.508005 368.69669,77.868905 364.98218,77.868905 C 360.03038,77.868905 356.23453,80.317105 353.75648,85.109115 C 352.31064,87.905065 352.31073,88.250245 353.75754,89.059915 C 354.62947,89.547875 358.14729,92.392935 361.57494,95.382295 C 373.67667,105.93659 385.05189,109.87945 387.55431,104.38722 C 389.01862,101.17342 400.23138,93.868905 403.70042,93.868905 C 405.61476,93.868905 406.3807,93.354525 406.3807,92.068905 C 406.3807,89.300765 408.42915,87.865755 412.3307,87.900705 C 416.2925,87.936195 418.45173,89.238425 420.29952,92.706685 C 421.27351,94.534825 422.08643,94.908595 424.02848,94.421175 C 425.97033,93.933795 427.14185,94.472205 429.40044,96.890035 C 430.98913,98.590725 433.7721,100.41478 435.58483,100.94347 C 438.47789,101.78726 439.06063,101.62756 440.35288,99.636815 C 445.10643,92.313915 453.6284,87.868905 462.91432,87.868905 C 471.25226,87.868905 477.3762,94.861065 477.37915,104.38451 C 477.38132,111.40533 474.73351,115.99375 469.63732,117.8004 C 465.8216,119.15312 465.3143,119.09082 460.41928,116.6683 L 455.23918,114.10469 L 455.55994,118.7368 C 455.85694,123.02582 455.69553,123.39336 453.3807,123.69898 C 452.0057,123.88052 449.0807,125.72311 446.8807,127.79362 C 444.6807,129.86413 441.3057,132.60737 439.3807,133.88971 C 437.4557,135.17205 435.71687,136.34329 435.51663,136.49247 C 435.3164,136.64165 436.1039,138.303 437.26663,140.18434 C 440.00489,144.61494 439.95186,145.14881 436.36797,149.23063 C 433.17349,152.86894 427.63954,155.56972 421.9273,156.27821 C 420.02228,156.51449 417.43247,156.99854 416.17217,157.35387 C 414.69967,157.76902 414.33665,157.68168 415.15644,157.10949 z M 461.66289,105.49411 C 466.02111,106.09147 466.3807,105.96302 467.55302,103.39006 C 468.64455,100.9944 468.56244,100.47497 466.9,99.259355 C 463.50165,96.774425 454.03816,98.379955 450.76501,101.99675 C 449.2334,103.68915 449.23826,104.00257 450.83387,106.43778 L 452.55063,109.05789 L 454.78597,106.9579 C 456.6536,105.20335 457.78484,104.96256 461.66289,105.49411 z M 480.08955,157.24443 C 479.03653,156.19141 479.23148,154.86891 480.43972,154.86891 C 481.02218,154.86891 481.22062,155.31891 480.8807,155.86891 C 480.53516,156.42801 481.28072,156.85424 482.57168,156.83564 L 484.8807,156.80237 L 482.82974,155.08564 C 481.26204,153.77341 480.78031,152.19079 480.78523,148.36891 C 480.78878,145.61891 480.4093,142.24744 479.94194,140.87675 C 479.17159,138.6174 479.24977,138.51536 480.77884,139.78437 C 482.10899,140.8883 482.72069,140.92526 483.67308,139.95921 C 484.61817,139.00056 484.50928,138.45979 483.17218,137.47168 C 480.67758,135.62817 479.8077,125.30277 482.07374,124.43321 C 484.50372,123.50074 486.09262,125.4993 484.69743,127.73335 C 484.07418,128.73133 483.86705,130.0378 484.23714,130.63662 C 484.60722,131.23543 484.90343,137.49517 484.89536,144.54714 C 484.88148,156.68738 484.7722,157.38444 482.83955,157.66109 C 481.71692,157.82179 480.47942,157.63429 480.08955,157.24443 z M 482.25305,118.70224 C 481.74301,109.37956 481.9401,107.3904 483.40197,107.10616 C 484.64333,106.86478 484.91924,108.04245 484.9015,113.50646 C 484.88705,117.95665 484.46065,120.34226 483.63023,120.61907 C 482.88848,120.86632 482.32882,120.08736 482.25305,118.70224 z M 379.00441,69.349758 C 376.06529,66.410633 377.10113,63.67485 383.3807,57.791426 C 389.1743,52.363315 389.3807,51.996847 389.3807,47.13811 C 389.3807,42.527633 389.68488,41.874271 393.01325,39.335601 C 396.00346,37.054853 398.10542,36.431883 404.90027,35.812562 C 416.73834,34.733574 419.96577,32.472032 421.51698,24.168809 C 422.76442,17.491595 424.77273,15.934307 435.02949,13.690888 C 444.53714,11.61132 473.5654,10.035808 469.8807,11.799335 C 462.39978,15.379766 448.69837,19.973669 443.16225,20.757679 C 434.68965,21.957548 433.72397,22.530265 426.73194,30.502062 C 423.51376,34.171199 419.46171,37.767608 417.72739,38.494081 C 415.99308,39.220554 410.20812,40.121839 404.87193,40.496935 C 392.82345,41.34386 390.96003,42.710991 391.65408,50.194442 C 392.08855,54.878864 391.98999,55.090456 388.28416,57.429845 C 384.39732,59.883502 381.94201,63.096875 383.08255,64.23742 C 383.42987,64.584736 386.14059,64.868903 389.10639,64.868903 C 395.04346,64.868903 395.33233,66.026622 389.95576,68.273094 C 383.92501,70.792905 380.75884,71.104181 379.00441,69.349758 z M 434.60321,38.312199 C 427.83023,33.568222 439.44607,28.281864 448.8156,31.844152 C 452.78899,33.354831 451.84999,34.868903 446.93972,34.868903 C 442.58714,34.868903 440.3344,36.104222 442.3807,37.368903 C 442.94864,37.719911 443.15443,38.426005 442.838,38.938001 C 441.93507,40.398969 437.05277,40.027939 434.60321,38.312199 z M 399.1307,26.788804 C 398.1682,26.228199 397.3807,24.907716 397.3807,23.854397 C 397.3807,19.888982 404.86882,18.583104 410.97957,21.482844 C 414.6962,23.2465 415.79992,26.473299 412.3807,25.579154 C 411.08084,25.239232 410.3807,25.548472 410.3807,26.462523 C 410.3807,28.151255 401.89255,28.397435 399.1307,26.788804 z" | |
96 | style="fill:#a19ea5" /> | |
97 | <path | |
98 | id="path4242" | |
99 | d="M 105.76326,194.33186 C 96.199481,191.3282 86.035511,183.95952 84.415432,178.8551 C 83.669624,176.50526 84.619431,173.43151 87.043677,170.34958 C 89.131529,167.6953 90.839771,164.85771 90.839771,164.04381 C 90.839771,163.22992 85.918717,159.94111 79.904096,156.73534 C 65.654177,149.14022 48.534772,133.52161 39.035518,119.44956 C 25.94837,100.06246 20.676575,94.528555 15.260318,94.492261 C 12.544659,94.474078 9.7834525,93.586577 9.1243032,92.52005 C 7.1111542,89.262706 9.8582449,82.714405 14.697759,79.234457 L 19.284506,75.93627 L 32.226689,86.830368 C 45.242318,97.786283 61.932601,107.70092 70.896763,109.80181 C 74.874966,110.73415 76.973245,109.63504 82.823316,103.55448 C 91.577415,94.455454 106.5437,84.581571 109.7288,85.803804 C 112.30619,86.792846 119.14001,82.528975 119.50937,79.701372 C 119.63551,78.735652 119.84193,77.072338 119.96808,76.00515 C 120.1008,74.882421 123.45816,74.302552 127.93568,74.629009 C 134.42967,75.102512 136.37445,76.225828 140.03071,81.615217 C 142.42694,85.147312 144.93094,87.89196 145.59516,87.714438 C 146.25938,87.536916 148.11372,86.880753 149.71593,86.256298 C 151.55372,85.540025 154.60158,87.11622 157.97278,90.526315 C 160.91183,93.499275 166.37382,96.761572 170.11052,97.77588 C 176.63713,99.547487 177.10469,99.356038 181.99078,92.911204 C 189.2319,83.360053 193.30348,80.314122 203.42538,76.876064 C 213.99829,73.284813 227.86298,74.099195 234.92479,78.726276 C 249.97261,88.585994 246.13011,121.71137 229.57839,124.81649 C 217.25776,127.12786 203.68336,119.34028 204.912,110.66549 C 205.47565,106.68593 206.35069,106.38575 217.3878,106.38575 C 228.7903,106.38575 229.33057,106.17926 231.11535,101.13898 C 232.77591,96.449555 232.39214,95.427248 227.50256,91.5151 C 221.01109,86.321288 212.43622,85.84151 203.33017,90.162611 C 193.1595,94.988901 192.26182,99.390772 198.85898,112.08736 C 201.94886,118.03401 204.71121,125.78933 204.99756,129.32143 C 205.44391,134.8274 204.9522,135.7516 201.55033,135.80083 C 199.36802,135.83241 193.58823,139.5894 188.70635,144.14971 C 183.82446,148.71 177.14673,154.02271 173.86693,155.95573 C 170.58712,157.88875 167.90365,160.16082 167.90365,161.00476 C 167.90365,161.8487 169.76144,165.83259 172.03207,169.85786 L 176.16049,177.17652 L 169.56843,183.28424 C 155.87761,195.96917 126.9335,200.98073 105.76326,194.33186 z" | |
100 | style="fill:#edd400" | |
101 | sodipodi:nodetypes="cssssssscccsssssssssssssssssssssssssscccc" /> | |
102 | <path | |
103 | id="path4238" | |
104 | d="M 105.76326,195.26015 C 91.2682,190.70773 79.926103,178.96138 85.064191,173.82331 C 86.412111,172.47539 90.329525,173.11166 98.078673,175.93715 C 114.43988,181.90274 127.59098,183.59079 140.28535,181.35472 C 153.94689,178.94829 158.14857,176.20124 155.47497,171.42379 C 153.72375,168.29452 151.50157,168.02067 131.82394,168.50911 C 119.87893,168.8056 106.35554,168.19755 101.77196,167.15787 C 89.698721,164.41931 70.093174,152.93068 56.939947,140.88681 C 44.534571,129.52772 29.195171,107.81695 31.238758,104.51038 C 31.937342,103.38006 30.70876,100.53908 28.508587,98.197089 C 25.268931,94.748645 23.184206,94.116538 17.545112,94.872902 C 13.258048,95.447908 10.071549,94.981011 9.2539007,93.658026 C 7.1231945,90.210482 9.7375867,83.729446 14.697767,80.162746 L 19.284499,76.864559 L 32.226699,87.758658 C 47.530117,100.64033 63.263112,109.42753 74.136789,111.1663 C 82.555064,112.51244 85.287914,115.79329 81.646114,120.18138 C 77.940809,124.646 66.533098,123.44089 54.981809,117.36455 C 49.183358,114.31439 44.065729,112.19224 43.609327,112.64866 C 42.195407,114.06256 58.535133,129.40174 68.983105,136.4687 C 82.893943,145.87792 99.314337,150.64583 118.36258,150.80678 C 145.52872,151.03631 162.76551,145.71413 177.25684,132.62207 C 188.34716,122.60263 188.94814,120.5505 182.73878,113.90333 C 175.81472,106.49109 168.70623,106.44964 158.32432,113.76097 C 147.98605,121.04152 132.76454,123.60855 116.61147,120.79561 C 102.20671,118.28713 93.486961,114.8298 92.037334,111.05211 C 91.442016,109.50075 89.277658,108.23147 87.227649,108.23147 C 85.17764,108.23147 83.500363,107.13687 83.500363,105.79902 C 83.500363,100.44846 105.44657,85.088853 110.38429,86.983634 C 112.97609,87.978198 112.0154,89.694925 104.72512,97.096507 L 95.944216,106.01146 L 108.89174,108.95633 C 125.60393,112.75743 132.19327,112.622 141.75698,108.28088 C 150.27283,104.41539 151.12833,102.11981 146.51015,95.52644 C 143.6484,91.440733 143.6695,91.029744 146.86084,88.696177 C 151.48792,85.312779 152.0368,85.452081 158.05294,91.536605 C 160.9479,94.464463 166.37382,97.689862 170.11052,98.704169 C 176.63713,100.47578 177.10469,100.28433 181.99078,93.839493 C 189.2319,84.288343 193.30348,81.242411 203.42538,77.804353 C 214.46761,74.053691 228.66626,75.111117 235.46998,80.190801 C 246.39872,88.350288 247.47071,106.01058 237.63431,115.84696 C 231.52704,121.95423 223.54183,122.71682 215.49179,117.96155 C 204.60894,111.53288 206.6535,105.81232 219.23735,107.48162 C 226.96374,108.50657 228.35458,108.17571 230.11029,104.8951 C 232.76067,99.942824 232.67127,92.999442 229.92172,90.249895 C 226.72145,87.049615 210.78434,87.553668 203.33017,91.0909 C 193.1595,95.917191 192.26182,100.31906 198.85898,113.01565 C 201.94886,118.9623 204.71121,126.71762 204.99756,130.24972 C 205.44391,135.75569 204.9522,136.67989 201.55033,136.72912 C 199.36802,136.7607 193.58823,140.51769 188.70635,145.078 C 183.82446,149.63829 177.14673,154.951 173.86693,156.88402 C 170.58712,158.81704 167.90365,161.08911 167.90365,161.93305 C 167.90365,162.77699 169.76144,166.76088 172.03207,170.78615 L 176.16049,178.10481 L 169.56843,184.21253 C 155.87761,196.89746 126.9335,201.90902 105.76326,195.26015 z M 124.39689,92.286528 C 123.73252,90.555233 124.16318,88.866818 125.37189,88.463902 C 128.82997,87.311229 127.89606,85.131073 122.98588,82.893835 C 115.70755,79.577611 118.94662,74.88732 128.04458,75.568657 C 133.65369,75.988728 136.35232,77.369401 139.27998,81.316906 L 143.13312,86.512278 L 137.98496,90.949892 C 131.98533,96.12141 126.09095,96.701224 124.39689,92.286528 z" | |
105 | style="fill:#555753" | |
106 | sodipodi:nodetypes="cssssssssssscccsssssssssssssscccsssssssssssssssssssscccccssscccc" /> | |
107 | <path | |
108 | id="path4234" | |
109 | d="M 110.50482,194.3016 C 101.29684,192.13337 94.533525,188.48684 89.271383,182.85325 C 82.390918,175.4871 85.936884,174.28107 99.528813,179.36455 C 115.59245,185.37247 143.30992,186.28633 152.7661,181.11982 C 159.03409,177.69523 160.98588,170.45868 156.43581,167.51383 C 155.17435,166.69739 142.9955,165.96174 129.37171,165.87907 C 108.80987,165.75428 102.74285,165.05333 93.663859,161.75352 C 73.025491,154.25244 49.561448,135.01491 39.768427,117.56612 C 35.780389,110.46041 36.411322,110.85564 48.942698,123.31318 C 70.302623,144.54723 92.258893,154.15548 119.15432,154.03838 C 135.83546,153.96576 152.56346,150.85172 163.02604,145.87134 C 172.41161,141.40363 189.9219,125.23231 189.9219,121.03213 C 189.9219,119.19248 187.7843,115.1469 185.17167,112.04198 C 178.58784,104.21754 168.03965,104.18244 155.55484,111.94343 C 150.18536,115.28129 142.95424,117.92581 137.39714,118.58397 C 127.97216,119.70021 104.80591,116.69758 100.01936,113.73933 C 94.450094,110.29735 100.24351,109.86707 113.23644,112.75774 C 127.9361,116.02809 138.20198,114.95313 146.93857,109.22869 C 153.28212,105.07225 154.19121,101.72283 150.50345,96.094621 C 148.24619,92.649609 147.93449,90.769617 149.38072,89.323385 C 150.82695,87.877153 153.0819,88.968084 157.50247,93.252689 C 160.86829,96.51495 166.83523,100.07126 170.76237,101.15561 C 177.28458,102.95648 178.14485,102.76481 180.70126,98.941361 C 190.46478,84.338673 203.44977,77.038962 219.66199,77.038962 C 239.73552,77.038962 249.19265,98.555619 235.51724,113.11244 C 230.28699,118.67977 219.45458,118.99815 214.68225,113.7248 C 210.40882,109.00271 211.87531,107.60004 218.46592,110.10579 C 222.73772,111.72993 224.48175,111.47356 228.23768,108.66934 C 235.27205,103.41743 237.01116,96.063887 232.61714,90.15151 C 228.70991,84.894138 221.3182,83.243302 210.64805,85.245036 C 203.22425,86.637745 191.75676,96.268143 191.75676,101.10994 C 191.75676,103.03903 194.23381,109.00645 197.26132,114.37093 C 203.6019,125.60581 204.5447,133.91945 199.47821,133.91945 C 197.66998,133.91945 192.50945,137.70093 188.01037,142.32275 C 183.51127,146.94454 176.32104,152.80279 172.03207,155.34108 C 163.73389,160.25204 162.48268,163.20921 167.08641,167.02996 C 171.28,170.51035 173.54029,175.47679 172.34649,178.58776 C 170.71762,182.83253 158.4385,190.19925 147.65345,193.40206 C 137.09511,196.53755 121.59442,196.91291 110.50482,194.3016 z M 56.408298,114.61872 C 49.129046,110.97705 38.716927,103.92466 33.270272,98.946719 L 23.367251,89.895915 L 16.969775,92.568949 C 9.3420288,95.756035 8.6495364,95.306148 9.7405408,87.872639 C 10.344685,83.75629 11.031471,82.8609 12.211447,84.651204 C 13.540212,86.667268 14.305567,86.530535 16.306604,83.919666 C 17.660139,82.153618 19.320682,80.708671 19.996697,80.708671 C 20.672694,80.708671 26.554779,85.229385 33.067979,90.7547 C 45.470438,101.27603 59.192323,109.15379 71.573791,112.86101 C 75.610471,114.06964 78.913208,116.20591 78.913208,117.60829 C 78.913208,122.46961 69.63857,121.23756 56.408298,114.61872 z M 87.170053,103.7711 C 87.170053,101.119 98.339717,92.839094 105.19954,90.406132 C 109.67365,88.819295 99.599675,99.261745 92.756946,103.30384 C 87.921829,106.16003 87.170053,106.22289 87.170053,103.7711 z M 129.35231,88.988873 C 132.38564,85.333953 130.37875,80.708671 125.7596,80.708671 C 123.70957,80.708671 122.03229,79.882986 122.03229,78.873816 C 122.03229,76.472212 130.46732,76.514212 134.9969,78.938366 C 141.6449,82.496277 137.51074,91.717796 129.26767,91.717796 C 127.62199,91.717796 127.64274,91.04879 129.35231,88.988873 z" | |
110 | style="fill:#000000;fill-opacity:1" | |
111 | sodipodi:nodetypes="cssssssssssssssssssssssssssssssssssssscccccsssssssccssccssssc" /> | |
112 | </g> | |
113 | </svg> |
222 | 222 | set inc [$w cget -resolution] |
223 | 223 | } |
224 | 224 | if {([$w cget -from] > [$w cget -to]) ^ ($dir eq "up")} { |
225 | set inc [expr {-$inc}] | |
225 | if {$inc > 0} { | |
226 | set inc [expr {-$inc}] | |
227 | } | |
228 | } else { | |
229 | if {$inc < 0} { | |
230 | set inc [expr {-$inc}] | |
231 | } | |
226 | 232 | } |
227 | 233 | $w set [expr {[$w get] + $inc}] |
228 | 234 |
12 | 12 | # Insist on running with compatible version of Tcl |
13 | 13 | package require Tcl 8.6 |
14 | 14 | # Verify that we have Tk binary and script components from the same release |
15 | package require -exact Tk 8.6.2 | |
15 | package require -exact Tk 8.6.3 | |
16 | 16 | |
17 | 17 | # Create a ::tk namespace |
18 | 18 | namespace eval ::tk { |
1345 | 1345 | TK_VERSION=8.6 |
1346 | 1346 | TK_MAJOR_VERSION=8 |
1347 | 1347 | TK_MINOR_VERSION=6 |
1348 | TK_PATCH_LEVEL=".2" | |
1348 | TK_PATCH_LEVEL=".3" | |
1349 | 1349 | VERSION=${TK_VERSION} |
1350 | 1350 | LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" |
1351 | 1351 | |
4859 | 4859 | LD_SEARCH_FLAGS="" |
4860 | 4860 | TCL_NEEDS_EXP_FILE=1 |
4861 | 4861 | TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' |
4862 | TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' | |
4863 | TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' | |
4862 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" | |
4864 | 4863 | echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5 |
4865 | 4864 | echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6 |
4866 | 4865 | if test "${ac_cv_cygwin+set}" = set; then |
5526 | 5525 | LDFLAGS="" |
5527 | 5526 | ;; |
5528 | 5527 | *) |
5529 | SHLIB_CFLAGS="-fPIC" | |
5528 | case "$arch" in | |
5529 | alpha|sparc64) | |
5530 | SHLIB_CFLAGS="-fPIC" | |
5531 | ;; | |
5532 | *) | |
5533 | SHLIB_CFLAGS="-fpic" | |
5534 | ;; | |
5535 | esac | |
5530 | 5536 | SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' |
5531 | 5537 | SHLIB_SUFFIX=".so" |
5532 | 5538 | DL_OBJS="tclLoadDl.o" |
5593 | 5599 | # This configuration from FreeBSD Ports. |
5594 | 5600 | SHLIB_CFLAGS="-fPIC" |
5595 | 5601 | SHLIB_LD="${CC} -shared" |
5596 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname=\$@" | |
5597 | TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$@" | |
5602 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@" | |
5598 | 5603 | SHLIB_SUFFIX=".so" |
5599 | 5604 | DL_OBJS="tclLoadDl.o" |
5600 | 5605 | DL_LIBS="" |
6832 | 6837 | if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then |
6833 | 6838 | |
6834 | 6839 | LIB_SUFFIX=${SHARED_LIB_SUFFIX} |
6835 | MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' | |
6840 | MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' | |
6836 | 6841 | if test "${SHLIB_SUFFIX}" = ".dll"; then |
6837 | 6842 | |
6838 | 6843 | INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' |
65 | 65 | if ( y > parent_height - 20 || y + widget_height < 0 ) { |
66 | 66 | return; |
67 | 67 | } |
68 | ||
69 | /* Do not draw if the widget is completely outside of its parent, or within 50 pixels of the right border; this prevents buttons from being drawn on peer widgets as scrolling occurs. */ | |
70 | int parent_width = Tk_Width(Tk_Parent(tkwin)); | |
71 | int widget_width = Tk_Width(tkwin); | |
72 | int x = Tk_X(tkwin); | |
73 | if (x > parent_width - 50 || x < 0) { | |
74 | return; | |
75 | } | |
68 | 76 | } |
69 | 77 | [super drawRect:dirtyRect]; |
70 | 78 | } |
188 | 196 | [macButtonPtr->button setTag:(NSInteger)-1]; |
189 | 197 | |
190 | 198 | TkMacOSXMakeCollectableAndRelease(macButtonPtr->button); |
191 | TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage); | |
199 | TkMacOSXMakeCollectableAndRelease(macButtonPtr->image); | |
192 | 200 | TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage); |
193 | 201 | TkMacOSXMakeCollectableAndRelease(macButtonPtr->tristateImage); |
194 | 202 | } |
462 | 462 | * Color image |
463 | 463 | */ |
464 | 464 | |
465 | CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); | |
465 | CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); | |
466 | 466 | |
467 | 467 | bitsPerComponent = 8; |
468 | 468 | bitsPerPixel = 32; |
235 | 235 | if (!uname(&name)) { |
236 | 236 | tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10; |
237 | 237 | } |
238 | if (tkMacOSXMacOSXVersion && | |
238 | /*Check for new versioning scheme on Yosemite (10.10) and later.*/ | |
239 | if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) { | |
240 | tkMacOSXMacOSXVersion = MAC_OS_X_VERSION_MIN_REQUIRED/100; | |
241 | } | |
242 | if (tkMacOSXMacOSXVersion && MAC_OS_X_VERSION_MIN_REQUIRED < 100000 && | |
239 | 243 | tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) { |
240 | 244 | Tcl_Panic("Mac OS X 10.%d or later required !", |
241 | 245 | (MAC_OS_X_VERSION_MIN_REQUIRED/10)-100); |
242 | 246 | } |
247 | ||
243 | 248 | |
244 | 249 | #ifdef TK_FRAMEWORK |
245 | 250 | /* |
144 | 144 | Tk_Window tkwin = scalePtr->tkwin; |
145 | 145 | Tcl_Interp *interp = scalePtr->interp; |
146 | 146 | int result; |
147 | char string[PRINT_CHARS]; | |
147 | char string[TCL_DOUBLE_SPACE]; | |
148 | 148 | MacScale *macScalePtr = (MacScale *) clientData; |
149 | 149 | Rect r; |
150 | 150 | WindowRef windowRef; |
20 | 20 | #endif |
21 | 21 | */ |
22 | 22 | |
23 | NSRect TkMacOSXGetScrollFrame(TkScrollbar *scrlPtr); | |
24 | ||
25 | /* | |
26 | * A subclass of NSScroller with sanity checking: | |
27 | * | |
28 | * NSScrollers created by Tk will have their tag set to a pointer to the | |
29 | * TkScrollbar which manages the NSScroller. This allows an NSScroller to be | |
30 | * aware of the state of its Tk parent. This subclass overrides the drawRect | |
31 | * method so that it will not draw itself if the widget is completely outside | |
32 | * of its container. | |
33 | */ | |
34 | ||
35 | @interface TkNSScroller: NSScroller | |
36 | -(void) drawRect:(NSRect)dirtyRect; | |
37 | ||
38 | @end | |
39 | ||
40 | @implementation TkNSScroller | |
41 | ||
42 | - (void)drawRect:(NSRect)dirtyRect | |
43 | { | |
44 | NSInteger tag = [self tag]; | |
45 | if ( tag != -1) { | |
46 | TkScrollbar *scrollPtr = (TkScrollbar *)tag; | |
47 | MacDrawable* macWin = (MacDrawable *)scrollPtr; | |
48 | Tk_Window tkwin = scrollPtr->tkwin; | |
49 | NSRect Tkframe = TkMacOSXGetScrollFrame(scrollPtr); | |
50 | /* Do not draw if the widget is misplaced or unmapped. */ | |
51 | if ( NSIsEmptyRect(Tkframe) || | |
52 | ! macWin->winPtr->flags & TK_MAPPED || | |
53 | ! NSEqualRects(Tkframe, [self frame]) | |
54 | ) { | |
55 | return; | |
56 | } | |
57 | ||
58 | /* | |
59 | * Do not draw if the widget is completely outside of its parent. | |
60 | */ | |
61 | if (tkwin) { | |
62 | int parent_height = Tk_Height(Tk_Parent(tkwin)); | |
63 | int widget_height = Tk_Height(tkwin); | |
64 | int y = Tk_Y(tkwin); | |
65 | if ( y > parent_height || y + widget_height < 0 ) { | |
66 | return; | |
67 | } | |
68 | ||
69 | int parent_width = Tk_Width(Tk_Parent(tkwin)); | |
70 | int widget_width = Tk_Width(tkwin); | |
71 | int x = Tk_X(tkwin); | |
72 | if (x > parent_width || x + widget_width < 0) { | |
73 | return; | |
74 | } | |
75 | } | |
76 | } | |
77 | [super drawRect:dirtyRect]; | |
78 | } | |
79 | ||
80 | @end | |
81 | ||
82 | ||
83 | ||
23 | 84 | /* |
24 | 85 | * Declaration of Mac specific scrollbar structure. |
25 | 86 | */ |
26 | 87 | |
27 | 88 | typedef struct MacScrollbar { |
28 | 89 | TkScrollbar info; |
29 | NSScroller *scroller; | |
90 | TkNSScroller *scroller; | |
30 | 91 | int variant; |
31 | 92 | } MacScrollbar; |
32 | 93 | |
48 | 109 | static void UpdateScrollbarMetrics(void); |
49 | 110 | static void ScrollbarEventProc(ClientData clientData, |
50 | 111 | XEvent *eventPtr); |
112 | ||
51 | 113 | |
52 | 114 | /* |
53 | 115 | * The class procedure table for the scrollbar widget. |
65 | 127 | #define NSAppleAquaScrollBarVariantChanged @"AppleAquaScrollBarVariantChanged" |
66 | 128 | |
67 | 129 | @implementation TKApplication(TKScrlbr) |
68 | - (void) tkScroller: (NSScroller *) scroller | |
130 | - (void) tkScroller: (TkNSScroller *) scroller | |
69 | 131 | { |
70 | 132 | NSScrollerPart hitPart = [scroller hitPart]; |
71 | 133 | TkScrollbar *scrollPtr = (TkScrollbar *)[scroller tag]; |
253 | 315 | TkScrollbar *scrollPtr) |
254 | 316 | { |
255 | 317 | MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; |
256 | NSScroller *scroller = macScrollPtr->scroller; | |
257 | [scroller setTag:(NSInteger)0]; | |
318 | TkNSScroller *scroller = macScrollPtr->scroller; | |
319 | [scroller setTag:(NSInteger)-1]; | |
258 | 320 | |
259 | 321 | TkMacOSXMakeCollectableAndRelease(macScrollPtr->scroller); |
260 | 322 | } |
283 | 345 | { |
284 | 346 | TkScrollbar *scrollPtr = clientData; |
285 | 347 | MacScrollbar *macScrollPtr = clientData; |
286 | NSScroller *scroller = macScrollPtr->scroller; | |
348 | TkNSScroller *scroller = macScrollPtr->scroller; | |
287 | 349 | Tk_Window tkwin = scrollPtr->tkwin; |
288 | 350 | TkWindow *winPtr = (TkWindow *) tkwin; |
289 | 351 | MacDrawable *macWin = (MacDrawable *) winPtr->window; |
356 | 418 | [scroller setEnabled:(knobProportion < 1.0 && |
357 | 419 | (scrollPtr->vertical ? frame.size.height : frame.size.width) > |
358 | 420 | metrics[macScrollPtr->variant].minHeight)]; |
421 | // [scroller setEnabled: YES]; | |
359 | 422 | [scroller setDoubleValue:scrollPtr->firstFraction / (1.0 - knobProportion)]; |
360 | 423 | [scroller setKnobProportion:knobProportion]; |
361 | 424 | [scroller displayRectIgnoringOpacity:[scroller bounds]]; |
362 | 425 | TkMacOSXRestoreDrawingContext(&dc); |
363 | #ifdef TK_MAC_DEBUG_SCROLLBAR | |
426 | #ifdef TK_MAC_DEBUG_SCROLLBAR | |
364 | 427 | TKLog(@"scroller %s frame %@ width %d height %d", |
365 | 428 | ((TkWindow *)scrollPtr->tkwin)->pathName, NSStringFromRect(frame), |
366 | 429 | Tk_Width(tkwin), Tk_Height(tkwin)); |
367 | #endif | |
430 | #endif | |
368 | 431 | } |
369 | 432 | |
370 | 433 | /* |
392 | 455 | * changed. */ |
393 | 456 | { |
394 | 457 | MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; |
395 | NSScroller *scroller = macScrollPtr->scroller; | |
458 | TkNSScroller *scroller = macScrollPtr->scroller; | |
396 | 459 | int width, height, variant, fieldLength; |
397 | 460 | |
398 | 461 | if (scrollPtr->highlightWidth < 0) { |
420 | 483 | } |
421 | 484 | if (!scroller) { |
422 | 485 | if ((width > height) ^ !scrollPtr->vertical) { |
423 | /* -[NSScroller initWithFrame:] determines horizonalness for the | |
486 | /* -[NSScroller initWithFrame:] determines horizontalness for the | |
424 | 487 | * lifetime of the scroller via isHoriz = (width > height) */ |
425 | 488 | if (scrollPtr->vertical) { |
426 | 489 | width = height; |
431 | 494 | width = 2; |
432 | 495 | } |
433 | 496 | } |
434 | scroller = [[NSScroller alloc] initWithFrame: | |
497 | scroller = [[TkNSScroller alloc] initWithFrame: | |
435 | 498 | NSMakeRect(0, 0, width, height)]; |
436 | 499 | macScrollPtr->scroller = TkMacOSXMakeUncollectable(scroller); |
437 | 500 | [scroller setAction:@selector(tkScroller:)]; |
552 | 615 | /* Scrollbar widget record. */ |
553 | 616 | int x, int y) /* Coordinates within scrollPtr's window. */ |
554 | 617 | { |
555 | NSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller; | |
618 | TkNSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller; | |
556 | 619 | MacDrawable *macWin = (MacDrawable *) |
557 | 620 | ((TkWindow *) scrollPtr->tkwin)->window; |
558 | 621 | NSView *view = TkMacOSXDrawableView(macWin); |
613 | 676 | TkScrollbarEventProc(clientData, eventPtr); |
614 | 677 | } |
615 | 678 | } |
679 | ||
680 | ||
681 | /* | |
682 | *---------------------------------------------------------------------- | |
683 | * | |
684 | * TkMacOSXGetScrollFrame -- | |
685 | * | |
686 | * Computes a frame for an NSScroller that will correspond to where | |
687 | * Tk thinks the scroller is located. | |
688 | * | |
689 | * Results: | |
690 | * Returns an NSRect describing a frame for an NSScrollbar. | |
691 | * | |
692 | * Side effects: | |
693 | * None | |
694 | * | |
695 | *---------------------------------------------------------------------- | |
696 | */ | |
697 | NSRect TkMacOSXGetScrollFrame( | |
698 | TkScrollbar *scrlPtr) | |
699 | { | |
700 | MacScrollbar *macscrlPtr = (MacScrollbar *) scrlPtr; | |
701 | Tk_Window tkwin = scrlPtr->tkwin; | |
702 | TkWindow *winPtr = (TkWindow *) tkwin; | |
703 | if (tkwin) { | |
704 | MacDrawable *macWin = (MacDrawable *) winPtr->window; | |
705 | NSView *view = TkMacOSXDrawableView(macWin); | |
706 | CGFloat viewHeight = [view bounds].size.height; | |
707 | NSRect frame = NSMakeRect(macWin->xOff, macWin->yOff, | |
708 | Tk_Width(tkwin), Tk_Height(tkwin)); | |
709 | ||
710 | frame.origin.y = viewHeight - (frame.origin.y + frame.size.height); | |
711 | return frame; | |
712 | } else { | |
713 | return NSZeroRect; | |
714 | } | |
715 | } | |
716 | ||
717 | ||
616 | 718 | |
617 | 719 | /* |
618 | 720 | * Local Variables: |
355 | 355 | event.xexpose.width = damageBounds.size.width; |
356 | 356 | event.xexpose.height = damageBounds.size.height; |
357 | 357 | event.xexpose.count = 0; |
358 | Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); | |
359 | #ifdef TK_MAC_DEBUG_DRAWING | |
360 | TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x, | |
358 | Tk_HandleEvent(&event); | |
359 | ||
360 | #ifdef TK_MAC_DEBUG_DRAWING | |
361 | NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x, | |
361 | 362 | event.xexpose.y, event.xexpose.width, event.xexpose.height); |
362 | #endif | |
363 | #endif | |
363 | 364 | |
364 | 365 | /* |
365 | 366 | * Generate updates for the children of this window |
386 | 387 | /* |
387 | 388 | * TODO: Here we should handle out of process embedding. |
388 | 389 | */ |
389 | } | |
390 | } | |
390 | 391 | |
391 | 392 | return 1; |
392 | 393 | } |
767 | 768 | @interface TKContentView(TKWindowEvent) |
768 | 769 | - (void) drawRect: (NSRect) rect; |
769 | 770 | - (void) generateExposeEvents: (HIMutableShapeRef) shape; |
771 | - (void) viewDidEndLiveResize; | |
772 | - (void) viewWillDraw; | |
770 | 773 | - (BOOL) isOpaque; |
771 | 774 | - (BOOL) wantsDefaultClipping; |
772 | 775 | - (BOOL) acceptsFirstResponder; |
776 | 779 | @implementation TKContentView |
777 | 780 | @end |
778 | 781 | |
782 | double drawTime; | |
783 | ||
784 | /* | |
785 | * Set a minimum time for drawing to render. With removal of private NSView API's, default drawing | |
786 | * is slower and less responsive. This number, which seems feasible after some experimentatation, skips | |
787 | * some drawing to avoid lag. | |
788 | */ | |
789 | ||
790 | #define MAX_DYNAMIC_TIME .000000001 | |
791 | ||
792 | /*Restrict event processing to Expose events.*/ | |
779 | 793 | static Tk_RestrictAction |
780 | 794 | ExposeRestrictProc( |
781 | 795 | ClientData arg, |
784 | 798 | return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg) |
785 | 799 | ? TK_PROCESS_EVENT : TK_DEFER_EVENT); |
786 | 800 | } |
801 | ||
787 | 802 | |
788 | 803 | @implementation TKContentView(TKWindowEvent) |
789 | 804 | |
799 | 814 | NSRectFillListUsingOperation(rectsBeingDrawn, rectsBeingDrawnCount, |
800 | 815 | NSCompositeSourceOver); |
801 | 816 | #endif |
817 | ||
818 | NSDate *beginTime=[NSDate date]; | |
819 | ||
820 | /*Skip drawing during live resize if redraw is too slow.*/ | |
821 | if([self inLiveResize] && drawTime>MAX_DYNAMIC_TIME) return; | |
802 | 822 | |
803 | 823 | CGFloat height = [self bounds].size.height; |
804 | 824 | HIMutableShapeRef drawShape = HIShapeCreateMutable(); |
819 | 839 | nil]]; |
820 | 840 | } |
821 | 841 | CFRelease(drawShape); |
822 | } | |
842 | drawTime=-[beginTime timeIntervalSinceNow]; | |
843 | } | |
844 | ||
845 | /*At conclusion of resize event, send notification and set view for redraw if earlier drawing was skipped because of lagginess.*/ | |
846 | - (void)viewDidEndLiveResize | |
847 | { | |
848 | if(drawTime>MAX_DYNAMIC_TIME) { | |
849 | [self setNeedsDisplay:YES]; | |
850 | [super viewDidEndLiveResize]; | |
851 | } | |
852 | } | |
853 | ||
854 | -(void) viewWillDraw { | |
855 | [self setNeedsDisplay:YES]; | |
856 | } | |
823 | 857 | |
824 | 858 | - (void) generateExposeEvents: (HIMutableShapeRef) shape |
825 | 859 | { |
860 | ||
826 | 861 | TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); |
827 | 862 | unsigned long serial; |
828 | 863 | CGRect updateBounds; |
829 | 864 | |
830 | 865 | if (!winPtr) { |
831 | return; | |
832 | } | |
866 | return; | |
867 | } | |
868 | ||
833 | 869 | HIShapeGetBounds(shape, &updateBounds); |
834 | 870 | serial = LastKnownRequestProcessed(Tk_Display(winPtr)); |
835 | 871 | if (GenerateUpdates(shape, &updateBounds, winPtr) && |
836 | ![[NSRunLoop currentRunLoop] currentMode] && | |
837 | Tcl_GetServiceMode() != TCL_SERVICE_NONE) { | |
838 | /* | |
839 | * Ensure there are no pending idle-time redraws that could prevent the | |
840 | * just posted Expose events from generating new redraws. | |
841 | */ | |
842 | ||
843 | while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {} | |
844 | ||
845 | /* | |
846 | * For smoother drawing, process Expose events and resulting redraws | |
847 | * immediately instead of at idle time. | |
848 | */ | |
849 | ||
850 | ClientData oldArg; | |
851 | Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc, | |
852 | UINT2PTR(serial), &oldArg); | |
853 | ||
854 | while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {} | |
855 | Tk_RestrictEvents(oldProc, oldArg, &oldArg); | |
856 | while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {} | |
857 | } | |
858 | } | |
859 | ||
872 | ![[NSRunLoop currentRunLoop] currentMode] && | |
873 | Tcl_GetServiceMode() != TCL_SERVICE_NONE) { | |
874 | /* | |
875 | * Ensure there are no pending idle-time redraws that could prevent the | |
876 | * just posted Expose events from generating new redraws. | |
877 | */ | |
878 | ||
879 | while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {} | |
880 | ||
881 | /* | |
882 | * For smoother drawing, process Expose events and resulting redraws | |
883 | * immediately instead of at idle time. | |
884 | */ | |
885 | ||
886 | ClientData oldArg; | |
887 | Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc, | |
888 | UINT2PTR(serial), &oldArg); | |
889 | ||
890 | while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {} | |
891 | ||
892 | Tk_RestrictEvents(oldProc, oldArg, &oldArg); | |
893 | while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {} | |
894 | ||
895 | } | |
896 | ||
897 | } | |
898 | ||
899 | /*This is no-op on 10.7 and up because Apple has removed this widget, but leaving here for backwards compatibility.*/ | |
860 | 900 | - (void) tkToolbarButton: (id) sender |
861 | 901 | { |
862 | 902 | #ifdef TK_MAC_DEBUG_EVENTS |
884 | 924 | Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); |
885 | 925 | } |
886 | 926 | |
887 | #ifdef TK_MAC_DEBUG_DRAWING | |
888 | 927 | - (void) setFrameSize: (NSSize) newSize |
889 | 928 | { |
890 | TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, | |
891 | NSStringFromSize(newSize)); | |
892 | 929 | [super setFrameSize:newSize]; |
893 | 930 | } |
894 | 931 | |
895 | 932 | - (void) setNeedsDisplayInRect: (NSRect) invalidRect |
896 | 933 | { |
897 | TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, | |
898 | NSStringFromRect(invalidRect)); | |
899 | 934 | [super setNeedsDisplayInRect:invalidRect]; |
900 | 935 | } |
901 | #endif | |
902 | 936 | |
903 | 937 | - (BOOL) isOpaque |
904 | 938 | { |
293 | 293 | * TP30000359-TPXREF116> |
294 | 294 | */ |
295 | 295 | |
296 | static const int TAB_HEIGHT = 10; | |
297 | static const int TAB_OVERLAP = 10; | |
296 | ||
297 | int TAB_HEIGHT = 0; | |
298 | int TAB_OVERLAP = 0; | |
298 | 299 | |
299 | 300 | static void TabElementSize( |
300 | 301 | void *clientData, void *elementRecord, Tk_Window tkwin, |
301 | 302 | int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) |
302 | 303 | { |
303 | *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1; | |
304 | TAB_HEIGHT = 10; | |
305 | TAB_OVERLAP = 10; | |
306 | /*Different metrics on 10.10/Yosemite.*/ | |
307 | if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) { | |
308 | TAB_OVERLAP = 5; | |
309 | } | |
310 | *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1; | |
311 | ||
304 | 312 | } |
305 | 313 | |
306 | 314 | static void TabElementDraw( |
872 | 872 | .c find enclosed 99 99 [expr $x2 + 1] [expr $y2 + 1] |
873 | 873 | } -cleanup { |
874 | 874 | destroy .c |
875 | unset -nocomplain bbox x2 y2 | |
875 | 876 | } -result 1 |
876 | 877 | |
877 | 878 | test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup { |
11 | 11 | tcltest::loadTestedCommands |
12 | 12 | |
13 | 13 | |
14 | catch {eval font delete [font names]} | |
14 | set defaultfontlist [font names] | |
15 | ||
16 | proc getnondefaultfonts {} { | |
17 | global defaultfontlist | |
18 | set nondeffonts [list ] | |
19 | foreach afont [font names] { | |
20 | if {$afont ni $defaultfontlist} { | |
21 | lappend nondeffonts $afont | |
22 | } | |
23 | } | |
24 | set nondeffonts | |
25 | } | |
26 | ||
27 | proc clearnondefaultfonts {} { | |
28 | foreach afont [getnondefaultfonts] { | |
29 | font delete $afont | |
30 | } | |
31 | } | |
32 | ||
15 | 33 | deleteWindows |
16 | 34 | # Toplevel used (in some tests) of the whole file |
17 | 35 | toplevel .t |
160 | 178 | font delete xyz |
161 | 179 | } -result xyz |
162 | 180 | test font-5.5 {font command: configure: get one option} -setup { |
163 | catch {eval font delete [font names]} | |
181 | clearnondefaultfonts | |
164 | 182 | } -body { |
165 | 183 | # (objc == 4) so objPtr = objv[3] |
166 | 184 | font create xyz -family xyz |
167 | 185 | font configure xyz -family |
168 | font names | |
186 | getnondefaultfonts | |
169 | 187 | } -cleanup { |
170 | 188 | font delete xyz |
171 | 189 | } -result xyz |
191 | 209 | |
192 | 210 | |
193 | 211 | test font-6.1 {font command: create: make up name} -setup { |
194 | catch {eval font delete [font names]} | |
212 | clearnondefaultfonts | |
195 | 213 | } -body { |
196 | 214 | # (objc < 3) so name = NULL |
197 | 215 | font create |
198 | font names | |
216 | getnondefaultfonts | |
199 | 217 | } -cleanup { |
200 | 218 | font delete font1 |
201 | 219 | } -result {font1} |
202 | 220 | test font-6.2 {font command: create: name specified} -setup { |
203 | catch {eval font delete [font names]} | |
221 | clearnondefaultfonts | |
204 | 222 | } -body { |
205 | 223 | # not (objc < 3) |
206 | 224 | font create xyz |
207 | font names | |
225 | getnondefaultfonts | |
208 | 226 | } -cleanup { |
209 | 227 | font delete xyz |
210 | 228 | } -result {xyz} |
211 | 229 | test font-6.3 {font command: create: name not really specified} -setup { |
212 | catch {eval font delete [font names]} | |
230 | clearnondefaultfonts | |
213 | 231 | } -body { |
214 | 232 | # (name[0] == '-') so name = NULL |
215 | 233 | font create -family xyz |
216 | font names | |
234 | getnondefaultfonts | |
217 | 235 | } -cleanup { |
218 | 236 | font delete font1 |
219 | 237 | } -result {font1} |
220 | 238 | test font-6.4 {font command: create: generate name} -setup { |
221 | catch {eval font delete [font names]} | |
222 | 239 | } -body { |
223 | 240 | # (name == NULL) |
224 | 241 | font create -family one |
228 | 245 | font create -family four |
229 | 246 | font configure font2 -family |
230 | 247 | } -cleanup { |
231 | catch {eval font delete [font names]} | |
248 | font delete font1 font2 font3 | |
232 | 249 | } -result {four} |
233 | 250 | test font-6.5 {font command: create: bad option creating new font} -setup { |
234 | 251 | catch {font delete xyz} |
237 | 254 | font create xyz -xyz times |
238 | 255 | } -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike} |
239 | 256 | test font-6.6 {font command: create: bad option creating new font} -setup { |
240 | catch {eval font delete [font names]} | |
257 | clearnondefaultfonts | |
241 | 258 | } -body { |
242 | 259 | # name was not specified so skip = 2 |
243 | 260 | font create -xyz times |
257 | 274 | font delete |
258 | 275 | } -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"} |
259 | 276 | test font-7.2 {font command: delete: loop test} -setup { |
260 | catch {eval font delete [font names]} | |
277 | clearnondefaultfonts | |
261 | 278 | set x {} |
262 | 279 | } -body { |
263 | 280 | # for (i = 2; i < objc; i++) |
266 | 283 | font create c -underline 1 |
267 | 284 | font create d -underline 1 |
268 | 285 | font create e -underline 1 |
269 | lappend x [lsort [font names]] | |
286 | lappend x [lsort [getnondefaultfonts]] | |
270 | 287 | font delete a e c b |
271 | lappend x [lsort [font names]] | |
272 | } -cleanup { | |
273 | catch {eval font delete [font names]} | |
288 | lappend x [lsort [getnondefaultfonts]] | |
289 | } -cleanup { | |
290 | getnondefaultfonts | |
274 | 291 | } -result {{a b c d e} d} |
275 | 292 | test font-7.3 {font command: delete: loop test} -setup { |
276 | catch {eval font delete [font names]} | |
293 | clearnondefaultfonts | |
277 | 294 | set x {} |
278 | 295 | } -body { |
279 | 296 | # (namedHashPtr == NULL) in middle of loop |
282 | 299 | font create c -underline 1 |
283 | 300 | font create d -underline 1 |
284 | 301 | font create e -underline 1 |
285 | lappend x [lsort [font names]] | |
302 | lappend x [lsort [getnondefaultfonts]] | |
286 | 303 | catch {font delete a d q c e b} |
287 | lappend x [lsort [font names]] | |
288 | } -cleanup { | |
289 | catch {eval font delete [font names]} | |
304 | lappend x [lsort [getnondefaultfonts]] | |
305 | } -cleanup { | |
306 | clearnondefaultfonts | |
290 | 307 | } -result {{a b c d e} {b c e}} |
291 | 308 | test font-7.4 {font command: delete: non-existent} -setup { |
292 | 309 | catch {font delete xyz} |
433 | 450 | font names xyz |
434 | 451 | } -returnCodes error -result {wrong # args: should be "font names"} |
435 | 452 | test font-11.2 {font command: names: loop test: no passes} -setup { |
436 | catch {eval font delete [font names]} | |
437 | } -body { | |
438 | font names | |
453 | clearnondefaultfonts | |
454 | } -body { | |
455 | getnondefaultfonts | |
439 | 456 | } -result {} |
440 | 457 | test font-11.3 {font command: names: loop test: one pass} -setup { |
441 | catch {eval font delete [font names]} | |
458 | clearnondefaultfonts | |
442 | 459 | } -body { |
443 | 460 | font create |
444 | font names | |
461 | getnondefaultfonts | |
445 | 462 | } -result {font1} |
446 | 463 | test font-11.4 {font command: names: loop test: multiple passes} -setup { |
447 | catch {eval font delete [font names]} | |
464 | clearnondefaultfonts | |
448 | 465 | } -body { |
449 | 466 | font create xyz |
450 | 467 | font create abc |
451 | 468 | font create def |
452 | lsort [font names] | |
453 | } -cleanup { | |
454 | catch {eval font delete [font names]} | |
469 | lsort [getnondefaultfonts] | |
470 | } -cleanup { | |
471 | clearnondefaultfonts | |
455 | 472 | } -result {abc def xyz} |
456 | 473 | test font-11.5 {font command: names: skip deletePending fonts} -setup { |
457 | 474 | destroy .t.f |
458 | catch {eval font delete [font names]} | |
475 | clearnondefaultfonts | |
459 | 476 | pack [label .t.f] |
460 | 477 | update |
461 | 478 | set x {} |
463 | 480 | # (nfPtr->deletePending == 0) |
464 | 481 | font create xyz |
465 | 482 | font create abc |
466 | lappend x [lsort [font names]] | |
483 | lappend x [lsort [getnondefaultfonts]] | |
467 | 484 | .t.f config -font xyz |
468 | 485 | font delete xyz |
469 | lappend x [font names] | |
470 | } -cleanup { | |
471 | catch {eval font delete [font names]} | |
486 | lappend x [getnondefaultfonts] | |
487 | } -cleanup { | |
488 | clearnondefaultfonts | |
472 | 489 | } -result {{abc xyz} abc} |
473 | 490 | |
474 | 491 | |
508 | 525 | set x {} |
509 | 526 | } -body { |
510 | 527 | # not (new == 0) |
511 | lappend x [font names] | |
528 | lappend x [getnondefaultfonts] | |
512 | 529 | font create xyz |
513 | lappend x [font names] | |
530 | lappend x [getnondefaultfonts] | |
514 | 531 | } -cleanup { |
515 | 532 | font delete xyz |
516 | 533 | } -result {{} xyz} |
645 | 662 | win |
646 | 663 | } -setup { |
647 | 664 | destroy .t.f |
648 | catch {eval font delete [font names]} | |
665 | clearnondefaultfonts | |
649 | 666 | pack [label .t.f] |
650 | 667 | update |
651 | 668 | } -body { |
751 | 768 | } -result {-family fixed} |
752 | 769 | test font-17.4 {Tk_FreeFont procedure: named font} -setup { |
753 | 770 | destroy .t.f |
754 | catch {eval font delete [font names]} | |
771 | clearnondefaultfonts | |
755 | 772 | pack [label .t.f] |
756 | 773 | update |
757 | 774 | } -body { |
759 | 776 | font create xyz |
760 | 777 | .t.f config -font xyz |
761 | 778 | destroy .t.f |
762 | font names | |
779 | getnondefaultfonts | |
763 | 780 | } -result {xyz} |
764 | 781 | test font-17.5 {Tk_FreeFont procedure: named font} -setup { |
765 | 782 | destroy .t.f |
687 | 687 | .s set 1001.23456789 |
688 | 688 | .s get |
689 | 689 | } -result {1001.235} |
690 | test scale-6.21 {ComputeFormat procedure} -body { | |
691 | .s configure -length 200 -from 1000 -to 1001.8 -resolution 0 -digits 200 | |
692 | .s set 1001.23456789 | |
693 | .s get | |
694 | } -result {1001.235} | |
690 | 695 | destroy .s |
691 | 696 | |
692 | 697 | |
1356 | 1361 | } -result {0 {}} |
1357 | 1362 | |
1358 | 1363 | |
1364 | test scale-19 {Bug [3529885fff] - Click in through goes in wrong direction} \ | |
1365 | -setup { | |
1366 | catch {destroy .s} | |
1367 | catch {destroy .s1 .s2 .s3 .s4} | |
1368 | unset -nocomplain x1 x2 x3 x4 x y | |
1369 | scale .s1 -from 0 -to 100 -resolution 1 -variable x1 -digits 4 -orient horizontal -length 100 | |
1370 | scale .s2 -from 0 -to 100 -resolution -1 -variable x2 -digits 4 -orient horizontal -length 100 | |
1371 | scale .s3 -from 100 -to 0 -resolution 1 -variable x3 -digits 4 -orient horizontal -length 100 | |
1372 | scale .s4 -from 100 -to 0 -resolution -1 -variable x4 -digits 4 -orient horizontal -length 100 | |
1373 | pack .s1 .s2 .s3 .s4 -side left | |
1374 | update | |
1375 | } \ | |
1376 | -body { | |
1377 | foreach {x y} [.s1 coord 50] {} | |
1378 | event generate .s1 <1> -x $x -y $y | |
1379 | event generate .s1 <ButtonRelease-1> -x $x -y $y | |
1380 | foreach {x y} [.s2 coord 50] {} | |
1381 | event generate .s2 <1> -x $x -y $y | |
1382 | event generate .s2 <ButtonRelease-1> -x $x -y $y | |
1383 | foreach {x y} [.s3 coord 50] {} | |
1384 | event generate .s3 <1> -x $x -y $y | |
1385 | event generate .s3 <ButtonRelease-1> -x $x -y $y | |
1386 | foreach {x y} [.s4 coord 50] {} | |
1387 | event generate .s4 <1> -x $x -y $y | |
1388 | event generate .s4 <ButtonRelease-1> -x $x -y $y | |
1389 | update | |
1390 | list $x1 $x2 $x3 $x4 | |
1391 | } \ | |
1392 | -cleanup { | |
1393 | unset x1 x2 x3 x4 x y | |
1394 | destroy .s1 .s2 .s3 .s4 | |
1395 | } \ | |
1396 | -result {1.0 1.0 1.0 1.0} | |
1397 | ||
1359 | 1398 | option clear |
1360 | 1399 | |
1361 | 1400 | # cleanup |
26 | 26 | |
27 | 27 | # Create entries in the option database to be sure that geometry options |
28 | 28 | # like border width have predictable values. |
29 | ||
30 | option add *Text.borderWidth 2 | |
31 | option add *Text.highlightThickness 2 | |
29 | set twbw 2 | |
30 | set twht 2 | |
31 | option add *Text.borderWidth $twbw | |
32 | option add *Text.highlightThickness $twht | |
32 | 33 | |
33 | 34 | # The frame .f is needed to make sure that the overall window is always |
34 | 35 | # fairly wide, even if the text window is very narrow. This is needed |
3365 | 3366 | .t2.t window create 1.1 -window .t2.t.f |
3366 | 3367 | update |
3367 | 3368 | list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3] |
3368 | } [list [list 0.0 [expr {14.0/30}]] 300x50+5+[expr {$fixedDiff + 18}] [list 12 [expr {$fixedDiff + 68}] 7 $fixedHeight]] | |
3369 | } [list [list 0.0 [expr {20.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1}]+[expr {$twbw + $twht + $fixedHeight + 1}] [list [expr {$twbw + $twht + $fixedWidth + 1}] [expr {$twbw + $twht + $fixedHeight + 50 + 1}] $fixedWidth $fixedHeight]] | |
3369 | 3370 | test textDisp-29.2 {miscellaneous: lines wrap but are still too long} {textfonts} { |
3370 | 3371 | catch {destroy .t2} |
3371 | 3372 | toplevel .t2 |
3378 | 3379 | .t2.t insert end 123 |
3379 | 3380 | frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised |
3380 | 3381 | .t2.t window create 1.1 -window .t2.t.f |
3382 | update | |
3381 | 3383 | .t2.t xview scroll 1 unit |
3382 | 3384 | update |
3383 | 3385 | list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3] |
3384 | } [list [list [expr {7.0/300}] 0.49] 300x50+-2+[expr {$fixedDiff + 18}] [list 5 [expr {$fixedDiff + 68}] 7 $fixedHeight]] | |
3386 | } [list [list [expr {1.0*$fixedWidth/300}] [expr {21.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1 - $fixedWidth}]+[expr {$twbw + $twht + $fixedHeight + 1}] [list [expr {$twbw + $twht + $fixedWidth + 1 - $fixedWidth}] [expr {$twbw + $twht + $fixedHeight + 50 + 1}] $fixedWidth $fixedHeight]] | |
3385 | 3387 | test textDisp-29.2.1 {miscellaneous: lines wrap but are still too long} {textfonts} { |
3386 | 3388 | catch {destroy .t2} |
3387 | 3389 | toplevel .t2 |
3393 | 3395 | pack .t2.s -side bottom -fill x |
3394 | 3396 | .t2.t insert end 1\n |
3395 | 3397 | .t2.t insert end [string repeat "abc" 30] |
3398 | update | |
3396 | 3399 | .t2.t xview scroll 5 unit |
3397 | 3400 | update |
3398 | 3401 | .t2.t xview |
3409 | 3412 | .t2.t insert end 123 |
3410 | 3413 | frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised |
3411 | 3414 | .t2.t window create 1.1 -window .t2.t.f |
3415 | update | |
3412 | 3416 | .t2.t xview scroll 2 unit |
3413 | 3417 | update |
3414 | 3418 | list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3] |
3415 | } [list [list [expr {14.0/300}] [expr {154.0/300}]] 300x50+-9+[expr {$fixedDiff + 18}] {}] | |
3419 | } [list [list [expr {2.0*$fixedWidth/300}] [expr {22.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1 - 2*$fixedWidth}]+[expr {$twbw + $twht + $fixedHeight + 1}] {}] | |
3416 | 3420 | test textDisp-29.2.3 {miscellaneous: lines wrap but are still too long} {textfonts} { |
3417 | 3421 | catch {destroy .t2} |
3418 | 3422 | toplevel .t2 |
3425 | 3429 | .t2.t insert end 123 |
3426 | 3430 | frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised |
3427 | 3431 | .t2.t window create 1.1 -window .t2.t.f |
3432 | update | |
3428 | 3433 | .t2.t xview scroll 7 pixels |
3429 | 3434 | update |
3430 | 3435 | list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3] |
3431 | } [list [list [expr {7.0/300}] 0.49] 300x50+-2+[expr {$fixedDiff + 18}] [list 5 [expr {$fixedDiff + 68}] 7 $fixedHeight]] | |
3436 | } [list [list [expr {7.0/300}] [expr {(20.0*$fixedWidth + 7)/300}]] 300x50+[expr {$twbw + $twht + 1 - 7}]+[expr {$twbw + $twht + $fixedHeight + 1}] [list [expr {$twbw + $twht + $fixedWidth + 1 - 7}] [expr {$twbw + $twht + $fixedHeight + 50 + 1}] $fixedWidth $fixedHeight]] | |
3432 | 3437 | test textDisp-29.2.4 {miscellaneous: lines wrap but are still too long} {textfonts} { |
3433 | 3438 | catch {destroy .t2} |
3434 | 3439 | toplevel .t2 |
3441 | 3446 | .t2.t insert end 123 |
3442 | 3447 | frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised |
3443 | 3448 | .t2.t window create 1.1 -window .t2.t.f |
3449 | update | |
3444 | 3450 | .t2.t xview scroll 17 pixels |
3445 | 3451 | update |
3446 | 3452 | list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3] |
3447 | } [list [list [expr {17.0/300}] [expr {157.0/300}]] 300x50+-12+[expr {$fixedDiff + 18}] {}] | |
3453 | } [list [list [expr {17.0/300}] [expr {(20.0*$fixedWidth + 17)/300}]] 300x50+[expr {$twbw + $twht + 1 - 17}]+[expr {$twbw + $twht + $fixedHeight + 1}] {}] | |
3448 | 3454 | test textDisp-29.2.5 {miscellaneous: can show last character} { |
3449 | 3455 | catch {destroy .t2} |
3450 | 3456 | toplevel .t2 |
21 | 21 | && (([testwinlocale] & 0xff) == 9) |
22 | 22 | }] |
23 | 23 | |
24 | proc vista? {{prevista 0} {postvista 1}} { | |
25 | lassign [split $::tcl_platform(osVersion) .] major | |
26 | return [expr {$major >= 6 ? $postvista : $prevista}] | |
27 | } | |
28 | ||
29 | # What directory to use in initialdir tests. Old code used to use | |
30 | # c:/. However, on Vista/later that is a protected directory if you | |
31 | # are not running privileged. Moreover, not everyone has a drive c: | |
32 | # but not having a TEMP would break a lot Windows programs | |
33 | proc initialdir {} { | |
34 | # file join to return in Tcl canonical format (/ separator, not \) | |
35 | #return [file join $::env(TEMP)] | |
36 | return [tcltest::temporaryDirectory] | |
37 | } | |
38 | ||
39 | ||
24 | 40 | proc start {arg} { |
25 | 41 | set ::tk_dialog 0 |
26 | 42 | set ::iter_after 0 |
43 | set ::dialogclass "#32770" | |
27 | 44 | |
28 | 45 | after 1 $arg |
29 | 46 | } |
33 | 50 | set ::dialogresult {} |
34 | 51 | set ::testfont {} |
35 | 52 | |
36 | afterbody | |
53 | # Do not make the delay too short. The newer Vista dialogs take | |
54 | # time to come up. Even if the testforwindow returns true, the | |
55 | # controls are not ready to accept messages | |
56 | after 500 afterbody | |
37 | 57 | vwait ::dialogresult |
38 | 58 | return $::dialogresult |
39 | 59 | } |
40 | 60 | |
41 | 61 | proc afterbody {} { |
42 | if {$::tk_dialog == 0} { | |
43 | if {[incr ::iter_after] > 30} { | |
44 | set ::dialogresult ">30 iterations waiting on tk_dialog" | |
62 | # On Vista and later, using the new file dialogs we have to find | |
63 | # the window using its title as tk_dialog will not be set at the C level | |
64 | if {[vista?]} { | |
65 | if {[catch {testfindwindow "" $::dialogclass} ::tk_dialog]} { | |
66 | if {[incr ::iter_after] > 30} { | |
67 | set ::dialogresult ">30 iterations waiting on tk_dialog" | |
68 | return | |
69 | } | |
70 | after 150 {afterbody} | |
45 | 71 | return |
46 | 72 | } |
47 | after 150 {afterbody} | |
48 | return | |
73 | } else { | |
74 | if {$::tk_dialog == 0} { | |
75 | if {[incr ::iter_after] > 30} { | |
76 | set ::dialogresult ">30 iterations waiting on tk_dialog" | |
77 | return | |
78 | } | |
79 | after 150 {afterbody} | |
80 | return | |
81 | } | |
49 | 82 | } |
50 | 83 | uplevel #0 {set dialogresult [eval $command]} |
51 | 84 | } |
204 | 237 | test winDialog-5.3 {GetFileName: many arguments} -constraints { |
205 | 238 | nt testwinevent |
206 | 239 | } -body { |
207 | start {tk_getOpenFile -initialdir c:/ -parent . -title test -initialfile foo} | |
240 | start {tk_getOpenFile -initialdir [initialdir] -parent . -title test -initialfile foo} | |
208 | 241 | then { |
209 | 242 | Click cancel |
210 | 243 | } |
230 | 263 | test winDialog-5.7 {GetFileName: extension begins with .} -constraints { |
231 | 264 | nt testwinevent |
232 | 265 | } -body { |
233 | # if (string[0] == '.') { | |
234 | # string++; | |
235 | # } | |
236 | ||
237 | 266 | start {set x [tk_getSaveFile -defaultextension .foo -title Save]} |
238 | 267 | set msg {} |
239 | 268 | then { |
240 | if {[catch {SetText 0x47C bar} msg]} { | |
269 | if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} { | |
241 | 270 | Click cancel |
242 | 271 | } else { |
243 | 272 | Click ok |
244 | 273 | } |
245 | 274 | } |
246 | string totitle $x$msg | |
275 | set x "[file tail $x]$msg" | |
247 | 276 | } -cleanup { |
248 | 277 | unset msg |
249 | } -result [string totitle [file join [pwd] bar.foo]] | |
278 | } -result bar.foo | |
250 | 279 | test winDialog-5.8 {GetFileName: extension doesn't begin with .} -constraints { |
251 | 280 | nt testwinevent |
252 | 281 | } -body { |
253 | 282 | start {set x [tk_getSaveFile -defaultextension foo -title Save]} |
254 | 283 | set msg {} |
255 | 284 | then { |
256 | if {[catch {SetText 0x47C bar} msg]} { | |
285 | if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} { | |
257 | 286 | Click cancel |
258 | 287 | } else { |
259 | 288 | Click ok |
260 | 289 | } |
261 | 290 | } |
262 | string totitle $x$msg | |
291 | set x "[file tail $x]$msg" | |
263 | 292 | } -cleanup { |
264 | 293 | unset msg |
265 | } -result [string totitle [file join [pwd] bar.foo]] | |
294 | } -result bar.foo | |
266 | 295 | test winDialog-5.9 {GetFileName: file types} -constraints { |
267 | 296 | nt testwinevent |
268 | 297 | } -body { |
269 | # case FILE_TYPES: | |
270 | ||
298 | # case FILE_TYPES: | |
299 | ||
271 | 300 | start {tk_getSaveFile -filetypes {{"foo files" .foo FOOF}} -title Foo} |
272 | then { | |
273 | set x [GetText 0x470] | |
274 | Click cancel | |
275 | } | |
276 | return $x | |
277 | } -result {foo files (*.foo)} | |
301 | # XXX - currently disabled for vista style dialogs because the file | |
302 | # types control has no control ID and we don't have a mechanism to | |
303 | # locate it. | |
304 | if {[vista?]} { | |
305 | then { | |
306 | Click cancel | |
307 | } | |
308 | return 1 | |
309 | } else { | |
310 | then { | |
311 | set x [GetText 0x470] | |
312 | Click cancel | |
313 | } | |
314 | return [string equal $x {foo files (*.foo)}] | |
315 | } | |
316 | } -result 1 | |
278 | 317 | test winDialog-5.10 {GetFileName: file types: MakeFilter() fails} -constraints { |
279 | 318 | nt |
280 | 319 | } -body { |
282 | 321 | |
283 | 322 | tk_getSaveFile -filetypes {{"foo" .foo FOO}} |
284 | 323 | } -returnCodes error -result {bad Macintosh file type "FOO"} |
285 | if {[info exists ::env(TEMP)]} { | |
286 | 324 | test winDialog-5.11 {GetFileName: initial directory} -constraints { |
287 | 325 | nt testwinevent |
288 | 326 | } -body { |
289 | 327 | # case FILE_INITDIR: |
290 | ||
328 | unset -nocomplain x | |
291 | 329 | start {set x [tk_getSaveFile \ |
292 | -initialdir [file normalize $::env(TEMP)] \ | |
330 | -initialdir [initialdir] \ | |
293 | 331 | -initialfile "12x 455" -title Foo]} |
294 | 332 | then { |
295 | 333 | Click ok |
296 | 334 | } |
297 | 335 | return $x |
298 | } -result [file join [file normalize $::env(TEMP)] "12x 455"] | |
299 | } | |
336 | } -result [file join [initialdir] "12x 455"] | |
300 | 337 | test winDialog-5.12 {GetFileName: initial directory: Tcl_TranslateFilename()} -constraints { |
301 | 338 | nt |
302 | 339 | } -body { |
313 | 350 | then { |
314 | 351 | Click ok |
315 | 352 | } |
316 | string totitle $x | |
317 | } -result [string totitle [file join [pwd] "12x 456"]] | |
353 | file tail $x | |
354 | } -result "12x 456" | |
318 | 355 | test winDialog-5.14 {GetFileName: initial file: Tcl_TranslateFileName()} -constraints { |
319 | 356 | nt |
320 | 357 | } -body { |
321 | 358 | # if (Tcl_TranslateFileName(interp, string, &ds) == NULL) |
322 | 359 | tk_getOpenFile -initialfile ~12x/455 |
323 | 360 | } -returnCodes error -result {user "12x" doesn't exist} |
324 | test winDialog-5.15 {GetFileName: initial file: long name} -constraints { | |
325 | nt testwinevent | |
326 | } -body { | |
327 | start { | |
328 | set dialogresult [catch { | |
329 | tk_getSaveFile -initialfile [string repeat a 1024] -title Long | |
330 | } x] | |
331 | } | |
332 | then { | |
333 | Click ok | |
334 | } | |
335 | list $dialogresult [string match "invalid filename *" $x] | |
336 | } -result {1 1} | |
361 | if {![vista?]} { | |
362 | # XXX - disabled for Vista because the new dialogs allow long file | |
363 | # names to be specified but force the user to change it. | |
364 | test winDialog-5.15 {GetFileName: initial file: long name} -constraints { | |
365 | nt testwinevent | |
366 | } -body { | |
367 | start { | |
368 | set dialogresult [catch { | |
369 | tk_getSaveFile -initialfile [string repeat a 1024] -title Long | |
370 | } x] | |
371 | } | |
372 | then { | |
373 | Click ok | |
374 | } | |
375 | list $dialogresult [string match "invalid filename *" $x] | |
376 | } -result {1 1} | |
377 | } | |
337 | 378 | test winDialog-5.16 {GetFileName: parent} -constraints { |
338 | 379 | nt |
339 | 380 | } -body { |
357 | 398 | Click cancel |
358 | 399 | } |
359 | 400 | } -result {0} |
360 | test winDialog-5.18 {GetFileName: no filter specified} -constraints { | |
361 | nt testwinevent | |
362 | } -body { | |
363 | # if (ofn.lpstrFilter == NULL) | |
364 | ||
365 | start {tk_getOpenFile -title Filter} | |
366 | then { | |
367 | set x [GetText 0x470] | |
368 | Click cancel | |
369 | } | |
370 | return $x | |
371 | } -result {All Files (*.*)} | |
401 | if {[vista?]} { | |
402 | # In the newer file dialogs, the file type widget does not even exist | |
403 | # if no file types specified | |
404 | test winDialog-5.18 {GetFileName: no filter specified} -constraints { | |
405 | nt testwinevent | |
406 | } -body { | |
407 | # if (ofn.lpstrFilter == NULL) | |
408 | start {tk_getOpenFile -title Filter} | |
409 | then { | |
410 | catch {set x [GetText 0x470]} y | |
411 | Click cancel | |
412 | } | |
413 | return $y | |
414 | } -result {Could not find control with id 1136} | |
415 | } else { | |
416 | test winDialog-5.18 {GetFileName: no filter specified} -constraints { | |
417 | nt testwinevent | |
418 | } -body { | |
419 | # if (ofn.lpstrFilter == NULL) | |
420 | ||
421 | start {tk_getOpenFile -title Filter} | |
422 | then { | |
423 | set x [GetText 0x470] | |
424 | Click cancel | |
425 | } | |
426 | return $x | |
427 | } -result {All Files (*.*)} | |
428 | } | |
372 | 429 | test winDialog-5.19 {GetFileName: parent HWND doesn't yet exist} -constraints { |
373 | 430 | nt |
374 | 431 | } -setup { |
418 | 475 | } |
419 | 476 | return $x |
420 | 477 | } -result {&Save} |
421 | if {[info exists ::env(TEMP)]} { | |
422 | 478 | test winDialog-5.23 {GetFileName: convert \ to /} -constraints { |
423 | 479 | nt testwinevent |
424 | 480 | } -body { |
425 | 481 | set msg {} |
426 | 482 | start {set x [tk_getSaveFile -title Back]} |
427 | 483 | then { |
428 | if {[catch {SetText 0x47C [file nativename \ | |
429 | [file join [file normalize $::env(TEMP)] "12x 457"]]} msg]} { | |
484 | if {[catch {SetText [vista? 0x47C 0x3e9] [file nativename \ | |
485 | [file join [initialdir] "12x 457"]]} msg]} { | |
430 | 486 | Click cancel |
431 | 487 | } else { |
432 | 488 | Click ok |
435 | 491 | return $x$msg |
436 | 492 | } -cleanup { |
437 | 493 | unset msg |
438 | } -result [file join [file normalize $::env(TEMP)] "12x 457"] | |
439 | } | |
494 | } -result [file join [initialdir] "12x 457"] | |
440 | 495 | test winDialog-5.24 {GetFileName: file types: MakeFilter() succeeds} -constraints { |
441 | 496 | nt |
442 | 497 | } -body { |
491 | 546 | nt testwinevent |
492 | 547 | } -body { |
493 | 548 | start { |
494 | tk_chooseDirectory -initialdir c:/ -mustexist 1 -parent . -title test | |
549 | tk_chooseDirectory -initialdir [initialdir] -mustexist 1 -parent . -title test | |
495 | 550 | } |
496 | 551 | then { |
497 | 552 | Click cancel |
520 | 575 | } -body { |
521 | 576 | # case DIR_INITIAL: |
522 | 577 | |
523 | start {set x [tk_chooseDirectory -initialdir c:/ -title Foo]} | |
578 | start {set x [tk_chooseDirectory -initialdir [initialdir] -title Foo]} | |
524 | 579 | then { |
525 | 580 | Click ok |
526 | 581 | } |
527 | 582 | string tolower [set x] |
528 | } -result {c:/} | |
583 | } -result [string tolower [initialdir]] | |
529 | 584 | test winDialog-9.8 {Tk_ChooseDirectoryObjCmd: initial directory: Tcl_TranslateFilename()} -constraints { |
530 | 585 | nt |
531 | 586 | } -body { |
1337 | 1337 | TK_VERSION=8.6 |
1338 | 1338 | TK_MAJOR_VERSION=8 |
1339 | 1339 | TK_MINOR_VERSION=6 |
1340 | TK_PATCH_LEVEL=".2" | |
1340 | TK_PATCH_LEVEL=".3" | |
1341 | 1341 | VERSION=${TK_VERSION} |
1342 | 1342 | LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" |
1343 | 1343 | |
4851 | 4851 | LD_SEARCH_FLAGS="" |
4852 | 4852 | TCL_NEEDS_EXP_FILE=1 |
4853 | 4853 | TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' |
4854 | TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' | |
4855 | TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' | |
4854 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" | |
4856 | 4855 | echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5 |
4857 | 4856 | echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6 |
4858 | 4857 | if test "${ac_cv_cygwin+set}" = set; then |
5518 | 5517 | LDFLAGS="" |
5519 | 5518 | ;; |
5520 | 5519 | *) |
5521 | SHLIB_CFLAGS="-fPIC" | |
5520 | case "$arch" in | |
5521 | alpha|sparc64) | |
5522 | SHLIB_CFLAGS="-fPIC" | |
5523 | ;; | |
5524 | *) | |
5525 | SHLIB_CFLAGS="-fpic" | |
5526 | ;; | |
5527 | esac | |
5522 | 5528 | SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' |
5523 | 5529 | SHLIB_SUFFIX=".so" |
5524 | 5530 | DL_OBJS="tclLoadDl.o" |
5585 | 5591 | # This configuration from FreeBSD Ports. |
5586 | 5592 | SHLIB_CFLAGS="-fPIC" |
5587 | 5593 | SHLIB_LD="${CC} -shared" |
5588 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname=\$@" | |
5589 | TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$@" | |
5594 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@" | |
5590 | 5595 | SHLIB_SUFFIX=".so" |
5591 | 5596 | DL_OBJS="tclLoadDl.o" |
5592 | 5597 | DL_LIBS="" |
6824 | 6829 | if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then |
6825 | 6830 | |
6826 | 6831 | LIB_SUFFIX=${SHARED_LIB_SUFFIX} |
6827 | MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' | |
6832 | MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' | |
6828 | 6833 | if test "${SHLIB_SUFFIX}" = ".dll"; then |
6829 | 6834 | |
6830 | 6835 | INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' |
24 | 24 | TK_VERSION=8.6 |
25 | 25 | TK_MAJOR_VERSION=8 |
26 | 26 | TK_MINOR_VERSION=6 |
27 | TK_PATCH_LEVEL=".2" | |
27 | TK_PATCH_LEVEL=".3" | |
28 | 28 | VERSION=${TK_VERSION} |
29 | 29 | LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" |
30 | 30 |
1216 | 1216 | LD_SEARCH_FLAGS="" |
1217 | 1217 | TCL_NEEDS_EXP_FILE=1 |
1218 | 1218 | TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' |
1219 | TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$[@].a' | |
1220 | TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$[@].a' | |
1219 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a" | |
1221 | 1220 | AC_CACHE_CHECK(for Cygwin version of gcc, |
1222 | 1221 | ac_cv_cygwin, |
1223 | 1222 | AC_TRY_COMPILE([ |
1475 | 1474 | LDFLAGS="" |
1476 | 1475 | ;; |
1477 | 1476 | *) |
1478 | SHLIB_CFLAGS="-fPIC" | |
1477 | case "$arch" in | |
1478 | alpha|sparc64) | |
1479 | SHLIB_CFLAGS="-fPIC" | |
1480 | ;; | |
1481 | *) | |
1482 | SHLIB_CFLAGS="-fpic" | |
1483 | ;; | |
1484 | esac | |
1479 | 1485 | SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' |
1480 | 1486 | SHLIB_SUFFIX=".so" |
1481 | 1487 | DL_OBJS="tclLoadDl.o" |
1530 | 1536 | # This configuration from FreeBSD Ports. |
1531 | 1537 | SHLIB_CFLAGS="-fPIC" |
1532 | 1538 | SHLIB_LD="${CC} -shared" |
1533 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname=\$[@]" | |
1534 | TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]" | |
1539 | SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]" | |
1535 | 1540 | SHLIB_SUFFIX=".so" |
1536 | 1541 | DL_OBJS="tclLoadDl.o" |
1537 | 1542 | DL_LIBS="" |
2042 | 2047 | |
2043 | 2048 | AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [ |
2044 | 2049 | LIB_SUFFIX=${SHARED_LIB_SUFFIX} |
2045 | MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' | |
2050 | MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' | |
2046 | 2051 | AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [ |
2047 | 2052 | INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' |
2048 | 2053 | DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" |
3 | 3 | |
4 | 4 | Name: tk |
5 | 5 | Summary: Tk graphical toolkit for the Tcl scripting language. |
6 | Version: 8.6.2 | |
6 | Version: 8.6.3 | |
7 | 7 | Release: 2 |
8 | 8 | License: BSD |
9 | 9 | Group: Development/Languages |
261 | 261 | { |
262 | 262 | register Tk_Window tkwin = scalePtr->tkwin; |
263 | 263 | int y, width, length; |
264 | char valueString[PRINT_CHARS]; | |
264 | char valueString[TCL_DOUBLE_SPACE]; | |
265 | 265 | Tk_FontMetrics fm; |
266 | 266 | |
267 | 267 | Tk_GetFontMetrics(scalePtr->tkfont, &fm); |
340 | 340 | */ |
341 | 341 | |
342 | 342 | if (tickInterval != 0) { |
343 | char valueString[PRINT_CHARS]; | |
343 | char valueString[TCL_DOUBLE_SPACE]; | |
344 | 344 | double ticks, maxTicks; |
345 | 345 | |
346 | 346 | /* |
477 | 477 | { |
478 | 478 | register Tk_Window tkwin = scalePtr->tkwin; |
479 | 479 | int x, y, length, width; |
480 | char valueString[PRINT_CHARS]; | |
480 | char valueString[TCL_DOUBLE_SPACE]; | |
481 | 481 | Tk_FontMetrics fm; |
482 | 482 | |
483 | 483 | x = TkScaleValueToPixel(scalePtr, value); |
534 | 534 | Tcl_Interp *interp = scalePtr->interp; |
535 | 535 | Pixmap pixmap; |
536 | 536 | int result; |
537 | char string[PRINT_CHARS]; | |
537 | char string[TCL_DOUBLE_SPACE]; | |
538 | 538 | XRectangle drawnArea; |
539 | 539 | Tcl_DString buf; |
540 | 540 |
1311 | 1311 | TK_VERSION=8.6 |
1312 | 1312 | TK_MAJOR_VERSION=8 |
1313 | 1313 | TK_MINOR_VERSION=6 |
1314 | TK_PATCH_LEVEL=".2" | |
1314 | TK_PATCH_LEVEL=".3" | |
1315 | 1315 | VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION |
1316 | 1316 | |
1317 | 1317 | #------------------------------------------------------------------------ |
13 | 13 | TK_VERSION=8.6 |
14 | 14 | TK_MAJOR_VERSION=8 |
15 | 15 | TK_MINOR_VERSION=6 |
16 | TK_PATCH_LEVEL=".2" | |
16 | TK_PATCH_LEVEL=".3" | |
17 | 17 | VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION |
18 | 18 | |
19 | 19 | #------------------------------------------------------------------------ |
1264 | 1264 | return 0; |
1265 | 1265 | } |
1266 | 1266 | case BN_CLICKED: { |
1267 | int code; | |
1268 | Tcl_Interp *interp = butPtr->info.interp; | |
1269 | ||
1270 | if (butPtr->info.state != STATE_DISABLED) { | |
1271 | Tcl_Preserve((ClientData)interp); | |
1272 | code = TkInvokeButton((TkButton*)butPtr); | |
1273 | if (code != TCL_OK && code != TCL_CONTINUE | |
1274 | && code != TCL_BREAK) { | |
1275 | Tcl_AddErrorInfo(interp, "\n (button invoke)"); | |
1276 | Tcl_BackgroundException(interp, code); | |
1277 | } | |
1278 | Tcl_Release((ClientData)interp); | |
1279 | } | |
1280 | Tcl_ServiceAll(); | |
1281 | return 0; | |
1267 | /* | |
1268 | * OOPS: chromium fires WM_NULL regularly to ping if plugin is still | |
1269 | * alive. When using an external window (i.e. via the tcl plugin), this | |
1270 | * causes all buttons to fire once a second, so we need to make sure | |
1271 | * that we are not dealing with the chromium life check. | |
1272 | */ | |
1273 | if (wParam != 0 || lParam != 0) { | |
1274 | int code; | |
1275 | Tcl_Interp *interp = butPtr->info.interp; | |
1276 | ||
1277 | if (butPtr->info.state != STATE_DISABLED) { | |
1278 | Tcl_Preserve((ClientData)interp); | |
1279 | code = TkInvokeButton((TkButton*)butPtr); | |
1280 | if (code != TCL_OK && code != TCL_CONTINUE | |
1281 | && code != TCL_BREAK) { | |
1282 | Tcl_AddErrorInfo(interp, "\n (button invoke)"); | |
1283 | Tcl_BackgroundException(interp, code); | |
1284 | } | |
1285 | Tcl_Release((ClientData)interp); | |
1286 | } | |
1287 | Tcl_ServiceAll(); | |
1288 | return 0; | |
1289 | } | |
1282 | 1290 | } |
1283 | 1291 | |
1284 | 1292 | default: |
13 | 13 | #include "tkFont.h" |
14 | 14 | |
15 | 15 | #include <commdlg.h> /* includes common dialog functionality */ |
16 | #ifdef _MSC_VER | |
17 | # pragma comment (lib, "comdlg32.lib") | |
18 | #endif | |
19 | 16 | #include <dlgs.h> /* includes common dialog template defines */ |
20 | 17 | #include <cderr.h> /* includes the common dialog error codes */ |
21 | 18 | |
22 | 19 | #include <shlobj.h> /* includes SHBrowseForFolder */ |
20 | #include <shobjidl.h> | |
21 | ||
23 | 22 | #ifdef _MSC_VER |
24 | 23 | # pragma comment (lib, "shell32.lib") |
24 | # pragma comment (lib, "comdlg32.lib") | |
25 | # pragma comment (lib, "uuid.lib") | |
25 | 26 | #endif |
26 | 27 | |
27 | 28 | /* These needed for compilation with VC++ 5.2 */ |
29 | /* XXX - remove these since need at least VC 6 */ | |
28 | 30 | #ifndef BIF_EDITBOX |
29 | 31 | #define BIF_EDITBOX 0x10 |
30 | 32 | #endif |
33 | 35 | #define BIF_VALIDATE 0x0020 |
34 | 36 | #endif |
35 | 37 | |
38 | /* This "new" dialog style is now actually the "old" dialog style post-Vista */ | |
36 | 39 | #ifndef BIF_NEWDIALOGSTYLE |
37 | 40 | #define BIF_NEWDIALOGSTYLE 0x0040 |
38 | 41 | #endif |
56 | 59 | HHOOK hMsgBoxHook; /* Hook proc for tk_messageBox and the */ |
57 | 60 | HICON hSmallIcon; /* icons used by a parent to be used in */ |
58 | 61 | HICON hBigIcon; /* the message box */ |
62 | int newFileDialogsState; | |
63 | #define FDLG_STATE_INIT 0 /* Uninitialized */ | |
64 | #define FDLG_STATE_USE_NEW 1 /* Use the new dialogs */ | |
65 | #define FDLG_STATE_USE_OLD 2 /* Use the old dialogs */ | |
59 | 66 | } ThreadSpecificData; |
60 | 67 | static Tcl_ThreadDataKey dataKey; |
61 | 68 | |
158 | 165 | } OFNData; |
159 | 166 | |
160 | 167 | /* |
168 | * The following structure is used to gather options used by various | |
169 | * file dialogs | |
170 | */ | |
171 | typedef struct OFNOpts { | |
172 | Tk_Window tkwin; /* Owner window for dialog */ | |
173 | Tcl_Obj *extObj; /* Default extension */ | |
174 | Tcl_Obj *titleObj; /* Title for dialog */ | |
175 | Tcl_Obj *filterObj; /* File type filter list */ | |
176 | Tcl_Obj *typeVariableObj; /* Variable in which to store type selected */ | |
177 | Tcl_Obj *initialTypeObj; /* Initial value of above, or NULL */ | |
178 | Tcl_DString utfDirString; /* Initial dir */ | |
179 | int multi; /* Multiple selection enabled */ | |
180 | int confirmOverwrite; /* Confirm before overwriting */ | |
181 | int mustExist; /* Used only for */ | |
182 | int forceXPStyle; /* XXX - Force XP style even on newer systems */ | |
183 | TCHAR file[TK_MULTI_MAX_PATH]; /* File name | |
184 | XXX - fixed size because it was so | |
185 | historically. Why not malloc'ed ? | |
186 | XXX - also, TCHAR should really be WCHAR | |
187 | because TkWinGetUnicodeEncoding is always | |
188 | UCS2. | |
189 | */ | |
190 | } OFNOpts; | |
191 | ||
192 | /* Define the operation for which option parsing is to be done. */ | |
193 | enum OFNOper { | |
194 | OFN_FILE_SAVE, /* tk_getOpenFile */ | |
195 | OFN_FILE_OPEN, /* tk_getSaveFile */ | |
196 | OFN_DIR_CHOOSE /* tk_chooseDirectory */ | |
197 | }; | |
198 | ||
199 | ||
200 | /* | |
201 | * The following definitions are required when using older versions of | |
202 | * Visual C++ (like 6.0) and possibly MingW. Those headers do not contain | |
203 | * required definitions for interfaces new to Vista that we need for | |
204 | * the new file dialogs. Duplicating definitions is OK because they | |
205 | * should forever remain unchanged. | |
206 | * | |
207 | * XXX - is there a better/easier way to use new data definitions with | |
208 | * older compilers? Should we prefix definitions with Tcl_ instead | |
209 | * of using the same names as in the SDK? | |
210 | */ | |
211 | #ifndef __IShellItemArray_INTERFACE_DEFINED__ | |
212 | #define __IShellItemArray_INTERFACE_DEFINED__ | |
213 | ||
214 | typedef enum SIATTRIBFLAGS { | |
215 | SIATTRIBFLAGS_AND = 0x1, | |
216 | SIATTRIBFLAGS_OR = 0x2, | |
217 | SIATTRIBFLAGS_APPCOMPAT = 0x3, | |
218 | SIATTRIBFLAGS_MASK = 0x3, | |
219 | SIATTRIBFLAGS_ALLITEMS = 0x4000 | |
220 | } SIATTRIBFLAGS; | |
221 | #ifdef __MSVCRT__ | |
222 | typedef ULONG SFGAOF; | |
223 | ||
224 | typedef struct IShellItem IShellItem; | |
225 | ||
226 | typedef enum __MIDL_IShellItem_0001 { | |
227 | SIGDN_NORMALDISPLAY = 0,SIGDN_PARENTRELATIVEPARSING = 0x80018001,SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8001c001, | |
228 | SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,SIGDN_PARENTRELATIVEEDITING = 0x80031001,SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000, | |
229 | SIGDN_FILESYSPATH = 0x80058000,SIGDN_URL = 0x80068000 | |
230 | } SIGDN; | |
231 | ||
232 | typedef DWORD SICHINTF; | |
233 | ||
234 | typedef struct IShellItemVtbl | |
235 | { | |
236 | BEGIN_INTERFACE | |
237 | ||
238 | HRESULT (STDMETHODCALLTYPE *QueryInterface)(IShellItem *, REFIID, void **); | |
239 | ULONG (STDMETHODCALLTYPE *AddRef)(IShellItem *); | |
240 | ULONG (STDMETHODCALLTYPE *Release)(IShellItem *); | |
241 | HRESULT (STDMETHODCALLTYPE *BindToHandler)(IShellItem *, IBindCtx *, REFGUID, REFIID, void **); | |
242 | HRESULT (STDMETHODCALLTYPE *GetParent)(IShellItem *, IShellItem **); | |
243 | HRESULT (STDMETHODCALLTYPE *GetDisplayName)(IShellItem *, SIGDN, LPOLESTR *); | |
244 | HRESULT (STDMETHODCALLTYPE *GetAttributes)(IShellItem *, SFGAOF, SFGAOF *); | |
245 | HRESULT (STDMETHODCALLTYPE *Compare)(IShellItem *, IShellItem *, SICHINTF, int *); | |
246 | ||
247 | END_INTERFACE | |
248 | } IShellItemVtbl; | |
249 | struct IShellItem { | |
250 | CONST_VTBL struct IShellItemVtbl *lpVtbl; | |
251 | }; | |
252 | #endif /* __MSVCRT__ */ | |
253 | typedef struct IShellItemArray IShellItemArray; | |
254 | typedef struct IShellItemArrayVtbl | |
255 | { | |
256 | BEGIN_INTERFACE | |
257 | ||
258 | HRESULT ( STDMETHODCALLTYPE *QueryInterface )( | |
259 | IShellItemArray *, REFIID riid,void **ppvObject); | |
260 | ULONG ( STDMETHODCALLTYPE *AddRef )(IShellItemArray *); | |
261 | ULONG ( STDMETHODCALLTYPE *Release )(IShellItemArray *); | |
262 | HRESULT ( STDMETHODCALLTYPE *BindToHandler )(IShellItemArray *, | |
263 | IBindCtx *, REFGUID, REFIID, void **); | |
264 | /* flags is actually is enum GETPROPERTYSTOREFLAGS */ | |
265 | HRESULT ( STDMETHODCALLTYPE *GetPropertyStore )( | |
266 | IShellItemArray *, int, REFIID, void **); | |
267 | /* keyType actually REFPROPERTYKEY */ | |
268 | HRESULT ( STDMETHODCALLTYPE *GetPropertyDescriptionList )( | |
269 | IShellItemArray *, void *, REFIID, void **); | |
270 | HRESULT ( STDMETHODCALLTYPE *GetAttributes )(IShellItemArray *, | |
271 | SIATTRIBFLAGS, SFGAOF, SFGAOF *); | |
272 | HRESULT ( STDMETHODCALLTYPE *GetCount )( | |
273 | IShellItemArray *, DWORD *); | |
274 | HRESULT ( STDMETHODCALLTYPE *GetItemAt )( | |
275 | IShellItemArray *, DWORD, IShellItem **); | |
276 | /* ppenumShellItems actually (IEnumShellItems **) */ | |
277 | HRESULT ( STDMETHODCALLTYPE *EnumItems )( | |
278 | IShellItemArray *, void **); | |
279 | ||
280 | END_INTERFACE | |
281 | } IShellItemArrayVtbl; | |
282 | ||
283 | struct IShellItemArray { | |
284 | CONST_VTBL struct IShellItemArrayVtbl *lpVtbl; | |
285 | }; | |
286 | ||
287 | #endif /* __IShellItemArray_INTERFACE_DEFINED__ */ | |
288 | ||
289 | /* | |
290 | * Older compilers do not define these CLSIDs so we do so here under | |
291 | * a slightly different name so as to not clash with the definitions | |
292 | * in new compilers | |
293 | */ | |
294 | static const CLSID ClsidFileOpenDialog = { | |
295 | 0xDC1C5A9C, 0xE88A, 0X4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7} | |
296 | }; | |
297 | static const CLSID ClsidFileSaveDialog = { | |
298 | 0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B} | |
299 | }; | |
300 | static const IID IIDIFileOpenDialog = { | |
301 | 0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60} | |
302 | }; | |
303 | static const IID IIDIFileSaveDialog = { | |
304 | 0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB} | |
305 | }; | |
306 | static const IID IIDIShellItem = { | |
307 | 0x43826D1E, 0xE718, 0x42EE, {0xBC, 0x55, 0xA1, 0xE2, 0x61, 0xC3, 0x7B, 0xFE} | |
308 | }; | |
309 | ||
310 | #ifdef __IFileDialog_INTERFACE_DEFINED__ | |
311 | # define TCLCOMDLG_FILTERSPEC COMDLG_FILTERSPEC | |
312 | #else | |
313 | ||
314 | /* Forward declarations for structs that are referenced but not used */ | |
315 | typedef struct IPropertyStore IPropertyStore; | |
316 | typedef struct IPropertyDescriptionList IPropertyDescriptionList; | |
317 | typedef struct IFileOperationProgressSink IFileOperationProgressSink; | |
318 | typedef enum FDAP { | |
319 | FDAP_BOTTOM = 0, | |
320 | FDAP_TOP = 1 | |
321 | } FDAP; | |
322 | ||
323 | typedef struct { | |
324 | LPCWSTR pszName; | |
325 | LPCWSTR pszSpec; | |
326 | } TCLCOMDLG_FILTERSPEC; | |
327 | ||
328 | enum _FILEOPENDIALOGOPTIONS { | |
329 | FOS_OVERWRITEPROMPT = 0x2, | |
330 | FOS_STRICTFILETYPES = 0x4, | |
331 | FOS_NOCHANGEDIR = 0x8, | |
332 | FOS_PICKFOLDERS = 0x20, | |
333 | FOS_FORCEFILESYSTEM = 0x40, | |
334 | FOS_ALLNONSTORAGEITEMS = 0x80, | |
335 | FOS_NOVALIDATE = 0x100, | |
336 | FOS_ALLOWMULTISELECT = 0x200, | |
337 | FOS_PATHMUSTEXIST = 0x800, | |
338 | FOS_FILEMUSTEXIST = 0x1000, | |
339 | FOS_CREATEPROMPT = 0x2000, | |
340 | FOS_SHAREAWARE = 0x4000, | |
341 | FOS_NOREADONLYRETURN = 0x8000, | |
342 | FOS_NOTESTFILECREATE = 0x10000, | |
343 | FOS_HIDEMRUPLACES = 0x20000, | |
344 | FOS_HIDEPINNEDPLACES = 0x40000, | |
345 | FOS_NODEREFERENCELINKS = 0x100000, | |
346 | FOS_DONTADDTORECENT = 0x2000000, | |
347 | FOS_FORCESHOWHIDDEN = 0x10000000, | |
348 | FOS_DEFAULTNOMINIMODE = 0x20000000, | |
349 | FOS_FORCEPREVIEWPANEON = 0x40000000 | |
350 | } ; | |
351 | typedef DWORD FILEOPENDIALOGOPTIONS; | |
352 | ||
353 | typedef struct IFileDialog IFileDialog; | |
354 | typedef struct IFileDialogVtbl | |
355 | { | |
356 | BEGIN_INTERFACE | |
357 | ||
358 | HRESULT ( STDMETHODCALLTYPE *QueryInterface )( | |
359 | IFileDialog *, REFIID, void **); | |
360 | ULONG ( STDMETHODCALLTYPE *AddRef )( IFileDialog *); | |
361 | ULONG ( STDMETHODCALLTYPE *Release )( IFileDialog *); | |
362 | HRESULT ( STDMETHODCALLTYPE *Show )( IFileDialog *, HWND); | |
363 | HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileDialog *, | |
364 | UINT, const TCLCOMDLG_FILTERSPEC *); | |
365 | HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(IFileDialog *, UINT); | |
366 | HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(IFileDialog *, UINT *); | |
367 | /* XXX - Actually pfde is IFileDialogEvents* but we do not use | |
368 | this call and do not want to define IFileDialogEvents as that | |
369 | pulls in a whole bunch of other stuff. */ | |
370 | HRESULT ( STDMETHODCALLTYPE *Advise )( | |
371 | IFileDialog *, void *, DWORD *); | |
372 | HRESULT ( STDMETHODCALLTYPE *Unadvise )(IFileDialog *, DWORD); | |
373 | HRESULT ( STDMETHODCALLTYPE *SetOptions )( | |
374 | IFileDialog *, FILEOPENDIALOGOPTIONS); | |
375 | HRESULT ( STDMETHODCALLTYPE *GetOptions )( | |
376 | IFileDialog *, FILEOPENDIALOGOPTIONS *); | |
377 | HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )( | |
378 | IFileDialog *, IShellItem *); | |
379 | HRESULT ( STDMETHODCALLTYPE *SetFolder )( | |
380 | IFileDialog *, IShellItem *); | |
381 | HRESULT ( STDMETHODCALLTYPE *GetFolder )( | |
382 | IFileDialog *, IShellItem **); | |
383 | HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )( | |
384 | IFileDialog *, IShellItem **); | |
385 | HRESULT ( STDMETHODCALLTYPE *SetFileName )( | |
386 | IFileDialog *, LPCWSTR); | |
387 | HRESULT ( STDMETHODCALLTYPE *GetFileName )( | |
388 | IFileDialog *, LPWSTR *); | |
389 | HRESULT ( STDMETHODCALLTYPE *SetTitle )( | |
390 | IFileDialog *, LPCWSTR); | |
391 | HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )( | |
392 | IFileDialog *, LPCWSTR); | |
393 | HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )( | |
394 | IFileDialog *, LPCWSTR); | |
395 | HRESULT ( STDMETHODCALLTYPE *GetResult )( | |
396 | IFileDialog *, IShellItem **); | |
397 | HRESULT ( STDMETHODCALLTYPE *AddPlace )( | |
398 | IFileDialog *, IShellItem *, FDAP); | |
399 | HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )( | |
400 | IFileDialog *, LPCWSTR); | |
401 | HRESULT ( STDMETHODCALLTYPE *Close )( IFileDialog *, HRESULT); | |
402 | HRESULT ( STDMETHODCALLTYPE *SetClientGuid )( | |
403 | IFileDialog *, REFGUID); | |
404 | HRESULT ( STDMETHODCALLTYPE *ClearClientData )( IFileDialog *); | |
405 | /* pFilter actually IShellItemFilter. But deprecated in Win7 AND we do | |
406 | not use it anyways. So define as void* */ | |
407 | HRESULT ( STDMETHODCALLTYPE *SetFilter )( | |
408 | IFileDialog *, void *); | |
409 | ||
410 | END_INTERFACE | |
411 | } IFileDialogVtbl; | |
412 | ||
413 | struct IFileDialog { | |
414 | CONST_VTBL struct IFileDialogVtbl *lpVtbl; | |
415 | }; | |
416 | ||
417 | ||
418 | typedef struct IFileSaveDialog IFileSaveDialog; | |
419 | typedef struct IFileSaveDialogVtbl { | |
420 | BEGIN_INTERFACE | |
421 | ||
422 | HRESULT ( STDMETHODCALLTYPE *QueryInterface )( | |
423 | IFileSaveDialog *, REFIID, void **); | |
424 | ULONG ( STDMETHODCALLTYPE *AddRef )( IFileSaveDialog *); | |
425 | ULONG ( STDMETHODCALLTYPE *Release )( IFileSaveDialog *); | |
426 | HRESULT ( STDMETHODCALLTYPE *Show )( | |
427 | IFileSaveDialog *, HWND); | |
428 | HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileSaveDialog * this, | |
429 | UINT, const TCLCOMDLG_FILTERSPEC *); | |
430 | HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )( | |
431 | IFileSaveDialog *, UINT); | |
432 | HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )( | |
433 | IFileSaveDialog *, UINT *); | |
434 | /* Actually pfde is IFileSaveDialogEvents* */ | |
435 | HRESULT ( STDMETHODCALLTYPE *Advise )( | |
436 | IFileSaveDialog *, void *, DWORD *); | |
437 | HRESULT ( STDMETHODCALLTYPE *Unadvise )( IFileSaveDialog *, DWORD); | |
438 | HRESULT ( STDMETHODCALLTYPE *SetOptions )( | |
439 | IFileSaveDialog *, FILEOPENDIALOGOPTIONS); | |
440 | HRESULT ( STDMETHODCALLTYPE *GetOptions )( | |
441 | IFileSaveDialog *, FILEOPENDIALOGOPTIONS *); | |
442 | HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )( | |
443 | IFileSaveDialog *, IShellItem *); | |
444 | HRESULT ( STDMETHODCALLTYPE *SetFolder )( | |
445 | IFileSaveDialog *, IShellItem *); | |
446 | HRESULT ( STDMETHODCALLTYPE *GetFolder )( | |
447 | IFileSaveDialog *, IShellItem **); | |
448 | HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )( | |
449 | IFileSaveDialog *, IShellItem **); | |
450 | HRESULT ( STDMETHODCALLTYPE *SetFileName )( | |
451 | IFileSaveDialog *, LPCWSTR); | |
452 | HRESULT ( STDMETHODCALLTYPE *GetFileName )( | |
453 | IFileSaveDialog *, LPWSTR *); | |
454 | HRESULT ( STDMETHODCALLTYPE *SetTitle )( | |
455 | IFileSaveDialog *, LPCWSTR); | |
456 | HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )( | |
457 | IFileSaveDialog *, LPCWSTR); | |
458 | HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )( | |
459 | IFileSaveDialog *, LPCWSTR); | |
460 | HRESULT ( STDMETHODCALLTYPE *GetResult )( | |
461 | IFileSaveDialog *, IShellItem **); | |
462 | HRESULT ( STDMETHODCALLTYPE *AddPlace )( | |
463 | IFileSaveDialog *, IShellItem *, FDAP); | |
464 | HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )( | |
465 | IFileSaveDialog *, LPCWSTR); | |
466 | HRESULT ( STDMETHODCALLTYPE *Close )( IFileSaveDialog *, HRESULT); | |
467 | HRESULT ( STDMETHODCALLTYPE *SetClientGuid )( | |
468 | IFileSaveDialog *, REFGUID); | |
469 | HRESULT ( STDMETHODCALLTYPE *ClearClientData )( IFileSaveDialog *); | |
470 | /* pFilter Actually IShellItemFilter* */ | |
471 | HRESULT ( STDMETHODCALLTYPE *SetFilter )( | |
472 | IFileSaveDialog *, void *); | |
473 | HRESULT ( STDMETHODCALLTYPE *SetSaveAsItem )( | |
474 | IFileSaveDialog *, IShellItem *); | |
475 | HRESULT ( STDMETHODCALLTYPE *SetProperties )( | |
476 | IFileSaveDialog *, IPropertyStore *); | |
477 | HRESULT ( STDMETHODCALLTYPE *SetCollectedProperties )( | |
478 | IFileSaveDialog *, IPropertyDescriptionList *, BOOL); | |
479 | HRESULT ( STDMETHODCALLTYPE *GetProperties )( | |
480 | IFileSaveDialog *, IPropertyStore **); | |
481 | HRESULT ( STDMETHODCALLTYPE *ApplyProperties )( | |
482 | IFileSaveDialog *, IShellItem *, IPropertyStore *, | |
483 | HWND, IFileOperationProgressSink *); | |
484 | ||
485 | END_INTERFACE | |
486 | ||
487 | } IFileSaveDialogVtbl; | |
488 | ||
489 | struct IFileSaveDialog { | |
490 | CONST_VTBL struct IFileSaveDialogVtbl *lpVtbl; | |
491 | }; | |
492 | ||
493 | typedef struct IFileOpenDialog IFileOpenDialog; | |
494 | typedef struct IFileOpenDialogVtbl { | |
495 | BEGIN_INTERFACE | |
496 | ||
497 | HRESULT ( STDMETHODCALLTYPE *QueryInterface )( | |
498 | IFileOpenDialog *, REFIID, void **); | |
499 | ULONG ( STDMETHODCALLTYPE *AddRef )( IFileOpenDialog *); | |
500 | ULONG ( STDMETHODCALLTYPE *Release )( IFileOpenDialog *); | |
501 | HRESULT ( STDMETHODCALLTYPE *Show )( IFileOpenDialog *, HWND); | |
502 | HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileOpenDialog *, | |
503 | UINT, const TCLCOMDLG_FILTERSPEC *); | |
504 | HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )( | |
505 | IFileOpenDialog *, UINT); | |
506 | HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )( | |
507 | IFileOpenDialog *, UINT *); | |
508 | /* Actually pfde is IFileDialogEvents* */ | |
509 | HRESULT ( STDMETHODCALLTYPE *Advise )( | |
510 | IFileOpenDialog *, void *, DWORD *); | |
511 | HRESULT ( STDMETHODCALLTYPE *Unadvise )( IFileOpenDialog *, DWORD); | |
512 | HRESULT ( STDMETHODCALLTYPE *SetOptions )( | |
513 | IFileOpenDialog *, FILEOPENDIALOGOPTIONS); | |
514 | HRESULT ( STDMETHODCALLTYPE *GetOptions )( | |
515 | IFileOpenDialog *, FILEOPENDIALOGOPTIONS *); | |
516 | HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )( | |
517 | IFileOpenDialog *, IShellItem *); | |
518 | HRESULT ( STDMETHODCALLTYPE *SetFolder )( | |
519 | IFileOpenDialog *, IShellItem *); | |
520 | HRESULT ( STDMETHODCALLTYPE *GetFolder )( | |
521 | IFileOpenDialog *, IShellItem **); | |
522 | HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )( | |
523 | IFileOpenDialog *, IShellItem **); | |
524 | HRESULT ( STDMETHODCALLTYPE *SetFileName )( | |
525 | IFileOpenDialog *, LPCWSTR); | |
526 | HRESULT ( STDMETHODCALLTYPE *GetFileName )( | |
527 | IFileOpenDialog *, LPWSTR *); | |
528 | HRESULT ( STDMETHODCALLTYPE *SetTitle )( | |
529 | IFileOpenDialog *, LPCWSTR); | |
530 | HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )( | |
531 | IFileOpenDialog *, LPCWSTR); | |
532 | HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )( | |
533 | IFileOpenDialog *, LPCWSTR); | |
534 | HRESULT ( STDMETHODCALLTYPE *GetResult )( | |
535 | IFileOpenDialog *, IShellItem **); | |
536 | HRESULT ( STDMETHODCALLTYPE *AddPlace )( | |
537 | IFileOpenDialog *, IShellItem *, FDAP); | |
538 | HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )( | |
539 | IFileOpenDialog *, LPCWSTR); | |
540 | HRESULT ( STDMETHODCALLTYPE *Close )( IFileOpenDialog *, HRESULT); | |
541 | HRESULT ( STDMETHODCALLTYPE *SetClientGuid )( | |
542 | IFileOpenDialog *, REFGUID); | |
543 | HRESULT ( STDMETHODCALLTYPE *ClearClientData )( | |
544 | IFileOpenDialog *); | |
545 | HRESULT ( STDMETHODCALLTYPE *SetFilter )( | |
546 | IFileOpenDialog *, | |
547 | /* pFilter is actually IShellItemFilter */ | |
548 | void *); | |
549 | HRESULT ( STDMETHODCALLTYPE *GetResults )( | |
550 | IFileOpenDialog *, IShellItemArray **); | |
551 | HRESULT ( STDMETHODCALLTYPE *GetSelectedItems )( | |
552 | IFileOpenDialog *, IShellItemArray **); | |
553 | ||
554 | END_INTERFACE | |
555 | } IFileOpenDialogVtbl; | |
556 | ||
557 | struct IFileOpenDialog | |
558 | { | |
559 | CONST_VTBL struct IFileOpenDialogVtbl *lpVtbl; | |
560 | }; | |
561 | ||
562 | #endif /* __IFileDialog_INTERFACE_DEFINED__ */ | |
563 | ||
564 | /* | |
161 | 565 | * Definitions of functions used only in this file. |
162 | 566 | */ |
163 | 567 | |
165 | 569 | LPARAM wParam, LPARAM lParam); |
166 | 570 | static UINT CALLBACK ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, |
167 | 571 | LPARAM lParam); |
572 | static void CleanupOFNOptions(OFNOpts *optsPtr); | |
573 | static int ParseOFNOptions(ClientData clientData, | |
574 | Tcl_Interp *interp, int objc, | |
575 | Tcl_Obj *const objv[], enum OFNOper oper, OFNOpts *optsPtr); | |
576 | static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr, | |
577 | enum OFNOper oper); | |
578 | static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, | |
579 | enum OFNOper oper); | |
168 | 580 | static int GetFileName(ClientData clientData, |
169 | Tcl_Interp *interp, int objc, | |
170 | Tcl_Obj *const objv[], int isOpen); | |
581 | Tcl_Interp *interp, int objc, | |
582 | Tcl_Obj *const objv[], enum OFNOper oper); | |
583 | static int MakeFilterVista(Tcl_Interp *interp, OFNOpts *optsPtr, | |
584 | DWORD *countPtr, TCLCOMDLG_FILTERSPEC **dlgFilterPtrPtr, | |
585 | DWORD *defaultFilterIndexPtr); | |
586 | static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr); | |
171 | 587 | static int MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr, |
172 | 588 | Tcl_DString *dsPtr, Tcl_Obj *initialPtr, |
173 | 589 | int *indexPtr); |
177 | 593 | static void SetTkDialog(ClientData clientData); |
178 | 594 | static const char *ConvertExternalFilename(TCHAR *filename, |
179 | 595 | Tcl_DString *dsPtr); |
596 | static void LoadShellProcs(void); | |
597 | ||
598 | ||
599 | /* Definitions of dynamically loaded Win32 calls */ | |
600 | typedef HRESULT (STDAPICALLTYPE SHCreateItemFromParsingNameProc)( | |
601 | PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); | |
602 | struct ShellProcPointers { | |
603 | SHCreateItemFromParsingNameProc *SHCreateItemFromParsingName; | |
604 | } ShellProcs; | |
605 | ||
606 | ||
607 | /* | |
608 | *------------------------------------------------------------------------- | |
609 | * | |
610 | * LoadShellProcs -- | |
611 | * | |
612 | * Some shell functions are not available on older versions of | |
613 | * Windows. This function dynamically loads them and stores pointers | |
614 | * to them in ShellProcs. Any function that is not available has | |
615 | * the corresponding pointer set to NULL. | |
616 | * | |
617 | * Note this call never fails. Unavailability of a function is not | |
618 | * a reason for failure. Caller should check whether a particular | |
619 | * function pointer is NULL or not. Once loaded a function stays | |
620 | * forever loaded. | |
621 | * | |
622 | * XXX - we load the function pointers into global memory. This implies | |
623 | * there is a potential (however small) for race conditions between | |
624 | * threads. However, Tk is in any case meant to be loaded in exactly | |
625 | * one thread so this should not be an issue and saves us from | |
626 | * unnecessary bookkeeping. | |
627 | * | |
628 | * Return value: | |
629 | * None. | |
630 | * | |
631 | * Side effects: | |
632 | * ShellProcs is populated. | |
633 | *------------------------------------------------------------------------- | |
634 | */ | |
635 | static void LoadShellProcs() | |
636 | { | |
637 | static HMODULE shell32_handle = NULL; | |
638 | ||
639 | if (shell32_handle != NULL) | |
640 | return; /* We have already been through here. */ | |
641 | ||
642 | /* | |
643 | * XXX - Note we never call FreeLibrary. There is no point because | |
644 | * shell32.dll is loaded at startup anyways and stays for the duration | |
645 | * of the process so why bother with keeping track of when to unload | |
646 | */ | |
647 | shell32_handle = LoadLibrary(TEXT("shell32.dll")); | |
648 | if (shell32_handle == NULL) /* Should never happen but check anyways. */ | |
649 | return; | |
650 | ||
651 | ShellProcs.SHCreateItemFromParsingName = | |
652 | (SHCreateItemFromParsingNameProc*) GetProcAddress(shell32_handle, | |
653 | "SHCreateItemFromParsingName"); | |
654 | } | |
655 | ||
180 | 656 | |
181 | 657 | /* |
182 | 658 | *------------------------------------------------------------------------- |
486 | 962 | int objc, /* Number of arguments. */ |
487 | 963 | Tcl_Obj *const objv[]) /* Argument objects. */ |
488 | 964 | { |
489 | return GetFileName(clientData, interp, objc, objv, 1); | |
965 | return GetFileName(clientData, interp, objc, objv, OFN_FILE_OPEN); | |
490 | 966 | } |
491 | 967 | |
492 | 968 | /* |
513 | 989 | int objc, /* Number of arguments. */ |
514 | 990 | Tcl_Obj *const objv[]) /* Argument objects. */ |
515 | 991 | { |
516 | return GetFileName(clientData, interp, objc, objv, 0); | |
992 | return GetFileName(clientData, interp, objc, objv, OFN_FILE_SAVE); | |
517 | 993 | } |
518 | 994 | |
519 | 995 | /* |
520 | 996 | *---------------------------------------------------------------------- |
521 | 997 | * |
522 | * GetFileName -- | |
523 | * | |
524 | * Calls GetOpenFileName() or GetSaveFileName(). | |
998 | * CleanupOFNOptions -- | |
999 | * | |
1000 | * Cleans up any storage allocated by ParseOFNOptions | |
525 | 1001 | * |
526 | 1002 | * Results: |
527 | * See user documentation. | |
1003 | * None. | |
528 | 1004 | * |
529 | 1005 | * Side effects: |
530 | * See user documentation. | |
531 | * | |
1006 | * Releases resources held by *optsPtr | |
532 | 1007 | *---------------------------------------------------------------------- |
533 | 1008 | */ |
1009 | static void CleanupOFNOptions(OFNOpts *optsPtr) | |
1010 | { | |
1011 | Tcl_DStringFree(&optsPtr->utfDirString); | |
1012 | } | |
1013 | ||
1014 | ||
1015 | ||
1016 | /* | |
1017 | *---------------------------------------------------------------------- | |
1018 | * | |
1019 | * ParseOFNOptions -- | |
1020 | * | |
1021 | * Option parsing for tk_get{Open,Save}File | |
1022 | * | |
1023 | * Results: | |
1024 | * TCL_OK on success, TCL_ERROR otherwise | |
1025 | * | |
1026 | * Side effects: | |
1027 | * Returns option values in *optsPtr. Note these may include string | |
1028 | * pointers into objv[] | |
1029 | *---------------------------------------------------------------------- | |
1030 | */ | |
534 | 1031 | |
535 | 1032 | static int |
536 | GetFileName( | |
1033 | ParseOFNOptions( | |
537 | 1034 | ClientData clientData, /* Main window associated with interpreter. */ |
538 | 1035 | Tcl_Interp *interp, /* Current interpreter. */ |
539 | 1036 | int objc, /* Number of arguments. */ |
540 | 1037 | Tcl_Obj *const objv[], /* Argument objects. */ |
541 | int open) /* 1 to call GetOpenFileName(), 0 to call | |
542 | * GetSaveFileName(). */ | |
1038 | enum OFNOper oper, /* 1 for Open, 0 for Save */ | |
1039 | OFNOpts *optsPtr) /* Output, uninitialized on entry */ | |
543 | 1040 | { |
544 | OPENFILENAME ofn; | |
545 | TCHAR file[TK_MULTI_MAX_PATH]; | |
546 | OFNData ofnData; | |
547 | int cdlgerr; | |
548 | int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0; | |
549 | int confirmOverwrite = 1; | |
550 | const char *extension = NULL, *title = NULL; | |
551 | Tk_Window tkwin = clientData; | |
552 | HWND hWnd; | |
553 | Tcl_Obj *filterObj = NULL, *initialTypeObj = NULL, *typeVariableObj = NULL; | |
554 | Tcl_DString utfFilterString, utfDirString, ds; | |
555 | Tcl_DString extString, filterString, dirString, titleString; | |
556 | ThreadSpecificData *tsdPtr = | |
557 | Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); | |
1041 | int i; | |
1042 | Tcl_DString ds; | |
558 | 1043 | enum options { |
559 | 1044 | FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, FILE_PARENT, |
560 | FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW | |
1045 | FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW, | |
1046 | FILE_MUSTEXIST, | |
561 | 1047 | }; |
562 | 1048 | struct Options { |
563 | 1049 | const char *name; |
585 | 1071 | {"-typevariable", FILE_TYPEVARIABLE}, |
586 | 1072 | {NULL, FILE_DEFAULT/*ignored*/ } |
587 | 1073 | }; |
588 | const struct Options *const options = open ? openOptions : saveOptions; | |
589 | ||
590 | file[0] = '\0'; | |
591 | ZeroMemory(&ofnData, sizeof(OFNData)); | |
592 | Tcl_DStringInit(&utfFilterString); | |
593 | Tcl_DStringInit(&utfDirString); | |
594 | ||
595 | /* | |
596 | * Parse the arguments. | |
597 | */ | |
1074 | static const struct Options dirOptions[] = { | |
1075 | {"-initialdir", FILE_INITDIR}, | |
1076 | {"-mustexist", FILE_MUSTEXIST}, | |
1077 | {"-parent", FILE_PARENT}, | |
1078 | {"-title", FILE_TITLE}, | |
1079 | {NULL, FILE_DEFAULT/*ignored*/ } | |
1080 | }; | |
1081 | ||
1082 | const struct Options *options = NULL; | |
1083 | ||
1084 | switch (oper) { | |
1085 | case OFN_FILE_SAVE: options = saveOptions; break; | |
1086 | case OFN_DIR_CHOOSE: options = dirOptions; break; | |
1087 | case OFN_FILE_OPEN: options = openOptions; break; | |
1088 | } | |
1089 | ||
1090 | ZeroMemory(optsPtr, sizeof(*optsPtr)); | |
1091 | // optsPtr->forceXPStyle = 1; | |
1092 | optsPtr->tkwin = clientData; | |
1093 | optsPtr->confirmOverwrite = 1; /* By default we ask for confirmation */ | |
1094 | Tcl_DStringInit(&optsPtr->utfDirString); | |
1095 | optsPtr->file[0] = 0; | |
598 | 1096 | |
599 | 1097 | for (i = 1; i < objc; i += 2) { |
600 | 1098 | int index; |
603 | 1101 | |
604 | 1102 | if (Tcl_GetIndexFromObjStruct(interp, objv[i], options, |
605 | 1103 | sizeof(struct Options), "option", 0, &index) != TCL_OK) { |
606 | goto end; | |
1104 | /* | |
1105 | * XXX -xpstyle is explicitly checked for as it is undocumented | |
1106 | * and we do not want it to show in option error messages. | |
1107 | */ | |
1108 | if (strcmp(Tcl_GetString(objv[i]), "-xpstyle")) | |
1109 | goto error_return; | |
1110 | if (Tcl_GetBooleanFromObj(interp, valuePtr, | |
1111 | &optsPtr->forceXPStyle) != TCL_OK) | |
1112 | goto error_return; | |
1113 | ||
1114 | continue; | |
1115 | ||
607 | 1116 | } else if (i + 1 == objc) { |
608 | 1117 | Tcl_SetObjResult(interp, Tcl_ObjPrintf( |
609 | 1118 | "value for \"%s\" missing", options[index].name)); |
610 | 1119 | Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL); |
611 | goto end; | |
1120 | goto error_return; | |
612 | 1121 | } |
613 | 1122 | |
614 | 1123 | string = Tcl_GetString(valuePtr); |
615 | 1124 | switch (options[index].value) { |
616 | 1125 | case FILE_DEFAULT: |
617 | if (string[0] == '.') { | |
618 | string++; | |
619 | } | |
620 | extension = string; | |
1126 | optsPtr->extObj = valuePtr; | |
621 | 1127 | break; |
622 | 1128 | case FILE_TYPES: |
623 | filterObj = valuePtr; | |
1129 | optsPtr->filterObj = valuePtr; | |
624 | 1130 | break; |
625 | 1131 | case FILE_INITDIR: |
626 | Tcl_DStringFree(&utfDirString); | |
1132 | Tcl_DStringFree(&optsPtr->utfDirString); | |
627 | 1133 | if (Tcl_TranslateFileName(interp, string, |
628 | &utfDirString) == NULL) { | |
629 | goto end; | |
630 | } | |
1134 | &optsPtr->utfDirString) == NULL) | |
1135 | goto error_return; | |
631 | 1136 | break; |
632 | 1137 | case FILE_INITFILE: |
633 | if (Tcl_TranslateFileName(interp, string, &ds) == NULL) { | |
634 | goto end; | |
635 | } | |
1138 | if (Tcl_TranslateFileName(interp, string, &ds) == NULL) | |
1139 | goto error_return; | |
636 | 1140 | Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(), |
637 | Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL, | |
638 | (char *) file, sizeof(file), NULL, NULL, NULL); | |
1141 | Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL, | |
1142 | (char *) &optsPtr->file[0], sizeof(optsPtr->file), | |
1143 | NULL, NULL, NULL); | |
639 | 1144 | Tcl_DStringFree(&ds); |
640 | 1145 | break; |
641 | 1146 | case FILE_PARENT: |
642 | tkwin = Tk_NameToWindow(interp, string, tkwin); | |
643 | if (tkwin == NULL) { | |
644 | goto end; | |
645 | } | |
1147 | optsPtr->tkwin = Tk_NameToWindow(interp, string, clientData); | |
1148 | if (optsPtr->tkwin == NULL) | |
1149 | goto error_return; | |
646 | 1150 | break; |
647 | 1151 | case FILE_TITLE: |
648 | title = string; | |
1152 | optsPtr->titleObj = valuePtr; | |
649 | 1153 | break; |
650 | 1154 | case FILE_TYPEVARIABLE: |
651 | typeVariableObj = valuePtr; | |
652 | initialTypeObj = Tcl_ObjGetVar2(interp, typeVariableObj, NULL, | |
653 | TCL_GLOBAL_ONLY); | |
1155 | optsPtr->typeVariableObj = valuePtr; | |
1156 | optsPtr->initialTypeObj = Tcl_ObjGetVar2(interp, valuePtr, | |
1157 | NULL, TCL_GLOBAL_ONLY); | |
654 | 1158 | break; |
655 | 1159 | case FILE_MULTIPLE: |
656 | if (Tcl_GetBooleanFromObj(interp, valuePtr, &multi) != TCL_OK) { | |
657 | return TCL_ERROR; | |
658 | } | |
1160 | if (Tcl_GetBooleanFromObj(interp, valuePtr, | |
1161 | &optsPtr->multi) != TCL_OK) | |
1162 | goto error_return; | |
659 | 1163 | break; |
660 | 1164 | case FILE_CONFIRMOW: |
661 | 1165 | if (Tcl_GetBooleanFromObj(interp, valuePtr, |
662 | &confirmOverwrite) != TCL_OK) { | |
663 | return TCL_ERROR; | |
664 | } | |
1166 | &optsPtr->confirmOverwrite) != TCL_OK) | |
1167 | goto error_return; | |
665 | 1168 | break; |
666 | } | |
667 | } | |
668 | ||
669 | if (MakeFilter(interp, filterObj, &utfFilterString, initialTypeObj, | |
670 | &filterIndex) != TCL_OK) { | |
1169 | case FILE_MUSTEXIST: | |
1170 | if (Tcl_GetBooleanFromObj(interp, valuePtr, | |
1171 | &optsPtr->mustExist) != TCL_OK) | |
1172 | goto error_return; | |
1173 | break; | |
1174 | } | |
1175 | } | |
1176 | ||
1177 | return TCL_OK; | |
1178 | ||
1179 | error_return: /* interp should already hold error */ | |
1180 | /* On error, we need to clean up anything we might have allocated */ | |
1181 | CleanupOFNOptions(optsPtr); | |
1182 | return TCL_ERROR; | |
1183 | } | |
1184 | ||
1185 | ||
1186 | /* | |
1187 | *---------------------------------------------------------------------- | |
1188 | * VistaFileDialogsAvailable | |
1189 | * | |
1190 | * Checks whether the new (Vista) file dialogs can be used on | |
1191 | * the system. | |
1192 | * | |
1193 | * Returns: | |
1194 | * 1 if new dialogs are available, 0 otherwise | |
1195 | * | |
1196 | * Side effects: | |
1197 | * Loads required procedures dynamically if available. | |
1198 | * If new dialogs are available, COM is also initialized. | |
1199 | *---------------------------------------------------------------------- | |
1200 | */ | |
1201 | static int VistaFileDialogsAvailable() | |
1202 | { | |
1203 | HRESULT hr; | |
1204 | IFileDialog *fdlgPtr = NULL; | |
1205 | ThreadSpecificData *tsdPtr = | |
1206 | Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); | |
1207 | ||
1208 | if (tsdPtr->newFileDialogsState == FDLG_STATE_INIT) { | |
1209 | tsdPtr->newFileDialogsState = FDLG_STATE_USE_OLD; | |
1210 | LoadShellProcs(); | |
1211 | if (ShellProcs.SHCreateItemFromParsingName != NULL) { | |
1212 | hr = CoInitialize(0); | |
1213 | /* XXX - need we schedule CoUninitialize at thread shutdown ? */ | |
1214 | ||
1215 | /* Ensure all COM interfaces we use are available */ | |
1216 | if (SUCCEEDED(hr)) { | |
1217 | hr = CoCreateInstance(&ClsidFileOpenDialog, NULL, | |
1218 | CLSCTX_INPROC_SERVER, &IIDIFileOpenDialog, (void **) &fdlgPtr); | |
1219 | if (SUCCEEDED(hr)) { | |
1220 | fdlgPtr->lpVtbl->Release(fdlgPtr); | |
1221 | hr = CoCreateInstance(&ClsidFileSaveDialog, NULL, | |
1222 | CLSCTX_INPROC_SERVER, &IIDIFileSaveDialog, | |
1223 | (void **) &fdlgPtr); | |
1224 | if (SUCCEEDED(hr)) { | |
1225 | fdlgPtr->lpVtbl->Release(fdlgPtr); | |
1226 | ||
1227 | /* Looks like we have all we need */ | |
1228 | tsdPtr->newFileDialogsState = FDLG_STATE_USE_NEW; | |
1229 | } | |
1230 | } | |
1231 | } | |
1232 | } | |
1233 | } | |
1234 | ||
1235 | return (tsdPtr->newFileDialogsState == FDLG_STATE_USE_NEW); | |
1236 | } | |
1237 | ||
1238 | /* | |
1239 | *---------------------------------------------------------------------- | |
1240 | * | |
1241 | * GetFileNameVista -- | |
1242 | * | |
1243 | * Displays the new file dialogs on Vista and later. | |
1244 | * This function must generally not be called unless the | |
1245 | * tsdPtr->newFileDialogsState is FDLG_STATE_USE_NEW but if | |
1246 | * it is, it will just pass the call to the older GetFileNameXP | |
1247 | * | |
1248 | * Results: | |
1249 | * TCL_OK - dialog was successfully displayed, results returned in interp | |
1250 | * TCL_ERROR - error return | |
1251 | * | |
1252 | * Side effects: | |
1253 | * Dialogs is displayed | |
1254 | *---------------------------------------------------------------------- | |
1255 | */ | |
1256 | static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, | |
1257 | enum OFNOper oper) | |
1258 | { | |
1259 | HRESULT hr; | |
1260 | HWND hWnd; | |
1261 | DWORD flags, nfilters, defaultFilterIndex; | |
1262 | TCLCOMDLG_FILTERSPEC *filterPtr = NULL; | |
1263 | IFileDialog *fdlgIf = NULL; | |
1264 | IShellItem *dirIf = NULL; | |
1265 | LPWSTR wstr; | |
1266 | Tcl_Obj *resultObj = NULL; | |
1267 | ThreadSpecificData *tsdPtr = | |
1268 | Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); | |
1269 | int oldMode; | |
1270 | ||
1271 | if (tsdPtr->newFileDialogsState != FDLG_STATE_USE_NEW) { | |
1272 | /* XXX - should be an assert but Tcl does not seem to have one? */ | |
1273 | Tcl_SetResult(interp, "Internal error: GetFileNameVista: IFileDialog API not available", TCL_STATIC); | |
1274 | return TCL_ERROR; | |
1275 | } | |
1276 | ||
1277 | /* | |
1278 | * At this point new interfaces are supposed to be available. | |
1279 | * fdlgIf is actually a IFileOpenDialog or IFileSaveDialog | |
1280 | * both of which inherit from IFileDialog. We use the common | |
1281 | * IFileDialog interface for the most part, casting only for | |
1282 | * type-specific calls. | |
1283 | */ | |
1284 | Tk_MakeWindowExist(optsPtr->tkwin); | |
1285 | hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin)); | |
1286 | ||
1287 | /* | |
1288 | * The only validation we need to do w.r.t caller supplied data | |
1289 | * is the filter specification so do that before creating | |
1290 | */ | |
1291 | if (MakeFilterVista(interp, optsPtr, &nfilters, &filterPtr, | |
1292 | &defaultFilterIndex) != TCL_OK) | |
1293 | return TCL_ERROR; | |
1294 | ||
1295 | /* | |
1296 | * Beyond this point, do not just return on error as there will be | |
1297 | * resources that need to be released/freed. | |
1298 | */ | |
1299 | ||
1300 | if (oper == OFN_FILE_OPEN || oper == OFN_DIR_CHOOSE) | |
1301 | hr = CoCreateInstance(&ClsidFileOpenDialog, NULL, | |
1302 | CLSCTX_INPROC_SERVER, &IIDIFileOpenDialog, (void **) &fdlgIf); | |
1303 | else | |
1304 | hr = CoCreateInstance(&ClsidFileSaveDialog, NULL, | |
1305 | CLSCTX_INPROC_SERVER, &IIDIFileSaveDialog, (void **) &fdlgIf); | |
1306 | ||
1307 | if (FAILED(hr)) | |
1308 | goto vamoose; | |
1309 | ||
1310 | /* | |
1311 | * Get current settings first because we want to preserve existing | |
1312 | * settings like whether to show hidden files etc. based on the | |
1313 | * user's existing preference | |
1314 | */ | |
1315 | hr = fdlgIf->lpVtbl->GetOptions(fdlgIf, &flags); | |
1316 | if (FAILED(hr)) | |
1317 | goto vamoose; | |
1318 | ||
1319 | if (filterPtr) { | |
1320 | flags |= FOS_STRICTFILETYPES; | |
1321 | hr = fdlgIf->lpVtbl->SetFileTypes(fdlgIf, nfilters, filterPtr); | |
1322 | if (FAILED(hr)) | |
1323 | goto vamoose; | |
1324 | hr = fdlgIf->lpVtbl->SetFileTypeIndex(fdlgIf, defaultFilterIndex); | |
1325 | if (FAILED(hr)) | |
1326 | goto vamoose; | |
1327 | } | |
1328 | ||
1329 | /* Flags are equivalent to those we used in the older API */ | |
1330 | ||
1331 | /* | |
1332 | * Following flags must be set irrespective of original setting | |
1333 | * XXX - should FOS_NOVALIDATE be there ? Note FOS_NOVALIDATE has different | |
1334 | * semantics than OFN_NOVALIDATE in the old API. | |
1335 | */ | |
1336 | flags |= | |
1337 | FOS_FORCEFILESYSTEM | /* Only want files, not other shell items */ | |
1338 | FOS_NOVALIDATE | /* Don't check for access denied etc. */ | |
1339 | FOS_PATHMUSTEXIST; /* The *directory* path must exist */ | |
1340 | ||
1341 | ||
1342 | if (oper == OFN_DIR_CHOOSE) { | |
1343 | flags |= FOS_PICKFOLDERS; | |
1344 | if (optsPtr->mustExist) | |
1345 | flags |= FOS_FILEMUSTEXIST; /* XXX - check working */ | |
1346 | } else | |
1347 | flags &= ~ FOS_PICKFOLDERS; | |
1348 | ||
1349 | if (optsPtr->multi) | |
1350 | flags |= FOS_ALLOWMULTISELECT; | |
1351 | else | |
1352 | flags &= ~FOS_ALLOWMULTISELECT; | |
1353 | ||
1354 | if (optsPtr->confirmOverwrite) | |
1355 | flags |= FOS_OVERWRITEPROMPT; | |
1356 | else | |
1357 | flags &= ~FOS_OVERWRITEPROMPT; | |
1358 | ||
1359 | hr = fdlgIf->lpVtbl->SetOptions(fdlgIf, flags); | |
1360 | if (FAILED(hr)) | |
1361 | goto vamoose; | |
1362 | ||
1363 | if (optsPtr->extObj != NULL) { | |
1364 | wstr = Tcl_GetUnicode(optsPtr->extObj); | |
1365 | if (wstr[0] == L'.') | |
1366 | ++wstr; | |
1367 | hr = fdlgIf->lpVtbl->SetDefaultExtension(fdlgIf, wstr); | |
1368 | if (FAILED(hr)) | |
1369 | goto vamoose; | |
1370 | } | |
1371 | ||
1372 | if (optsPtr->titleObj != NULL) { | |
1373 | hr = fdlgIf->lpVtbl->SetTitle(fdlgIf, | |
1374 | Tcl_GetUnicode(optsPtr->titleObj)); | |
1375 | if (FAILED(hr)) | |
1376 | goto vamoose; | |
1377 | } | |
1378 | ||
1379 | if (optsPtr->file[0]) { | |
1380 | hr = fdlgIf->lpVtbl->SetFileName(fdlgIf, optsPtr->file); | |
1381 | if (FAILED(hr)) | |
1382 | goto vamoose; | |
1383 | } | |
1384 | ||
1385 | if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') { | |
1386 | Tcl_DString dirString; | |
1387 | Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString), | |
1388 | Tcl_DStringLength(&optsPtr->utfDirString), &dirString); | |
1389 | hr = ShellProcs.SHCreateItemFromParsingName( | |
1390 | (TCHAR *) Tcl_DStringValue(&dirString), NULL, | |
1391 | &IIDIShellItem, (void **) &dirIf); | |
1392 | /* XXX - Note on failure we do not raise error, simply ignore ini dir */ | |
1393 | if (SUCCEEDED(hr)) { | |
1394 | /* Note we use SetFolder, not SetDefaultFolder - see MSDN docs */ | |
1395 | fdlgIf->lpVtbl->SetFolder(fdlgIf, dirIf); /* Ignore errors */ | |
1396 | } | |
1397 | Tcl_DStringFree(&dirString); | |
1398 | } | |
1399 | ||
1400 | oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); | |
1401 | hr = fdlgIf->lpVtbl->Show(fdlgIf, hWnd); | |
1402 | Tcl_SetServiceMode(oldMode); | |
1403 | ||
1404 | if (SUCCEEDED(hr)) { | |
1405 | if ((oper == OFN_FILE_OPEN) && optsPtr->multi) { | |
1406 | IShellItemArray *multiIf; | |
1407 | DWORD dw, count; | |
1408 | IFileOpenDialog *fodIf = (IFileOpenDialog *) fdlgIf; | |
1409 | hr = fodIf->lpVtbl->GetResults(fodIf, &multiIf); | |
1410 | if (SUCCEEDED(hr)) { | |
1411 | Tcl_Obj *multiObj; | |
1412 | hr = multiIf->lpVtbl->GetCount(multiIf, &count); | |
1413 | multiObj = Tcl_NewListObj(count, NULL); | |
1414 | if (SUCCEEDED(hr)) { | |
1415 | IShellItem *itemIf; | |
1416 | for (dw = 0; dw < count; ++dw) { | |
1417 | hr = multiIf->lpVtbl->GetItemAt(multiIf, dw, &itemIf); | |
1418 | if (FAILED(hr)) | |
1419 | break; | |
1420 | hr = itemIf->lpVtbl->GetDisplayName(itemIf, | |
1421 | SIGDN_FILESYSPATH, &wstr); | |
1422 | if (SUCCEEDED(hr)) { | |
1423 | Tcl_DString fnds; | |
1424 | ConvertExternalFilename(wstr, &fnds); | |
1425 | CoTaskMemFree(wstr); | |
1426 | Tcl_ListObjAppendElement( | |
1427 | interp, multiObj, | |
1428 | Tcl_NewStringObj(Tcl_DStringValue(&fnds), | |
1429 | Tcl_DStringLength(&fnds))); | |
1430 | } | |
1431 | itemIf->lpVtbl->Release(itemIf); | |
1432 | if (FAILED(hr)) | |
1433 | break; | |
1434 | } | |
1435 | } | |
1436 | multiIf->lpVtbl->Release(multiIf); | |
1437 | if (SUCCEEDED(hr)) | |
1438 | resultObj = multiObj; | |
1439 | else | |
1440 | Tcl_DecrRefCount(multiObj); | |
1441 | } | |
1442 | } else { | |
1443 | IShellItem *resultIf; | |
1444 | hr = fdlgIf->lpVtbl->GetResult(fdlgIf, &resultIf); | |
1445 | if (SUCCEEDED(hr)) { | |
1446 | hr = resultIf->lpVtbl->GetDisplayName(resultIf, SIGDN_FILESYSPATH, | |
1447 | &wstr); | |
1448 | if (SUCCEEDED(hr)) { | |
1449 | Tcl_DString fnds; | |
1450 | ConvertExternalFilename(wstr, &fnds); | |
1451 | resultObj = Tcl_NewStringObj(Tcl_DStringValue(&fnds), | |
1452 | Tcl_DStringLength(&fnds)); | |
1453 | CoTaskMemFree(wstr); | |
1454 | } | |
1455 | resultIf->lpVtbl->Release(resultIf); | |
1456 | } | |
1457 | } | |
1458 | if (SUCCEEDED(hr)) { | |
1459 | if (filterPtr && optsPtr->typeVariableObj) { | |
1460 | UINT ftix; | |
1461 | hr = fdlgIf->lpVtbl->GetFileTypeIndex(fdlgIf, &ftix); | |
1462 | if (SUCCEEDED(hr)) { | |
1463 | /* Note ftix is a 1-based index */ | |
1464 | if (ftix > 0 && ftix <= nfilters) { | |
1465 | Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL, | |
1466 | Tcl_NewUnicodeObj(filterPtr[ftix-1].pszName, -1), | |
1467 | TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); | |
1468 | } | |
1469 | } | |
1470 | } | |
1471 | } | |
1472 | } else { | |
1473 | if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) | |
1474 | hr = 0; /* User cancelled, return empty string */ | |
1475 | } | |
1476 | ||
1477 | vamoose: /* (hr != 0) => error */ | |
1478 | if (dirIf) | |
1479 | dirIf->lpVtbl->Release(dirIf); | |
1480 | if (fdlgIf) | |
1481 | fdlgIf->lpVtbl->Release(fdlgIf); | |
1482 | ||
1483 | if (filterPtr) | |
1484 | FreeFilterVista(nfilters, filterPtr); | |
1485 | ||
1486 | if (hr == 0) { | |
1487 | if (resultObj) /* May be NULL if user cancelled */ | |
1488 | Tcl_SetObjResult(interp, resultObj); | |
1489 | return TCL_OK; | |
1490 | } else { | |
1491 | if (resultObj) | |
1492 | Tcl_DecrRefCount(resultObj); | |
1493 | Tcl_SetObjResult(interp, TkWin32ErrorObj(hr)); | |
1494 | return TCL_ERROR; | |
1495 | } | |
1496 | } | |
1497 | ||
1498 | ||
1499 | /* | |
1500 | *---------------------------------------------------------------------- | |
1501 | * | |
1502 | * GetFileNameXP -- | |
1503 | * | |
1504 | * Displays the old pre-Vista file dialogs. | |
1505 | * | |
1506 | * Results: | |
1507 | * TCL_OK - if dialog was successfully displayed | |
1508 | * TCL_ERROR - error return | |
1509 | * | |
1510 | * Side effects: | |
1511 | * See user documentation. | |
1512 | *---------------------------------------------------------------------- | |
1513 | */ | |
1514 | static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr, enum OFNOper oper) | |
1515 | { | |
1516 | OPENFILENAME ofn; | |
1517 | OFNData ofnData; | |
1518 | int cdlgerr; | |
1519 | int filterIndex = 0, result = TCL_ERROR, winCode, oldMode; | |
1520 | HWND hWnd; | |
1521 | Tcl_DString utfFilterString, ds; | |
1522 | Tcl_DString extString, filterString, dirString, titleString; | |
1523 | const char *str; | |
1524 | ThreadSpecificData *tsdPtr = | |
1525 | Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); | |
1526 | ||
1527 | ZeroMemory(&ofnData, sizeof(OFNData)); | |
1528 | Tcl_DStringInit(&utfFilterString); | |
1529 | Tcl_DStringInit(&dirString); /* XXX - original code was missing this | |
1530 | leaving dirString uninitialized for | |
1531 | the unlikely code path where cwd failed */ | |
1532 | ||
1533 | if (MakeFilter(interp, optsPtr->filterObj, &utfFilterString, | |
1534 | optsPtr->initialTypeObj, &filterIndex) != TCL_OK) { | |
671 | 1535 | goto end; |
672 | 1536 | } |
673 | 1537 | |
674 | Tk_MakeWindowExist(tkwin); | |
675 | hWnd = Tk_GetHWND(Tk_WindowId(tkwin)); | |
1538 | Tk_MakeWindowExist(optsPtr->tkwin); | |
1539 | hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin)); | |
676 | 1540 | |
677 | 1541 | ZeroMemory(&ofn, sizeof(OPENFILENAME)); |
678 | 1542 | ofn.lStructSize = sizeof(OPENFILENAME); |
679 | 1543 | ofn.hwndOwner = hWnd; |
680 | 1544 | ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner); |
681 | ofn.lpstrFile = file; | |
1545 | ofn.lpstrFile = optsPtr->file; | |
682 | 1546 | ofn.nMaxFile = TK_MULTI_MAX_PATH; |
683 | 1547 | ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR |
684 | | OFN_EXPLORER | OFN_ENABLEHOOK| OFN_ENABLESIZING; | |
1548 | | OFN_EXPLORER| OFN_ENABLEHOOK| OFN_ENABLESIZING; | |
685 | 1549 | ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc; |
686 | 1550 | ofn.lCustData = (LPARAM) &ofnData; |
687 | 1551 | |
688 | if (open != 0) { | |
1552 | if (oper != OFN_FILE_SAVE) { | |
689 | 1553 | ofn.Flags |= OFN_FILEMUSTEXIST; |
690 | } else if (confirmOverwrite) { | |
1554 | } else if (optsPtr->confirmOverwrite) { | |
691 | 1555 | ofn.Flags |= OFN_OVERWRITEPROMPT; |
692 | 1556 | } |
693 | 1557 | if (tsdPtr->debugFlag != 0) { |
694 | 1558 | ofnData.interp = interp; |
695 | 1559 | } |
696 | if (multi != 0) { | |
1560 | if (optsPtr->multi != 0) { | |
697 | 1561 | ofn.Flags |= OFN_ALLOWMULTISELECT; |
698 | 1562 | |
699 | 1563 | /* |
705 | 1569 | ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR)); |
706 | 1570 | } |
707 | 1571 | |
708 | if (extension != NULL) { | |
709 | Tcl_WinUtfToTChar(extension, -1, &extString); | |
1572 | if (optsPtr->extObj != NULL) { | |
1573 | str = Tcl_GetString(optsPtr->extObj); | |
1574 | if (str[0] == '.') | |
1575 | ++str; | |
1576 | Tcl_WinUtfToTChar(str, -1, &extString); | |
710 | 1577 | ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString); |
711 | 1578 | } |
712 | 1579 | |
715 | 1582 | ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString); |
716 | 1583 | ofn.nFilterIndex = filterIndex; |
717 | 1584 | |
718 | if (Tcl_DStringValue(&utfDirString)[0] != '\0') { | |
719 | Tcl_WinUtfToTChar(Tcl_DStringValue(&utfDirString), | |
720 | Tcl_DStringLength(&utfDirString), &dirString); | |
1585 | if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') { | |
1586 | Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString), | |
1587 | Tcl_DStringLength(&optsPtr->utfDirString), &dirString); | |
721 | 1588 | } else { |
722 | 1589 | /* |
723 | 1590 | * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure |
726 | 1593 | |
727 | 1594 | Tcl_DString cwd; |
728 | 1595 | |
729 | Tcl_DStringFree(&utfDirString); | |
730 | if ((Tcl_GetCwd(interp, &utfDirString) == NULL) || | |
1596 | Tcl_DStringFree(&optsPtr->utfDirString); | |
1597 | if ((Tcl_GetCwd(interp, &optsPtr->utfDirString) == NULL) || | |
731 | 1598 | (Tcl_TranslateFileName(interp, |
732 | Tcl_DStringValue(&utfDirString), &cwd) == NULL)) { | |
1599 | Tcl_DStringValue(&optsPtr->utfDirString), &cwd) == NULL)) { | |
733 | 1600 | Tcl_ResetResult(interp); |
734 | 1601 | } else { |
735 | 1602 | Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd), |
739 | 1606 | } |
740 | 1607 | ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString); |
741 | 1608 | |
742 | if (title != NULL) { | |
743 | Tcl_WinUtfToTChar(title, -1, &titleString); | |
1609 | if (optsPtr->titleObj != NULL) { | |
1610 | Tcl_WinUtfToTChar(Tcl_GetString(optsPtr->titleObj), -1, &titleString); | |
744 | 1611 | ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString); |
745 | 1612 | } |
746 | 1613 | |
749 | 1616 | */ |
750 | 1617 | |
751 | 1618 | oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); |
752 | if (open != 0) { | |
1619 | if (oper != OFN_FILE_SAVE) { | |
753 | 1620 | winCode = GetOpenFileName(&ofn); |
754 | 1621 | } else { |
755 | 1622 | winCode = GetSaveFileName(&ofn); |
858 | 1725 | Tcl_DStringFree(&ds); |
859 | 1726 | } |
860 | 1727 | result = TCL_OK; |
861 | if ((ofn.nFilterIndex > 0) && gotFilename && typeVariableObj | |
862 | && filterObj) { | |
1728 | if ((ofn.nFilterIndex > 0) && gotFilename && optsPtr->typeVariableObj | |
1729 | && optsPtr->filterObj) { | |
863 | 1730 | int listObjc, count; |
864 | 1731 | Tcl_Obj **listObjv = NULL; |
865 | 1732 | Tcl_Obj **typeInfo = NULL; |
866 | 1733 | |
867 | if (Tcl_ListObjGetElements(interp, filterObj, | |
1734 | if (Tcl_ListObjGetElements(interp, optsPtr->filterObj, | |
868 | 1735 | &listObjc, &listObjv) != TCL_OK) { |
869 | 1736 | result = TCL_ERROR; |
870 | 1737 | } else if (Tcl_ListObjGetElements(interp, |
871 | 1738 | listObjv[ofn.nFilterIndex - 1], &count, |
872 | 1739 | &typeInfo) != TCL_OK) { |
873 | 1740 | result = TCL_ERROR; |
874 | } else if (Tcl_ObjSetVar2(interp, typeVariableObj, NULL, | |
875 | typeInfo[0], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { | |
1741 | } else if (Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL, | |
1742 | typeInfo[0], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { | |
876 | 1743 | result = TCL_ERROR; |
877 | 1744 | } |
878 | 1745 | } |
891 | 1758 | Tcl_DStringFree(&titleString); |
892 | 1759 | } |
893 | 1760 | if (ofn.lpstrInitialDir != NULL) { |
1761 | /* XXX - huh? lpstrInitialDir is set from Tcl_DStringValue which | |
1762 | can never return NULL */ | |
894 | 1763 | Tcl_DStringFree(&dirString); |
895 | 1764 | } |
896 | 1765 | Tcl_DStringFree(&filterString); |
898 | 1767 | Tcl_DStringFree(&extString); |
899 | 1768 | } |
900 | 1769 | |
901 | end: | |
902 | Tcl_DStringFree(&utfDirString); | |
1770 | end: | |
903 | 1771 | Tcl_DStringFree(&utfFilterString); |
904 | 1772 | if (ofnData.dynFileBuffer != NULL) { |
905 | 1773 | ckfree(ofnData.dynFileBuffer); |
908 | 1776 | |
909 | 1777 | return result; |
910 | 1778 | } |
1779 | ||
1780 | ||
1781 | /* | |
1782 | *---------------------------------------------------------------------- | |
1783 | * | |
1784 | * GetFileName -- | |
1785 | * | |
1786 | * Calls GetOpenFileName() or GetSaveFileName(). | |
1787 | * | |
1788 | * Results: | |
1789 | * See user documentation. | |
1790 | * | |
1791 | * Side effects: | |
1792 | * See user documentation. | |
1793 | * | |
1794 | *---------------------------------------------------------------------- | |
1795 | */ | |
1796 | ||
1797 | static int | |
1798 | GetFileName( | |
1799 | ClientData clientData, /* Main window associated with interpreter. */ | |
1800 | Tcl_Interp *interp, /* Current interpreter. */ | |
1801 | int objc, /* Number of arguments. */ | |
1802 | Tcl_Obj *const objv[], /* Argument objects. */ | |
1803 | enum OFNOper oper) /* 1 to call GetOpenFileName(), 0 to call | |
1804 | * GetSaveFileName(). */ | |
1805 | { | |
1806 | OFNOpts ofnOpts; | |
1807 | int result; | |
1808 | ||
1809 | result = ParseOFNOptions(clientData, interp, objc, objv, oper, &ofnOpts); | |
1810 | if (result != TCL_OK) | |
1811 | return result; | |
1812 | ||
1813 | if (VistaFileDialogsAvailable() && ! ofnOpts.forceXPStyle) | |
1814 | result = GetFileNameVista(interp, &ofnOpts, oper); | |
1815 | else | |
1816 | result = GetFileNameXP(interp, &ofnOpts, oper); | |
1817 | ||
1818 | CleanupOFNOptions(&ofnOpts); | |
1819 | return result; | |
1820 | } | |
1821 | ||
911 | 1822 | |
912 | 1823 | /* |
913 | 1824 | *------------------------------------------------------------------------- |
972 | 1883 | buffer = ofnData->dynFileBuffer; |
973 | 1884 | hdlg = GetParent(hdlg); |
974 | 1885 | |
975 | selsize = SendMessage(hdlg, CDM_GETSPEC, 0, 0); | |
976 | dirsize = SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0); | |
1886 | selsize = (int) SendMessage(hdlg, CDM_GETSPEC, 0, 0); | |
1887 | dirsize = (int) SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0); | |
977 | 1888 | buffersize = (selsize + dirsize + 1); |
978 | 1889 | |
979 | 1890 | /* |
1231 | 2142 | /* |
1232 | 2143 | *---------------------------------------------------------------------- |
1233 | 2144 | * |
2145 | * FreeFilterVista | |
2146 | * | |
2147 | * Frees storage previously allocated by MakeFilterVista. | |
2148 | * count is the number of elements in dlgFilterPtr[] | |
2149 | */ | |
2150 | static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr) | |
2151 | { | |
2152 | if (dlgFilterPtr != NULL) { | |
2153 | DWORD dw; | |
2154 | for (dw = 0; dw < count; ++dw) { | |
2155 | if (dlgFilterPtr[dw].pszName != NULL) | |
2156 | ckfree(dlgFilterPtr[dw].pszName); | |
2157 | if (dlgFilterPtr[dw].pszSpec != NULL) | |
2158 | ckfree(dlgFilterPtr[dw].pszSpec); | |
2159 | } | |
2160 | ckfree(dlgFilterPtr); | |
2161 | } | |
2162 | } | |
2163 | ||
2164 | /* | |
2165 | *---------------------------------------------------------------------- | |
2166 | * | |
2167 | * MakeFilterVista -- | |
2168 | * | |
2169 | * Returns file type filters in a format required | |
2170 | * by the Vista file dialogs. | |
2171 | * | |
2172 | * Results: | |
2173 | * A standard TCL return value. | |
2174 | * | |
2175 | * Side effects: | |
2176 | * Various values are returned through the parameters as | |
2177 | * described in the comments below. | |
2178 | *---------------------------------------------------------------------- | |
2179 | */ | |
2180 | static int MakeFilterVista( | |
2181 | Tcl_Interp *interp, /* Current interpreter. */ | |
2182 | OFNOpts *optsPtr, /* Caller specified options */ | |
2183 | DWORD *countPtr, /* Will hold number of filters */ | |
2184 | TCLCOMDLG_FILTERSPEC **dlgFilterPtrPtr, /* Will hold pointer to filter array. | |
2185 | Set to NULL if no filters specified. | |
2186 | Must be freed by calling | |
2187 | FreeFilterVista */ | |
2188 | DWORD *initialIndexPtr) /* Will hold index of default type */ | |
2189 | { | |
2190 | TCLCOMDLG_FILTERSPEC *dlgFilterPtr; | |
2191 | const char *initial = NULL; | |
2192 | FileFilterList flist; | |
2193 | FileFilter *filterPtr; | |
2194 | DWORD initialIndex = 0; | |
2195 | Tcl_DString ds, patterns; | |
2196 | int i; | |
2197 | ||
2198 | if (optsPtr->filterObj == NULL) { | |
2199 | *dlgFilterPtrPtr = NULL; | |
2200 | *countPtr = 0; | |
2201 | return TCL_OK; | |
2202 | } | |
2203 | ||
2204 | if (optsPtr->initialTypeObj) | |
2205 | initial = Tcl_GetString(optsPtr->initialTypeObj); | |
2206 | ||
2207 | TkInitFileFilters(&flist); | |
2208 | if (TkGetFileFilters(interp, &flist, optsPtr->filterObj, 1) != TCL_OK) | |
2209 | return TCL_ERROR; | |
2210 | ||
2211 | if (flist.filters == NULL) { | |
2212 | *dlgFilterPtrPtr = NULL; | |
2213 | *countPtr = 0; | |
2214 | return TCL_OK; | |
2215 | } | |
2216 | ||
2217 | Tcl_DStringInit(&ds); | |
2218 | Tcl_DStringInit(&patterns); | |
2219 | dlgFilterPtr = ckalloc(flist.numFilters * sizeof(*dlgFilterPtr)); | |
2220 | ||
2221 | for (i = 0, filterPtr = flist.filters; | |
2222 | filterPtr; | |
2223 | filterPtr = filterPtr->next, ++i) { | |
2224 | const char *sep; | |
2225 | FileFilterClause *clausePtr; | |
2226 | int nbytes; | |
2227 | ||
2228 | /* Check if this entry should be shown as the default */ | |
2229 | if (initial && strcmp(initial, filterPtr->name) == 0) | |
2230 | initialIndex = i+1; /* Windows filter indices are 1-based */ | |
2231 | ||
2232 | /* First stash away the text description of the pattern */ | |
2233 | Tcl_WinUtfToTChar(filterPtr->name, -1, &ds); | |
2234 | nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */ | |
2235 | nbytes += sizeof(WCHAR); /* Terminating \0 */ | |
2236 | dlgFilterPtr[i].pszName = ckalloc(nbytes); | |
2237 | memmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes); | |
2238 | Tcl_DStringFree(&ds); | |
2239 | ||
2240 | /* | |
2241 | * Loop through and join patterns with a ";" Each "clause" | |
2242 | * corresponds to a single textual description (called typename) | |
2243 | * in the tk_getOpenFile docs. Each such typename may occur | |
2244 | * multiple times and all these form a single filter entry | |
2245 | * with one clause per occurence. Further each clause may specify | |
2246 | * multiple patterns. Hence the nested loop here. | |
2247 | */ | |
2248 | sep = ""; | |
2249 | for (clausePtr=filterPtr->clauses ; clausePtr; | |
2250 | clausePtr=clausePtr->next) { | |
2251 | GlobPattern *globPtr; | |
2252 | for (globPtr = clausePtr->patterns; globPtr; | |
2253 | globPtr = globPtr->next) { | |
2254 | Tcl_DStringAppend(&patterns, sep, -1); | |
2255 | Tcl_DStringAppend(&patterns, globPtr->pattern, -1); | |
2256 | sep = ";"; | |
2257 | } | |
2258 | } | |
2259 | ||
2260 | /* Again we need a Unicode form of the string */ | |
2261 | Tcl_WinUtfToTChar(Tcl_DStringValue(&patterns), -1, &ds); | |
2262 | nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */ | |
2263 | nbytes += sizeof(WCHAR); /* Terminating \0 */ | |
2264 | dlgFilterPtr[i].pszSpec = ckalloc(nbytes); | |
2265 | memmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes); | |
2266 | Tcl_DStringFree(&ds); | |
2267 | Tcl_DStringFree(&patterns); | |
2268 | } | |
2269 | ||
2270 | if (initialIndex == 0) | |
2271 | initialIndex = 1; /* If no default, show first entry */ | |
2272 | *initialIndexPtr = initialIndex; | |
2273 | *dlgFilterPtrPtr = dlgFilterPtr; | |
2274 | *countPtr = flist.numFilters; | |
2275 | ||
2276 | TkFreeFileFilters(&flist); | |
2277 | return TCL_OK; | |
2278 | } | |
2279 | ||
2280 | ||
2281 | /* | |
2282 | *---------------------------------------------------------------------- | |
2283 | * | |
1234 | 2284 | * Tk_ChooseDirectoryObjCmd -- |
1235 | 2285 | * |
1236 | 2286 | * This function implements the "tk_chooseDirectory" dialog box for the |
1306 | 2356 | Tcl_Obj *const objv[]) /* Argument objects. */ |
1307 | 2357 | { |
1308 | 2358 | TCHAR path[MAX_PATH]; |
1309 | int oldMode, result = TCL_ERROR, i; | |
2359 | int oldMode, result; | |
1310 | 2360 | LPCITEMIDLIST pidl; /* Returned by browser */ |
1311 | 2361 | BROWSEINFO bInfo; /* Used by browser */ |
1312 | 2362 | ChooseDir cdCBData; /* Structure to pass back and forth */ |
1313 | 2363 | LPMALLOC pMalloc; /* Used by shell */ |
1314 | Tk_Window tkwin = clientData; | |
1315 | 2364 | HWND hWnd; |
1316 | const char *utfTitle = NULL;/* Title for window */ | |
1317 | 2365 | TCHAR saveDir[MAX_PATH]; |
1318 | 2366 | Tcl_DString titleString; /* Title */ |
1319 | Tcl_DString initDirString; /* Initial directory */ | |
1320 | 2367 | Tcl_DString tempString; /* temporary */ |
1321 | 2368 | Tcl_Obj *objPtr; |
1322 | static const char *const optionStrings[] = { | |
1323 | "-initialdir", "-mustexist", "-parent", "-title", NULL | |
1324 | }; | |
1325 | enum options { | |
1326 | DIR_INITIAL, DIR_EXIST, DIR_PARENT, FILE_TITLE | |
1327 | }; | |
1328 | ||
1329 | /* | |
1330 | * Initialize | |
1331 | */ | |
2369 | OFNOpts ofnOpts; | |
2370 | const char *utfDir; | |
2371 | ||
2372 | result = ParseOFNOptions(clientData, interp, objc, objv, | |
2373 | OFN_DIR_CHOOSE, &ofnOpts); | |
2374 | if (result != TCL_OK) | |
2375 | return result; | |
2376 | ||
2377 | /* Use new dialogs if available */ | |
2378 | if (VistaFileDialogsAvailable() && ! ofnOpts.forceXPStyle) { | |
2379 | result = GetFileNameVista(interp, &ofnOpts, OFN_DIR_CHOOSE); | |
2380 | CleanupOFNOptions(&ofnOpts); | |
2381 | return result; | |
2382 | } | |
2383 | ||
2384 | /* Older dialogs */ | |
1332 | 2385 | |
1333 | 2386 | path[0] = '\0'; |
1334 | 2387 | ZeroMemory(&cdCBData, sizeof(ChooseDir)); |
1335 | 2388 | cdCBData.interp = interp; |
1336 | ||
1337 | /* | |
1338 | * Process the command line options | |
1339 | */ | |
1340 | ||
1341 | for (i = 1; i < objc; i += 2) { | |
1342 | int index; | |
1343 | const char *string; | |
2389 | cdCBData.mustExist = ofnOpts.mustExist; | |
2390 | ||
2391 | utfDir = Tcl_DStringValue(&ofnOpts.utfDirString); | |
2392 | if (utfDir[0] != '\0') { | |
1344 | 2393 | const TCHAR *uniStr; |
1345 | Tcl_Obj *optionPtr, *valuePtr; | |
1346 | ||
1347 | optionPtr = objv[i]; | |
1348 | valuePtr = objv[i + 1]; | |
1349 | ||
1350 | if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings, | |
1351 | sizeof(char *), "option", 0, &index) != TCL_OK) { | |
1352 | goto cleanup; | |
1353 | } | |
1354 | if (i + 1 == objc) { | |
1355 | Tcl_SetObjResult(interp, Tcl_ObjPrintf( | |
1356 | "value for \"%s\" missing", Tcl_GetString(optionPtr))); | |
1357 | Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL); | |
1358 | goto cleanup; | |
1359 | } | |
1360 | ||
1361 | string = Tcl_GetString(valuePtr); | |
1362 | switch ((enum options) index) { | |
1363 | case DIR_INITIAL: | |
1364 | if (Tcl_TranslateFileName(interp,string,&initDirString) == NULL) { | |
1365 | goto cleanup; | |
1366 | } | |
1367 | Tcl_WinUtfToTChar(Tcl_DStringValue(&initDirString), -1, | |
1368 | &tempString); | |
1369 | uniStr = (TCHAR *) Tcl_DStringValue(&tempString); | |
1370 | ||
1371 | /* | |
1372 | * Convert possible relative path to full path to keep dialog | |
1373 | * happy. | |
1374 | */ | |
1375 | ||
1376 | GetFullPathName(uniStr, MAX_PATH, saveDir, NULL); | |
1377 | _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH); | |
1378 | Tcl_DStringFree(&initDirString); | |
1379 | Tcl_DStringFree(&tempString); | |
1380 | break; | |
1381 | case DIR_EXIST: | |
1382 | if (Tcl_GetBooleanFromObj(interp, valuePtr, | |
1383 | &cdCBData.mustExist) != TCL_OK) { | |
1384 | goto cleanup; | |
1385 | } | |
1386 | break; | |
1387 | case DIR_PARENT: | |
1388 | tkwin = Tk_NameToWindow(interp, string, tkwin); | |
1389 | if (tkwin == NULL) { | |
1390 | goto cleanup; | |
1391 | } | |
1392 | break; | |
1393 | case FILE_TITLE: | |
1394 | utfTitle = string; | |
1395 | break; | |
1396 | } | |
1397 | } | |
2394 | ||
2395 | Tcl_WinUtfToTChar(Tcl_DStringValue(&ofnOpts.utfDirString), -1, | |
2396 | &tempString); | |
2397 | uniStr = (TCHAR *) Tcl_DStringValue(&tempString); | |
2398 | ||
2399 | /* Convert possible relative path to full path to keep dialog happy. */ | |
2400 | ||
2401 | GetFullPathName(uniStr, MAX_PATH, saveDir, NULL); | |
2402 | _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH); | |
2403 | } | |
2404 | ||
2405 | /* XXX - rest of this (original) code has no error checks at all. */ | |
1398 | 2406 | |
1399 | 2407 | /* |
1400 | 2408 | * Get ready to call the browser |
1401 | 2409 | */ |
1402 | 2410 | |
1403 | Tk_MakeWindowExist(tkwin); | |
1404 | hWnd = Tk_GetHWND(Tk_WindowId(tkwin)); | |
2411 | Tk_MakeWindowExist(ofnOpts.tkwin); | |
2412 | hWnd = Tk_GetHWND(Tk_WindowId(ofnOpts.tkwin)); | |
1405 | 2413 | |
1406 | 2414 | /* |
1407 | 2415 | * Setup the parameters used by SHBrowseForFolder |
1415 | 2423 | } |
1416 | 2424 | bInfo.lParam = (LPARAM) &cdCBData; |
1417 | 2425 | |
1418 | if (utfTitle != NULL) { | |
1419 | Tcl_WinUtfToTChar(utfTitle, -1, &titleString); | |
2426 | if (ofnOpts.titleObj != NULL) { | |
2427 | Tcl_WinUtfToTChar(Tcl_GetString(ofnOpts.titleObj), -1, &titleString); | |
1420 | 2428 | bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString); |
1421 | 2429 | } else { |
1422 | 2430 | bInfo.lpszTitle = TEXT("Please choose a directory, then select OK."); |
1454 | 2462 | oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); |
1455 | 2463 | GetCurrentDirectory(MAX_PATH, saveDir); |
1456 | 2464 | if (SHGetMalloc(&pMalloc) == NOERROR) { |
2465 | /* | |
2466 | * XXX - MSDN says CoInitialize must have been called before | |
2467 | * SHBrowseForFolder can be used but don't see that called anywhere. | |
2468 | */ | |
1457 | 2469 | pidl = SHBrowseForFolder(&bInfo); |
1458 | 2470 | |
1459 | 2471 | /* |
1505 | 2517 | Tcl_DStringFree(&ds); |
1506 | 2518 | } |
1507 | 2519 | |
1508 | result = TCL_OK; | |
1509 | ||
1510 | if (utfTitle != NULL) { | |
1511 | Tcl_DStringFree(&titleString); | |
1512 | } | |
1513 | ||
1514 | cleanup: | |
1515 | return result; | |
2520 | CleanupOFNOptions(&ofnOpts); | |
2521 | return TCL_OK; | |
1516 | 2522 | } |
1517 | 2523 | |
1518 | 2524 | /* |
158 | 158 | } |
159 | 159 | |
160 | 160 | /* |
161 | * ---------------------------------------------------------------------- | |
162 | * | |
163 | * Win32ErrorObj -- | |
164 | * | |
165 | * Returns a string object containing text from a COM or Win32 error code | |
166 | * | |
167 | * Results: | |
168 | * A Tcl_Obj containing the Win32 error message. | |
169 | * | |
170 | * Side effects: | |
171 | * Removed the error message from the COM threads error object. | |
172 | * | |
173 | * ---------------------------------------------------------------------- | |
174 | */ | |
175 | ||
176 | Tcl_Obj* | |
177 | TkWin32ErrorObj( | |
178 | HRESULT hrError) | |
179 | { | |
180 | LPTSTR lpBuffer = NULL, p = NULL; | |
181 | TCHAR sBuffer[30]; | |
182 | Tcl_Obj* errPtr = NULL; | |
183 | ||
184 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | |
185 | | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError, | |
186 | LANG_NEUTRAL, (LPTSTR)&lpBuffer, 0, NULL); | |
187 | ||
188 | if (lpBuffer == NULL) { | |
189 | lpBuffer = sBuffer; | |
190 | wsprintf(sBuffer, TEXT("Error Code: %08lX"), hrError); | |
191 | } | |
192 | ||
193 | if ((p = _tcsrchr(lpBuffer, TEXT('\r'))) != NULL) { | |
194 | *p = TEXT('\0'); | |
195 | } | |
196 | ||
197 | #ifdef _UNICODE | |
198 | errPtr = Tcl_NewUnicodeObj(lpBuffer, (int)wcslen(lpBuffer)); | |
199 | #else | |
200 | errPtr = Tcl_NewStringObj(lpBuffer, (int)strlen(lpBuffer)); | |
201 | #endif /* _UNICODE */ | |
202 | ||
203 | if (lpBuffer != sBuffer) { | |
204 | LocalFree((HLOCAL)lpBuffer); | |
205 | } | |
206 | ||
207 | return errPtr; | |
208 | } | |
209 | ||
210 | ||
211 | /* | |
161 | 212 | * Local Variables: |
162 | 213 | * mode: c |
163 | 214 | * c-basic-offset: 4 |
198 | 198 | int reqValue); |
199 | 199 | MODULE_SCOPE void TkpWinToplevelDetachWindow(TkWindow *winPtr); |
200 | 200 | MODULE_SCOPE int TkpWmGetState(TkWindow *winPtr); |
201 | ||
202 | /* | |
203 | * Common routines used in Windows implementation | |
204 | */ | |
205 | MODULE_SCOPE Tcl_Obj * TkWin32ErrorObj(HRESULT hrError); | |
206 | ||
201 | 207 | |
202 | 208 | /* |
203 | 209 | * The following functions are not present in old versions of Windows |
76 | 76 | static int Send(LPDISPATCH pdispInterp, Tcl_Interp *interp, |
77 | 77 | int async, ClientData clientData, int objc, |
78 | 78 | Tcl_Obj *const objv[]); |
79 | static Tcl_Obj * Win32ErrorObj(HRESULT hrError); | |
80 | 79 | static void SendTrace(const char *format, ...); |
81 | 80 | static Tcl_EventProc SendEventProc; |
82 | 81 | |
280 | 279 | if (objList != NULL) { |
281 | 280 | Tcl_DecrRefCount(objList); |
282 | 281 | } |
283 | Tcl_SetObjResult(interp, Win32ErrorObj(hr)); | |
282 | Tcl_SetObjResult(interp, TkWin32ErrorObj(hr)); | |
284 | 283 | result = TCL_ERROR; |
285 | 284 | } |
286 | 285 | |
450 | 449 | pROT->lpVtbl->Release(pROT); |
451 | 450 | } |
452 | 451 | if (FAILED(hr) && result == TCL_OK) { |
453 | Tcl_SetObjResult(interp, Win32ErrorObj(hr)); | |
452 | Tcl_SetObjResult(interp, TkWin32ErrorObj(hr)); | |
454 | 453 | result = TCL_ERROR; |
455 | 454 | } |
456 | 455 | return result; |
808 | 807 | /* |
809 | 808 | * ---------------------------------------------------------------------- |
810 | 809 | * |
811 | * Win32ErrorObj -- | |
812 | * | |
813 | * Returns a string object containing text from a COM or Win32 error code | |
814 | * | |
815 | * Results: | |
816 | * A Tcl_Obj containing the Win32 error message. | |
817 | * | |
818 | * Side effects: | |
819 | * Removed the error message from the COM threads error object. | |
820 | * | |
821 | * ---------------------------------------------------------------------- | |
822 | */ | |
823 | ||
824 | static Tcl_Obj* | |
825 | Win32ErrorObj( | |
826 | HRESULT hrError) | |
827 | { | |
828 | LPTSTR lpBuffer = NULL, p = NULL; | |
829 | TCHAR sBuffer[30]; | |
830 | Tcl_Obj* errPtr = NULL; | |
831 | ||
832 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | |
833 | | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError, | |
834 | LANG_NEUTRAL, (LPTSTR)&lpBuffer, 0, NULL); | |
835 | ||
836 | if (lpBuffer == NULL) { | |
837 | lpBuffer = sBuffer; | |
838 | wsprintf(sBuffer, TEXT("Error Code: %08lX"), hrError); | |
839 | } | |
840 | ||
841 | if ((p = _tcsrchr(lpBuffer, TEXT('\r'))) != NULL) { | |
842 | *p = TEXT('\0'); | |
843 | } | |
844 | ||
845 | #ifdef _UNICODE | |
846 | errPtr = Tcl_NewUnicodeObj(lpBuffer, (int)wcslen(lpBuffer)); | |
847 | #else | |
848 | errPtr = Tcl_NewStringObj(lpBuffer, (int)strlen(lpBuffer)); | |
849 | #endif /* _UNICODE */ | |
850 | ||
851 | if (lpBuffer != sBuffer) { | |
852 | LocalFree((HLOCAL)lpBuffer); | |
853 | } | |
854 | ||
855 | return errPtr; | |
856 | } | |
857 | ||
858 | /* | |
859 | * ---------------------------------------------------------------------- | |
860 | * | |
861 | 810 | * TkWinSend_SetExcepInfo -- |
862 | 811 | * |
863 | 812 | * Convert the error information from a Tcl interpreter into a COM |
78 | 78 | return TCL_OK; |
79 | 79 | } |
80 | 80 | |
81 | struct TestFindControlState { | |
82 | int id; | |
83 | HWND control; | |
84 | }; | |
85 | ||
86 | /* Callback for window enumeration - used for TestFindControl */ | |
87 | BOOL CALLBACK TestFindControlCallback( | |
88 | HWND hwnd, | |
89 | LPARAM lParam | |
90 | ) | |
91 | { | |
92 | struct TestFindControlState *fcsPtr = (struct TestFindControlState *)lParam; | |
93 | fcsPtr->control = GetDlgItem(hwnd, fcsPtr->id); | |
94 | /* If we have found the control, return FALSE to stop the enumeration */ | |
95 | return fcsPtr->control == NULL ? TRUE : FALSE; | |
96 | } | |
97 | ||
98 | /* | |
99 | * Finds the descendent control window with the specified ID and returns | |
100 | * its HWND. | |
101 | */ | |
102 | HWND TestFindControl(HWND root, int id) | |
103 | { | |
104 | struct TestFindControlState fcs; | |
105 | ||
106 | fcs.control = GetDlgItem(root, id); | |
107 | if (fcs.control == NULL) { | |
108 | /* Control is not a direct child. Look in descendents */ | |
109 | fcs.id = id; | |
110 | fcs.control = NULL; | |
111 | EnumChildWindows(root, TestFindControlCallback, (LPARAM) &fcs); | |
112 | } | |
113 | return fcs.control; | |
114 | } | |
115 | ||
116 | ||
81 | 117 | /* |
82 | 118 | *---------------------------------------------------------------------- |
83 | 119 | * |
243 | 279 | { |
244 | 280 | HWND hwnd = 0; |
245 | 281 | HWND child = 0; |
282 | HWND control; | |
246 | 283 | int id; |
247 | 284 | char *rest; |
248 | 285 | UINT message; |
249 | 286 | WPARAM wParam; |
250 | 287 | LPARAM lParam; |
288 | LRESULT result; | |
251 | 289 | static const TkStateMap messageMap[] = { |
252 | 290 | {WM_LBUTTONDOWN, "WM_LBUTTONDOWN"}, |
253 | 291 | {WM_LBUTTONUP, "WM_LBUTTONUP"}, |
301 | 339 | return TCL_ERROR; |
302 | 340 | } |
303 | 341 | } |
342 | ||
304 | 343 | message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3])); |
305 | 344 | wParam = 0; |
306 | 345 | lParam = 0; |
317 | 356 | Tcl_DString ds; |
318 | 357 | char buf[256]; |
319 | 358 | |
359 | #if 0 | |
320 | 360 | GetDlgItemTextA(hwnd, id, buf, 256); |
361 | #else | |
362 | control = TestFindControl(hwnd, id); | |
363 | if (control == NULL) { | |
364 | Tcl_SetObjResult(interp, | |
365 | Tcl_ObjPrintf("Could not find control with id %d", id)); | |
366 | return TCL_ERROR; | |
367 | } | |
368 | buf[0] = 0; | |
369 | SendMessageA(control, WM_GETTEXT, (WPARAM)sizeof(buf), | |
370 | (LPARAM) buf); | |
371 | #endif | |
321 | 372 | Tcl_ExternalToUtfDString(NULL, buf, -1, &ds); |
322 | 373 | Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL); |
323 | 374 | Tcl_DStringFree(&ds); |
325 | 376 | } |
326 | 377 | case WM_SETTEXT: { |
327 | 378 | Tcl_DString ds; |
328 | BOOL result; | |
329 | ||
379 | ||
380 | control = TestFindControl(hwnd, id); | |
381 | if (control == NULL) { | |
382 | Tcl_SetObjResult(interp, | |
383 | Tcl_ObjPrintf("Could not find control with id %d", id)); | |
384 | return TCL_ERROR; | |
385 | } | |
330 | 386 | Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[4]), -1, &ds); |
331 | result = SetDlgItemTextA(hwnd, id, Tcl_DStringValue(&ds)); | |
387 | result = SendMessageA(control, WM_SETTEXT, 0, | |
388 | (LPARAM) Tcl_DStringValue(&ds)); | |
332 | 389 | Tcl_DStringFree(&ds); |
333 | 390 | if (result == 0) { |
334 | Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1)); | |
335 | AppendSystemError(interp, GetLastError()); | |
336 | return TCL_ERROR; | |
391 | Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1)); | |
392 | AppendSystemError(interp, GetLastError()); | |
393 | return TCL_ERROR; | |
337 | 394 | } |
338 | 395 | break; |
339 | 396 | } |
381 | 438 | Tcl_DString titleString, classString; |
382 | 439 | HWND hwnd = NULL; |
383 | 440 | int r = TCL_OK; |
441 | DWORD myPid; | |
384 | 442 | |
385 | 443 | Tcl_DStringInit(&classString); |
386 | 444 | Tcl_DStringInit(&titleString); |
394 | 452 | if (objc == 3) { |
395 | 453 | class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString); |
396 | 454 | } |
397 | ||
455 | if (title[0] == 0) | |
456 | title = NULL; | |
457 | #if 0 | |
398 | 458 | hwnd = FindWindow(class, title); |
459 | #else | |
460 | /* We want find a window the belongs to us and not some other process */ | |
461 | hwnd = NULL; | |
462 | myPid = GetCurrentProcessId(); | |
463 | while (1) { | |
464 | DWORD pid, tid; | |
465 | hwnd = FindWindowEx(NULL, hwnd, class, title); | |
466 | if (hwnd == NULL) | |
467 | break; | |
468 | tid = GetWindowThreadProcessId(hwnd, &pid); | |
469 | if (tid == 0) { | |
470 | /* Window has gone */ | |
471 | hwnd = NULL; | |
472 | break; | |
473 | } | |
474 | if (pid == myPid) | |
475 | break; /* Found it */ | |
476 | } | |
477 | ||
478 | #endif | |
399 | 479 | |
400 | 480 | if (hwnd == NULL) { |
401 | 481 | Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1)); |
19 | 19 | </trustInfo> |
20 | 20 | <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> |
21 | 21 | <application> |
22 | <!-- Windows 10 --> | |
23 | <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> | |
22 | 24 | <!-- Windows 8.1 --> |
23 | 25 | <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> |
24 | 26 | <!-- Windows 8 --> |