Codebase list tk8.6 / 06f88b9
New upstream version 8.6.3+dfsg Sergei Golovan authored 9 years ago Sergei Golovan committed 6 years ago
39 changed file(s) with 1917 addition(s) and 597 deletion(s). Raw diff Collapse all Expand all
00 README: Tk
1 This is the Tk 8.6.2 source distribution.
1 This is the Tk 8.6.3 source distribution.
22 http://sourceforge.net/projects/tcl/files/Tcl/
33 You can get any source release of Tk from the URL above.
44
71207120 2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper)
71217121
71227122 --- 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
1818 .TP
1919 \fB\-initialdir\fR \fIdirname\fR
2020 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
2326 parameter specifies a relative path, the return value will convert the
2427 relative path to an absolute path.
2528 .TP
6464 \fB\-initialdir\fR \fIdirectory\fR
6565 .
6666 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
6972 parameter specifies a relative path, the return value will convert the
7073 relative path to an absolute path.
7174 .TP
7474 #define TK_MAJOR_VERSION 8
7575 #define TK_MINOR_VERSION 6
7676 #define TK_RELEASE_LEVEL TCL_FINAL_RELEASE
77 #define TK_RELEASE_SERIAL 2
77 #define TK_RELEASE_SERIAL 3
7878
7979 #define TK_VERSION "8.6"
80 #define TK_PATCH_LEVEL "8.6.2"
80 #define TK_PATCH_LEVEL "8.6.3"
8181
8282 /*
8383 * A special definition used to allow this header file to be included from
14181418 }
14191419 }
14201420 UnhookCascadeEntry(mePtr);
1421 menuRefPtr = mePtr->childMenuRefPtr;
14211422 if (menuRefPtr != NULL) {
14221423 if (menuRefPtr->menuPtr == destroyThis) {
14231424 menuRefPtr->menuPtr = NULL;
14241425 }
1425 if (destroyThis != NULL) {
1426 TkDestroyMenu(destroyThis);
1427 }
1426 }
1427 if (destroyThis != NULL) {
1428 TkDestroyMenu(destroyThis);
14281429 }
14291430 } else {
14301431 UnhookCascadeEntry(mePtr);
799799 */
800800
801801 numDigits = scalePtr->digits;
802 if (numDigits > TCL_MAX_PREC) {
803 numDigits = 0;
804 }
802805 if (numDigits <= 0) {
803806 if (scalePtr->resolution > 0) {
804807 /*
879882 ComputeScaleGeometry(
880883 register TkScale *scalePtr) /* Information about widget. */
881884 {
882 char valueString[PRINT_CHARS];
885 char valueString[TCL_DOUBLE_SPACE];
883886 int tmp, valuePixels, x, y, extraSpace;
884887 Tk_FontMetrics fm;
885888
12951298 register TkScale *scalePtr) /* Info about widget. */
12961299 {
12971300 if (scalePtr->varNamePtr != NULL) {
1298 char string[PRINT_CHARS];
1301 char string[TCL_DOUBLE_SPACE];
12991302
13001303 sprintf(string, scalePtr->format, scalePtr->value);
13011304 scalePtr->flags |= SETTING_VAR;
214214 #define SPACING 2
215215
216216 /*
217 * How many characters of space to provide when formatting the scale's value:
218 */
219
220 #define PRINT_CHARS 150
221
222 /*
223217 * Declaration of procedures used in the implementation of the scale widget.
224218 */
225219
168168 return TCL_ERROR;
169169 }
170170 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 }
171179 for (i = 4; i < objc; i += 2) {
172180 if (TkTextGetObjIndex(interp, textPtr, objv[i],
173181 &index1) != TCL_OK) {
+0
-114
library/images/lamp.svg less more
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>
222222 set inc [$w cget -resolution]
223223 }
224224 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 }
226232 }
227233 $w set [expr {[$w get] + $inc}]
228234
1212 # Insist on running with compatible version of Tcl
1313 package require Tcl 8.6
1414 # 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
1616
1717 # Create a ::tk namespace
1818 namespace eval ::tk {
13451345 TK_VERSION=8.6
13461346 TK_MAJOR_VERSION=8
13471347 TK_MINOR_VERSION=6
1348 TK_PATCH_LEVEL=".2"
1348 TK_PATCH_LEVEL=".3"
13491349 VERSION=${TK_VERSION}
13501350 LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
13511351
48594859 LD_SEARCH_FLAGS=""
48604860 TCL_NEEDS_EXP_FILE=1
48614861 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"
48644863 echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
48654864 echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
48664865 if test "${ac_cv_cygwin+set}" = set; then
55265525 LDFLAGS=""
55275526 ;;
55285527 *)
5529 SHLIB_CFLAGS="-fPIC"
5528 case "$arch" in
5529 alpha|sparc64)
5530 SHLIB_CFLAGS="-fPIC"
5531 ;;
5532 *)
5533 SHLIB_CFLAGS="-fpic"
5534 ;;
5535 esac
55305536 SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
55315537 SHLIB_SUFFIX=".so"
55325538 DL_OBJS="tclLoadDl.o"
55935599 # This configuration from FreeBSD Ports.
55945600 SHLIB_CFLAGS="-fPIC"
55955601 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,\$@"
55985603 SHLIB_SUFFIX=".so"
55995604 DL_OBJS="tclLoadDl.o"
56005605 DL_LIBS=""
68326837 if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then
68336838
68346839 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}'
68366841 if test "${SHLIB_SUFFIX}" = ".dll"; then
68376842
68386843 INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
6565 if ( y > parent_height - 20 || y + widget_height < 0 ) {
6666 return;
6767 }
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 }
6876 }
6977 [super drawRect:dirtyRect];
7078 }
188196 [macButtonPtr->button setTag:(NSInteger)-1];
189197
190198 TkMacOSXMakeCollectableAndRelease(macButtonPtr->button);
191 TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
199 TkMacOSXMakeCollectableAndRelease(macButtonPtr->image);
192200 TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
193201 TkMacOSXMakeCollectableAndRelease(macButtonPtr->tristateImage);
194202 }
462462 * Color image
463463 */
464464
465 CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
465 CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
466466
467467 bitsPerComponent = 8;
468468 bitsPerPixel = 32;
235235 if (!uname(&name)) {
236236 tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
237237 }
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 &&
239243 tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) {
240244 Tcl_Panic("Mac OS X 10.%d or later required !",
241245 (MAC_OS_X_VERSION_MIN_REQUIRED/10)-100);
242246 }
247
243248
244249 #ifdef TK_FRAMEWORK
245250 /*
144144 Tk_Window tkwin = scalePtr->tkwin;
145145 Tcl_Interp *interp = scalePtr->interp;
146146 int result;
147 char string[PRINT_CHARS];
147 char string[TCL_DOUBLE_SPACE];
148148 MacScale *macScalePtr = (MacScale *) clientData;
149149 Rect r;
150150 WindowRef windowRef;
2020 #endif
2121 */
2222
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
2384 /*
2485 * Declaration of Mac specific scrollbar structure.
2586 */
2687
2788 typedef struct MacScrollbar {
2889 TkScrollbar info;
29 NSScroller *scroller;
90 TkNSScroller *scroller;
3091 int variant;
3192 } MacScrollbar;
3293
48109 static void UpdateScrollbarMetrics(void);
49110 static void ScrollbarEventProc(ClientData clientData,
50111 XEvent *eventPtr);
112
51113
52114 /*
53115 * The class procedure table for the scrollbar widget.
65127 #define NSAppleAquaScrollBarVariantChanged @"AppleAquaScrollBarVariantChanged"
66128
67129 @implementation TKApplication(TKScrlbr)
68 - (void) tkScroller: (NSScroller *) scroller
130 - (void) tkScroller: (TkNSScroller *) scroller
69131 {
70132 NSScrollerPart hitPart = [scroller hitPart];
71133 TkScrollbar *scrollPtr = (TkScrollbar *)[scroller tag];
253315 TkScrollbar *scrollPtr)
254316 {
255317 MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
256 NSScroller *scroller = macScrollPtr->scroller;
257 [scroller setTag:(NSInteger)0];
318 TkNSScroller *scroller = macScrollPtr->scroller;
319 [scroller setTag:(NSInteger)-1];
258320
259321 TkMacOSXMakeCollectableAndRelease(macScrollPtr->scroller);
260322 }
283345 {
284346 TkScrollbar *scrollPtr = clientData;
285347 MacScrollbar *macScrollPtr = clientData;
286 NSScroller *scroller = macScrollPtr->scroller;
348 TkNSScroller *scroller = macScrollPtr->scroller;
287349 Tk_Window tkwin = scrollPtr->tkwin;
288350 TkWindow *winPtr = (TkWindow *) tkwin;
289351 MacDrawable *macWin = (MacDrawable *) winPtr->window;
356418 [scroller setEnabled:(knobProportion < 1.0 &&
357419 (scrollPtr->vertical ? frame.size.height : frame.size.width) >
358420 metrics[macScrollPtr->variant].minHeight)];
421 // [scroller setEnabled: YES];
359422 [scroller setDoubleValue:scrollPtr->firstFraction / (1.0 - knobProportion)];
360423 [scroller setKnobProportion:knobProportion];
361424 [scroller displayRectIgnoringOpacity:[scroller bounds]];
362425 TkMacOSXRestoreDrawingContext(&dc);
363 #ifdef TK_MAC_DEBUG_SCROLLBAR
426 #ifdef TK_MAC_DEBUG_SCROLLBAR
364427 TKLog(@"scroller %s frame %@ width %d height %d",
365428 ((TkWindow *)scrollPtr->tkwin)->pathName, NSStringFromRect(frame),
366429 Tk_Width(tkwin), Tk_Height(tkwin));
367 #endif
430 #endif
368431 }
369432
370433 /*
392455 * changed. */
393456 {
394457 MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
395 NSScroller *scroller = macScrollPtr->scroller;
458 TkNSScroller *scroller = macScrollPtr->scroller;
396459 int width, height, variant, fieldLength;
397460
398461 if (scrollPtr->highlightWidth < 0) {
420483 }
421484 if (!scroller) {
422485 if ((width > height) ^ !scrollPtr->vertical) {
423 /* -[NSScroller initWithFrame:] determines horizonalness for the
486 /* -[NSScroller initWithFrame:] determines horizontalness for the
424487 * lifetime of the scroller via isHoriz = (width > height) */
425488 if (scrollPtr->vertical) {
426489 width = height;
431494 width = 2;
432495 }
433496 }
434 scroller = [[NSScroller alloc] initWithFrame:
497 scroller = [[TkNSScroller alloc] initWithFrame:
435498 NSMakeRect(0, 0, width, height)];
436499 macScrollPtr->scroller = TkMacOSXMakeUncollectable(scroller);
437500 [scroller setAction:@selector(tkScroller:)];
552615 /* Scrollbar widget record. */
553616 int x, int y) /* Coordinates within scrollPtr's window. */
554617 {
555 NSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
618 TkNSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
556619 MacDrawable *macWin = (MacDrawable *)
557620 ((TkWindow *) scrollPtr->tkwin)->window;
558621 NSView *view = TkMacOSXDrawableView(macWin);
613676 TkScrollbarEventProc(clientData, eventPtr);
614677 }
615678 }
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
616718
617719 /*
618720 * Local Variables:
355355 event.xexpose.width = damageBounds.size.width;
356356 event.xexpose.height = damageBounds.size.height;
357357 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,
361362 event.xexpose.y, event.xexpose.width, event.xexpose.height);
362 #endif
363 #endif
363364
364365 /*
365366 * Generate updates for the children of this window
386387 /*
387388 * TODO: Here we should handle out of process embedding.
388389 */
389 }
390 }
390391
391392 return 1;
392393 }
767768 @interface TKContentView(TKWindowEvent)
768769 - (void) drawRect: (NSRect) rect;
769770 - (void) generateExposeEvents: (HIMutableShapeRef) shape;
771 - (void) viewDidEndLiveResize;
772 - (void) viewWillDraw;
770773 - (BOOL) isOpaque;
771774 - (BOOL) wantsDefaultClipping;
772775 - (BOOL) acceptsFirstResponder;
776779 @implementation TKContentView
777780 @end
778781
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.*/
779793 static Tk_RestrictAction
780794 ExposeRestrictProc(
781795 ClientData arg,
784798 return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg)
785799 ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
786800 }
801
787802
788803 @implementation TKContentView(TKWindowEvent)
789804
799814 NSRectFillListUsingOperation(rectsBeingDrawn, rectsBeingDrawnCount,
800815 NSCompositeSourceOver);
801816 #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;
802822
803823 CGFloat height = [self bounds].size.height;
804824 HIMutableShapeRef drawShape = HIShapeCreateMutable();
819839 nil]];
820840 }
821841 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 }
823857
824858 - (void) generateExposeEvents: (HIMutableShapeRef) shape
825859 {
860
826861 TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
827862 unsigned long serial;
828863 CGRect updateBounds;
829864
830865 if (!winPtr) {
831 return;
832 }
866 return;
867 }
868
833869 HIShapeGetBounds(shape, &updateBounds);
834870 serial = LastKnownRequestProcessed(Tk_Display(winPtr));
835871 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.*/
860900 - (void) tkToolbarButton: (id) sender
861901 {
862902 #ifdef TK_MAC_DEBUG_EVENTS
884924 Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
885925 }
886926
887 #ifdef TK_MAC_DEBUG_DRAWING
888927 - (void) setFrameSize: (NSSize) newSize
889928 {
890 TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
891 NSStringFromSize(newSize));
892929 [super setFrameSize:newSize];
893930 }
894931
895932 - (void) setNeedsDisplayInRect: (NSRect) invalidRect
896933 {
897 TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
898 NSStringFromRect(invalidRect));
899934 [super setNeedsDisplayInRect:invalidRect];
900935 }
901 #endif
902936
903937 - (BOOL) isOpaque
904938 {
293293 * TP30000359-TPXREF116>
294294 */
295295
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;
298299
299300 static void TabElementSize(
300301 void *clientData, void *elementRecord, Tk_Window tkwin,
301302 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
302303 {
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
304312 }
305313
306314 static void TabElementDraw(
872872 .c find enclosed 99 99 [expr $x2 + 1] [expr $y2 + 1]
873873 } -cleanup {
874874 destroy .c
875 unset -nocomplain bbox x2 y2
875876 } -result 1
876877
877878 test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup {
1111 tcltest::loadTestedCommands
1212
1313
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
1533 deleteWindows
1634 # Toplevel used (in some tests) of the whole file
1735 toplevel .t
160178 font delete xyz
161179 } -result xyz
162180 test font-5.5 {font command: configure: get one option} -setup {
163 catch {eval font delete [font names]}
181 clearnondefaultfonts
164182 } -body {
165183 # (objc == 4) so objPtr = objv[3]
166184 font create xyz -family xyz
167185 font configure xyz -family
168 font names
186 getnondefaultfonts
169187 } -cleanup {
170188 font delete xyz
171189 } -result xyz
191209
192210
193211 test font-6.1 {font command: create: make up name} -setup {
194 catch {eval font delete [font names]}
212 clearnondefaultfonts
195213 } -body {
196214 # (objc < 3) so name = NULL
197215 font create
198 font names
216 getnondefaultfonts
199217 } -cleanup {
200218 font delete font1
201219 } -result {font1}
202220 test font-6.2 {font command: create: name specified} -setup {
203 catch {eval font delete [font names]}
221 clearnondefaultfonts
204222 } -body {
205223 # not (objc < 3)
206224 font create xyz
207 font names
225 getnondefaultfonts
208226 } -cleanup {
209227 font delete xyz
210228 } -result {xyz}
211229 test font-6.3 {font command: create: name not really specified} -setup {
212 catch {eval font delete [font names]}
230 clearnondefaultfonts
213231 } -body {
214232 # (name[0] == '-') so name = NULL
215233 font create -family xyz
216 font names
234 getnondefaultfonts
217235 } -cleanup {
218236 font delete font1
219237 } -result {font1}
220238 test font-6.4 {font command: create: generate name} -setup {
221 catch {eval font delete [font names]}
222239 } -body {
223240 # (name == NULL)
224241 font create -family one
228245 font create -family four
229246 font configure font2 -family
230247 } -cleanup {
231 catch {eval font delete [font names]}
248 font delete font1 font2 font3
232249 } -result {four}
233250 test font-6.5 {font command: create: bad option creating new font} -setup {
234251 catch {font delete xyz}
237254 font create xyz -xyz times
238255 } -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
239256 test font-6.6 {font command: create: bad option creating new font} -setup {
240 catch {eval font delete [font names]}
257 clearnondefaultfonts
241258 } -body {
242259 # name was not specified so skip = 2
243260 font create -xyz times
257274 font delete
258275 } -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"}
259276 test font-7.2 {font command: delete: loop test} -setup {
260 catch {eval font delete [font names]}
277 clearnondefaultfonts
261278 set x {}
262279 } -body {
263280 # for (i = 2; i < objc; i++)
266283 font create c -underline 1
267284 font create d -underline 1
268285 font create e -underline 1
269 lappend x [lsort [font names]]
286 lappend x [lsort [getnondefaultfonts]]
270287 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
274291 } -result {{a b c d e} d}
275292 test font-7.3 {font command: delete: loop test} -setup {
276 catch {eval font delete [font names]}
293 clearnondefaultfonts
277294 set x {}
278295 } -body {
279296 # (namedHashPtr == NULL) in middle of loop
282299 font create c -underline 1
283300 font create d -underline 1
284301 font create e -underline 1
285 lappend x [lsort [font names]]
302 lappend x [lsort [getnondefaultfonts]]
286303 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
290307 } -result {{a b c d e} {b c e}}
291308 test font-7.4 {font command: delete: non-existent} -setup {
292309 catch {font delete xyz}
433450 font names xyz
434451 } -returnCodes error -result {wrong # args: should be "font names"}
435452 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
439456 } -result {}
440457 test font-11.3 {font command: names: loop test: one pass} -setup {
441 catch {eval font delete [font names]}
458 clearnondefaultfonts
442459 } -body {
443460 font create
444 font names
461 getnondefaultfonts
445462 } -result {font1}
446463 test font-11.4 {font command: names: loop test: multiple passes} -setup {
447 catch {eval font delete [font names]}
464 clearnondefaultfonts
448465 } -body {
449466 font create xyz
450467 font create abc
451468 font create def
452 lsort [font names]
453 } -cleanup {
454 catch {eval font delete [font names]}
469 lsort [getnondefaultfonts]
470 } -cleanup {
471 clearnondefaultfonts
455472 } -result {abc def xyz}
456473 test font-11.5 {font command: names: skip deletePending fonts} -setup {
457474 destroy .t.f
458 catch {eval font delete [font names]}
475 clearnondefaultfonts
459476 pack [label .t.f]
460477 update
461478 set x {}
463480 # (nfPtr->deletePending == 0)
464481 font create xyz
465482 font create abc
466 lappend x [lsort [font names]]
483 lappend x [lsort [getnondefaultfonts]]
467484 .t.f config -font xyz
468485 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
472489 } -result {{abc xyz} abc}
473490
474491
508525 set x {}
509526 } -body {
510527 # not (new == 0)
511 lappend x [font names]
528 lappend x [getnondefaultfonts]
512529 font create xyz
513 lappend x [font names]
530 lappend x [getnondefaultfonts]
514531 } -cleanup {
515532 font delete xyz
516533 } -result {{} xyz}
645662 win
646663 } -setup {
647664 destroy .t.f
648 catch {eval font delete [font names]}
665 clearnondefaultfonts
649666 pack [label .t.f]
650667 update
651668 } -body {
751768 } -result {-family fixed}
752769 test font-17.4 {Tk_FreeFont procedure: named font} -setup {
753770 destroy .t.f
754 catch {eval font delete [font names]}
771 clearnondefaultfonts
755772 pack [label .t.f]
756773 update
757774 } -body {
759776 font create xyz
760777 .t.f config -font xyz
761778 destroy .t.f
762 font names
779 getnondefaultfonts
763780 } -result {xyz}
764781 test font-17.5 {Tk_FreeFont procedure: named font} -setup {
765782 destroy .t.f
687687 .s set 1001.23456789
688688 .s get
689689 } -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}
690695 destroy .s
691696
692697
13561361 } -result {0 {}}
13571362
13581363
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
13591398 option clear
13601399
13611400 # cleanup
2626
2727 # Create entries in the option database to be sure that geometry options
2828 # 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
3233
3334 # The frame .f is needed to make sure that the overall window is always
3435 # fairly wide, even if the text window is very narrow. This is needed
33653366 .t2.t window create 1.1 -window .t2.t.f
33663367 update
33673368 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]]
33693370 test textDisp-29.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
33703371 catch {destroy .t2}
33713372 toplevel .t2
33783379 .t2.t insert end 123
33793380 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
33803381 .t2.t window create 1.1 -window .t2.t.f
3382 update
33813383 .t2.t xview scroll 1 unit
33823384 update
33833385 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]]
33853387 test textDisp-29.2.1 {miscellaneous: lines wrap but are still too long} {textfonts} {
33863388 catch {destroy .t2}
33873389 toplevel .t2
33933395 pack .t2.s -side bottom -fill x
33943396 .t2.t insert end 1\n
33953397 .t2.t insert end [string repeat "abc" 30]
3398 update
33963399 .t2.t xview scroll 5 unit
33973400 update
33983401 .t2.t xview
34093412 .t2.t insert end 123
34103413 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
34113414 .t2.t window create 1.1 -window .t2.t.f
3415 update
34123416 .t2.t xview scroll 2 unit
34133417 update
34143418 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}] {}]
34163420 test textDisp-29.2.3 {miscellaneous: lines wrap but are still too long} {textfonts} {
34173421 catch {destroy .t2}
34183422 toplevel .t2
34253429 .t2.t insert end 123
34263430 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
34273431 .t2.t window create 1.1 -window .t2.t.f
3432 update
34283433 .t2.t xview scroll 7 pixels
34293434 update
34303435 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]]
34323437 test textDisp-29.2.4 {miscellaneous: lines wrap but are still too long} {textfonts} {
34333438 catch {destroy .t2}
34343439 toplevel .t2
34413446 .t2.t insert end 123
34423447 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
34433448 .t2.t window create 1.1 -window .t2.t.f
3449 update
34443450 .t2.t xview scroll 17 pixels
34453451 update
34463452 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}] {}]
34483454 test textDisp-29.2.5 {miscellaneous: can show last character} {
34493455 catch {destroy .t2}
34503456 toplevel .t2
2121 && (([testwinlocale] & 0xff) == 9)
2222 }]
2323
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
2440 proc start {arg} {
2541 set ::tk_dialog 0
2642 set ::iter_after 0
43 set ::dialogclass "#32770"
2744
2845 after 1 $arg
2946 }
3350 set ::dialogresult {}
3451 set ::testfont {}
3552
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
3757 vwait ::dialogresult
3858 return $::dialogresult
3959 }
4060
4161 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}
4571 return
4672 }
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 }
4982 }
5083 uplevel #0 {set dialogresult [eval $command]}
5184 }
204237 test winDialog-5.3 {GetFileName: many arguments} -constraints {
205238 nt testwinevent
206239 } -body {
207 start {tk_getOpenFile -initialdir c:/ -parent . -title test -initialfile foo}
240 start {tk_getOpenFile -initialdir [initialdir] -parent . -title test -initialfile foo}
208241 then {
209242 Click cancel
210243 }
230263 test winDialog-5.7 {GetFileName: extension begins with .} -constraints {
231264 nt testwinevent
232265 } -body {
233 # if (string[0] == '.') {
234 # string++;
235 # }
236
237266 start {set x [tk_getSaveFile -defaultextension .foo -title Save]}
238267 set msg {}
239268 then {
240 if {[catch {SetText 0x47C bar} msg]} {
269 if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} {
241270 Click cancel
242271 } else {
243272 Click ok
244273 }
245274 }
246 string totitle $x$msg
275 set x "[file tail $x]$msg"
247276 } -cleanup {
248277 unset msg
249 } -result [string totitle [file join [pwd] bar.foo]]
278 } -result bar.foo
250279 test winDialog-5.8 {GetFileName: extension doesn't begin with .} -constraints {
251280 nt testwinevent
252281 } -body {
253282 start {set x [tk_getSaveFile -defaultextension foo -title Save]}
254283 set msg {}
255284 then {
256 if {[catch {SetText 0x47C bar} msg]} {
285 if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} {
257286 Click cancel
258287 } else {
259288 Click ok
260289 }
261290 }
262 string totitle $x$msg
291 set x "[file tail $x]$msg"
263292 } -cleanup {
264293 unset msg
265 } -result [string totitle [file join [pwd] bar.foo]]
294 } -result bar.foo
266295 test winDialog-5.9 {GetFileName: file types} -constraints {
267296 nt testwinevent
268297 } -body {
269 # case FILE_TYPES:
270
298 # case FILE_TYPES:
299
271300 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
278317 test winDialog-5.10 {GetFileName: file types: MakeFilter() fails} -constraints {
279318 nt
280319 } -body {
282321
283322 tk_getSaveFile -filetypes {{"foo" .foo FOO}}
284323 } -returnCodes error -result {bad Macintosh file type "FOO"}
285 if {[info exists ::env(TEMP)]} {
286324 test winDialog-5.11 {GetFileName: initial directory} -constraints {
287325 nt testwinevent
288326 } -body {
289327 # case FILE_INITDIR:
290
328 unset -nocomplain x
291329 start {set x [tk_getSaveFile \
292 -initialdir [file normalize $::env(TEMP)] \
330 -initialdir [initialdir] \
293331 -initialfile "12x 455" -title Foo]}
294332 then {
295333 Click ok
296334 }
297335 return $x
298 } -result [file join [file normalize $::env(TEMP)] "12x 455"]
299 }
336 } -result [file join [initialdir] "12x 455"]
300337 test winDialog-5.12 {GetFileName: initial directory: Tcl_TranslateFilename()} -constraints {
301338 nt
302339 } -body {
313350 then {
314351 Click ok
315352 }
316 string totitle $x
317 } -result [string totitle [file join [pwd] "12x 456"]]
353 file tail $x
354 } -result "12x 456"
318355 test winDialog-5.14 {GetFileName: initial file: Tcl_TranslateFileName()} -constraints {
319356 nt
320357 } -body {
321358 # if (Tcl_TranslateFileName(interp, string, &ds) == NULL)
322359 tk_getOpenFile -initialfile ~12x/455
323360 } -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 }
337378 test winDialog-5.16 {GetFileName: parent} -constraints {
338379 nt
339380 } -body {
357398 Click cancel
358399 }
359400 } -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 }
372429 test winDialog-5.19 {GetFileName: parent HWND doesn't yet exist} -constraints {
373430 nt
374431 } -setup {
418475 }
419476 return $x
420477 } -result {&Save}
421 if {[info exists ::env(TEMP)]} {
422478 test winDialog-5.23 {GetFileName: convert \ to /} -constraints {
423479 nt testwinevent
424480 } -body {
425481 set msg {}
426482 start {set x [tk_getSaveFile -title Back]}
427483 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]} {
430486 Click cancel
431487 } else {
432488 Click ok
435491 return $x$msg
436492 } -cleanup {
437493 unset msg
438 } -result [file join [file normalize $::env(TEMP)] "12x 457"]
439 }
494 } -result [file join [initialdir] "12x 457"]
440495 test winDialog-5.24 {GetFileName: file types: MakeFilter() succeeds} -constraints {
441496 nt
442497 } -body {
491546 nt testwinevent
492547 } -body {
493548 start {
494 tk_chooseDirectory -initialdir c:/ -mustexist 1 -parent . -title test
549 tk_chooseDirectory -initialdir [initialdir] -mustexist 1 -parent . -title test
495550 }
496551 then {
497552 Click cancel
520575 } -body {
521576 # case DIR_INITIAL:
522577
523 start {set x [tk_chooseDirectory -initialdir c:/ -title Foo]}
578 start {set x [tk_chooseDirectory -initialdir [initialdir] -title Foo]}
524579 then {
525580 Click ok
526581 }
527582 string tolower [set x]
528 } -result {c:/}
583 } -result [string tolower [initialdir]]
529584 test winDialog-9.8 {Tk_ChooseDirectoryObjCmd: initial directory: Tcl_TranslateFilename()} -constraints {
530585 nt
531586 } -body {
13371337 TK_VERSION=8.6
13381338 TK_MAJOR_VERSION=8
13391339 TK_MINOR_VERSION=6
1340 TK_PATCH_LEVEL=".2"
1340 TK_PATCH_LEVEL=".3"
13411341 VERSION=${TK_VERSION}
13421342 LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
13431343
48514851 LD_SEARCH_FLAGS=""
48524852 TCL_NEEDS_EXP_FILE=1
48534853 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"
48564855 echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
48574856 echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
48584857 if test "${ac_cv_cygwin+set}" = set; then
55185517 LDFLAGS=""
55195518 ;;
55205519 *)
5521 SHLIB_CFLAGS="-fPIC"
5520 case "$arch" in
5521 alpha|sparc64)
5522 SHLIB_CFLAGS="-fPIC"
5523 ;;
5524 *)
5525 SHLIB_CFLAGS="-fpic"
5526 ;;
5527 esac
55225528 SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
55235529 SHLIB_SUFFIX=".so"
55245530 DL_OBJS="tclLoadDl.o"
55855591 # This configuration from FreeBSD Ports.
55865592 SHLIB_CFLAGS="-fPIC"
55875593 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,\$@"
55905595 SHLIB_SUFFIX=".so"
55915596 DL_OBJS="tclLoadDl.o"
55925597 DL_LIBS=""
68246829 if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then
68256830
68266831 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}'
68286833 if test "${SHLIB_SUFFIX}" = ".dll"; then
68296834
68306835 INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
2424 TK_VERSION=8.6
2525 TK_MAJOR_VERSION=8
2626 TK_MINOR_VERSION=6
27 TK_PATCH_LEVEL=".2"
27 TK_PATCH_LEVEL=".3"
2828 VERSION=${TK_VERSION}
2929 LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
3030
12161216 LD_SEARCH_FLAGS=""
12171217 TCL_NEEDS_EXP_FILE=1
12181218 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"
12211220 AC_CACHE_CHECK(for Cygwin version of gcc,
12221221 ac_cv_cygwin,
12231222 AC_TRY_COMPILE([
14751474 LDFLAGS=""
14761475 ;;
14771476 *)
1478 SHLIB_CFLAGS="-fPIC"
1477 case "$arch" in
1478 alpha|sparc64)
1479 SHLIB_CFLAGS="-fPIC"
1480 ;;
1481 *)
1482 SHLIB_CFLAGS="-fpic"
1483 ;;
1484 esac
14791485 SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
14801486 SHLIB_SUFFIX=".so"
14811487 DL_OBJS="tclLoadDl.o"
15301536 # This configuration from FreeBSD Ports.
15311537 SHLIB_CFLAGS="-fPIC"
15321538 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,\$[@]"
15351540 SHLIB_SUFFIX=".so"
15361541 DL_OBJS="tclLoadDl.o"
15371542 DL_LIBS=""
20422047
20432048 AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
20442049 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}'
20462051 AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
20472052 INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
20482053 DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
33
44 Name: tk
55 Summary: Tk graphical toolkit for the Tcl scripting language.
6 Version: 8.6.2
6 Version: 8.6.3
77 Release: 2
88 License: BSD
99 Group: Development/Languages
261261 {
262262 register Tk_Window tkwin = scalePtr->tkwin;
263263 int y, width, length;
264 char valueString[PRINT_CHARS];
264 char valueString[TCL_DOUBLE_SPACE];
265265 Tk_FontMetrics fm;
266266
267267 Tk_GetFontMetrics(scalePtr->tkfont, &fm);
340340 */
341341
342342 if (tickInterval != 0) {
343 char valueString[PRINT_CHARS];
343 char valueString[TCL_DOUBLE_SPACE];
344344 double ticks, maxTicks;
345345
346346 /*
477477 {
478478 register Tk_Window tkwin = scalePtr->tkwin;
479479 int x, y, length, width;
480 char valueString[PRINT_CHARS];
480 char valueString[TCL_DOUBLE_SPACE];
481481 Tk_FontMetrics fm;
482482
483483 x = TkScaleValueToPixel(scalePtr, value);
534534 Tcl_Interp *interp = scalePtr->interp;
535535 Pixmap pixmap;
536536 int result;
537 char string[PRINT_CHARS];
537 char string[TCL_DOUBLE_SPACE];
538538 XRectangle drawnArea;
539539 Tcl_DString buf;
540540
13111311 TK_VERSION=8.6
13121312 TK_MAJOR_VERSION=8
13131313 TK_MINOR_VERSION=6
1314 TK_PATCH_LEVEL=".2"
1314 TK_PATCH_LEVEL=".3"
13151315 VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
13161316
13171317 #------------------------------------------------------------------------
1313 TK_VERSION=8.6
1414 TK_MAJOR_VERSION=8
1515 TK_MINOR_VERSION=6
16 TK_PATCH_LEVEL=".2"
16 TK_PATCH_LEVEL=".3"
1717 VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
1818
1919 #------------------------------------------------------------------------
12641264 return 0;
12651265 }
12661266 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 }
12821290 }
12831291
12841292 default:
1313 #include "tkFont.h"
1414
1515 #include <commdlg.h> /* includes common dialog functionality */
16 #ifdef _MSC_VER
17 # pragma comment (lib, "comdlg32.lib")
18 #endif
1916 #include <dlgs.h> /* includes common dialog template defines */
2017 #include <cderr.h> /* includes the common dialog error codes */
2118
2219 #include <shlobj.h> /* includes SHBrowseForFolder */
20 #include <shobjidl.h>
21
2322 #ifdef _MSC_VER
2423 # pragma comment (lib, "shell32.lib")
24 # pragma comment (lib, "comdlg32.lib")
25 # pragma comment (lib, "uuid.lib")
2526 #endif
2627
2728 /* These needed for compilation with VC++ 5.2 */
29 /* XXX - remove these since need at least VC 6 */
2830 #ifndef BIF_EDITBOX
2931 #define BIF_EDITBOX 0x10
3032 #endif
3335 #define BIF_VALIDATE 0x0020
3436 #endif
3537
38 /* This "new" dialog style is now actually the "old" dialog style post-Vista */
3639 #ifndef BIF_NEWDIALOGSTYLE
3740 #define BIF_NEWDIALOGSTYLE 0x0040
3841 #endif
5659 HHOOK hMsgBoxHook; /* Hook proc for tk_messageBox and the */
5760 HICON hSmallIcon; /* icons used by a parent to be used in */
5861 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 */
5966 } ThreadSpecificData;
6067 static Tcl_ThreadDataKey dataKey;
6168
158165 } OFNData;
159166
160167 /*
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 /*
161565 * Definitions of functions used only in this file.
162566 */
163567
165569 LPARAM wParam, LPARAM lParam);
166570 static UINT CALLBACK ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam,
167571 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);
168580 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);
171587 static int MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr,
172588 Tcl_DString *dsPtr, Tcl_Obj *initialPtr,
173589 int *indexPtr);
177593 static void SetTkDialog(ClientData clientData);
178594 static const char *ConvertExternalFilename(TCHAR *filename,
179595 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
180656
181657 /*
182658 *-------------------------------------------------------------------------
486962 int objc, /* Number of arguments. */
487963 Tcl_Obj *const objv[]) /* Argument objects. */
488964 {
489 return GetFileName(clientData, interp, objc, objv, 1);
965 return GetFileName(clientData, interp, objc, objv, OFN_FILE_OPEN);
490966 }
491967
492968 /*
513989 int objc, /* Number of arguments. */
514990 Tcl_Obj *const objv[]) /* Argument objects. */
515991 {
516 return GetFileName(clientData, interp, objc, objv, 0);
992 return GetFileName(clientData, interp, objc, objv, OFN_FILE_SAVE);
517993 }
518994
519995 /*
520996 *----------------------------------------------------------------------
521997 *
522 * GetFileName --
523 *
524 * Calls GetOpenFileName() or GetSaveFileName().
998 * CleanupOFNOptions --
999 *
1000 * Cleans up any storage allocated by ParseOFNOptions
5251001 *
5261002 * Results:
527 * See user documentation.
1003 * None.
5281004 *
5291005 * Side effects:
530 * See user documentation.
531 *
1006 * Releases resources held by *optsPtr
5321007 *----------------------------------------------------------------------
5331008 */
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 */
5341031
5351032 static int
536 GetFileName(
1033 ParseOFNOptions(
5371034 ClientData clientData, /* Main window associated with interpreter. */
5381035 Tcl_Interp *interp, /* Current interpreter. */
5391036 int objc, /* Number of arguments. */
5401037 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 */
5431040 {
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;
5581043 enum options {
5591044 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,
5611047 };
5621048 struct Options {
5631049 const char *name;
5851071 {"-typevariable", FILE_TYPEVARIABLE},
5861072 {NULL, FILE_DEFAULT/*ignored*/ }
5871073 };
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;
5981096
5991097 for (i = 1; i < objc; i += 2) {
6001098 int index;
6031101
6041102 if (Tcl_GetIndexFromObjStruct(interp, objv[i], options,
6051103 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
6071116 } else if (i + 1 == objc) {
6081117 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
6091118 "value for \"%s\" missing", options[index].name));
6101119 Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
611 goto end;
1120 goto error_return;
6121121 }
6131122
6141123 string = Tcl_GetString(valuePtr);
6151124 switch (options[index].value) {
6161125 case FILE_DEFAULT:
617 if (string[0] == '.') {
618 string++;
619 }
620 extension = string;
1126 optsPtr->extObj = valuePtr;
6211127 break;
6221128 case FILE_TYPES:
623 filterObj = valuePtr;
1129 optsPtr->filterObj = valuePtr;
6241130 break;
6251131 case FILE_INITDIR:
626 Tcl_DStringFree(&utfDirString);
1132 Tcl_DStringFree(&optsPtr->utfDirString);
6271133 if (Tcl_TranslateFileName(interp, string,
628 &utfDirString) == NULL) {
629 goto end;
630 }
1134 &optsPtr->utfDirString) == NULL)
1135 goto error_return;
6311136 break;
6321137 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;
6361140 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);
6391144 Tcl_DStringFree(&ds);
6401145 break;
6411146 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;
6461150 break;
6471151 case FILE_TITLE:
648 title = string;
1152 optsPtr->titleObj = valuePtr;
6491153 break;
6501154 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);
6541158 break;
6551159 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;
6591163 break;
6601164 case FILE_CONFIRMOW:
6611165 if (Tcl_GetBooleanFromObj(interp, valuePtr,
662 &confirmOverwrite) != TCL_OK) {
663 return TCL_ERROR;
664 }
1166 &optsPtr->confirmOverwrite) != TCL_OK)
1167 goto error_return;
6651168 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) {
6711535 goto end;
6721536 }
6731537
674 Tk_MakeWindowExist(tkwin);
675 hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
1538 Tk_MakeWindowExist(optsPtr->tkwin);
1539 hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin));
6761540
6771541 ZeroMemory(&ofn, sizeof(OPENFILENAME));
6781542 ofn.lStructSize = sizeof(OPENFILENAME);
6791543 ofn.hwndOwner = hWnd;
6801544 ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
681 ofn.lpstrFile = file;
1545 ofn.lpstrFile = optsPtr->file;
6821546 ofn.nMaxFile = TK_MULTI_MAX_PATH;
6831547 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR
684 | OFN_EXPLORER | OFN_ENABLEHOOK| OFN_ENABLESIZING;
1548 | OFN_EXPLORER| OFN_ENABLEHOOK| OFN_ENABLESIZING;
6851549 ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
6861550 ofn.lCustData = (LPARAM) &ofnData;
6871551
688 if (open != 0) {
1552 if (oper != OFN_FILE_SAVE) {
6891553 ofn.Flags |= OFN_FILEMUSTEXIST;
690 } else if (confirmOverwrite) {
1554 } else if (optsPtr->confirmOverwrite) {
6911555 ofn.Flags |= OFN_OVERWRITEPROMPT;
6921556 }
6931557 if (tsdPtr->debugFlag != 0) {
6941558 ofnData.interp = interp;
6951559 }
696 if (multi != 0) {
1560 if (optsPtr->multi != 0) {
6971561 ofn.Flags |= OFN_ALLOWMULTISELECT;
6981562
6991563 /*
7051569 ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR));
7061570 }
7071571
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);
7101577 ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString);
7111578 }
7121579
7151582 ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString);
7161583 ofn.nFilterIndex = filterIndex;
7171584
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);
7211588 } else {
7221589 /*
7231590 * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure
7261593
7271594 Tcl_DString cwd;
7281595
729 Tcl_DStringFree(&utfDirString);
730 if ((Tcl_GetCwd(interp, &utfDirString) == NULL) ||
1596 Tcl_DStringFree(&optsPtr->utfDirString);
1597 if ((Tcl_GetCwd(interp, &optsPtr->utfDirString) == NULL) ||
7311598 (Tcl_TranslateFileName(interp,
732 Tcl_DStringValue(&utfDirString), &cwd) == NULL)) {
1599 Tcl_DStringValue(&optsPtr->utfDirString), &cwd) == NULL)) {
7331600 Tcl_ResetResult(interp);
7341601 } else {
7351602 Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd),
7391606 }
7401607 ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString);
7411608
742 if (title != NULL) {
743 Tcl_WinUtfToTChar(title, -1, &titleString);
1609 if (optsPtr->titleObj != NULL) {
1610 Tcl_WinUtfToTChar(Tcl_GetString(optsPtr->titleObj), -1, &titleString);
7441611 ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString);
7451612 }
7461613
7491616 */
7501617
7511618 oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
752 if (open != 0) {
1619 if (oper != OFN_FILE_SAVE) {
7531620 winCode = GetOpenFileName(&ofn);
7541621 } else {
7551622 winCode = GetSaveFileName(&ofn);
8581725 Tcl_DStringFree(&ds);
8591726 }
8601727 result = TCL_OK;
861 if ((ofn.nFilterIndex > 0) && gotFilename && typeVariableObj
862 && filterObj) {
1728 if ((ofn.nFilterIndex > 0) && gotFilename && optsPtr->typeVariableObj
1729 && optsPtr->filterObj) {
8631730 int listObjc, count;
8641731 Tcl_Obj **listObjv = NULL;
8651732 Tcl_Obj **typeInfo = NULL;
8661733
867 if (Tcl_ListObjGetElements(interp, filterObj,
1734 if (Tcl_ListObjGetElements(interp, optsPtr->filterObj,
8681735 &listObjc, &listObjv) != TCL_OK) {
8691736 result = TCL_ERROR;
8701737 } else if (Tcl_ListObjGetElements(interp,
8711738 listObjv[ofn.nFilterIndex - 1], &count,
8721739 &typeInfo) != TCL_OK) {
8731740 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) {
8761743 result = TCL_ERROR;
8771744 }
8781745 }
8911758 Tcl_DStringFree(&titleString);
8921759 }
8931760 if (ofn.lpstrInitialDir != NULL) {
1761 /* XXX - huh? lpstrInitialDir is set from Tcl_DStringValue which
1762 can never return NULL */
8941763 Tcl_DStringFree(&dirString);
8951764 }
8961765 Tcl_DStringFree(&filterString);
8981767 Tcl_DStringFree(&extString);
8991768 }
9001769
901 end:
902 Tcl_DStringFree(&utfDirString);
1770 end:
9031771 Tcl_DStringFree(&utfFilterString);
9041772 if (ofnData.dynFileBuffer != NULL) {
9051773 ckfree(ofnData.dynFileBuffer);
9081776
9091777 return result;
9101778 }
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
9111822
9121823 /*
9131824 *-------------------------------------------------------------------------
9721883 buffer = ofnData->dynFileBuffer;
9731884 hdlg = GetParent(hdlg);
9741885
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);
9771888 buffersize = (selsize + dirsize + 1);
9781889
9791890 /*
12312142 /*
12322143 *----------------------------------------------------------------------
12332144 *
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 *
12342284 * Tk_ChooseDirectoryObjCmd --
12352285 *
12362286 * This function implements the "tk_chooseDirectory" dialog box for the
13062356 Tcl_Obj *const objv[]) /* Argument objects. */
13072357 {
13082358 TCHAR path[MAX_PATH];
1309 int oldMode, result = TCL_ERROR, i;
2359 int oldMode, result;
13102360 LPCITEMIDLIST pidl; /* Returned by browser */
13112361 BROWSEINFO bInfo; /* Used by browser */
13122362 ChooseDir cdCBData; /* Structure to pass back and forth */
13132363 LPMALLOC pMalloc; /* Used by shell */
1314 Tk_Window tkwin = clientData;
13152364 HWND hWnd;
1316 const char *utfTitle = NULL;/* Title for window */
13172365 TCHAR saveDir[MAX_PATH];
13182366 Tcl_DString titleString; /* Title */
1319 Tcl_DString initDirString; /* Initial directory */
13202367 Tcl_DString tempString; /* temporary */
13212368 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 */
13322385
13332386 path[0] = '\0';
13342387 ZeroMemory(&cdCBData, sizeof(ChooseDir));
13352388 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') {
13442393 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. */
13982406
13992407 /*
14002408 * Get ready to call the browser
14012409 */
14022410
1403 Tk_MakeWindowExist(tkwin);
1404 hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
2411 Tk_MakeWindowExist(ofnOpts.tkwin);
2412 hWnd = Tk_GetHWND(Tk_WindowId(ofnOpts.tkwin));
14052413
14062414 /*
14072415 * Setup the parameters used by SHBrowseForFolder
14152423 }
14162424 bInfo.lParam = (LPARAM) &cdCBData;
14172425
1418 if (utfTitle != NULL) {
1419 Tcl_WinUtfToTChar(utfTitle, -1, &titleString);
2426 if (ofnOpts.titleObj != NULL) {
2427 Tcl_WinUtfToTChar(Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
14202428 bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString);
14212429 } else {
14222430 bInfo.lpszTitle = TEXT("Please choose a directory, then select OK.");
14542462 oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
14552463 GetCurrentDirectory(MAX_PATH, saveDir);
14562464 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 */
14572469 pidl = SHBrowseForFolder(&bInfo);
14582470
14592471 /*
15052517 Tcl_DStringFree(&ds);
15062518 }
15072519
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;
15162522 }
15172523
15182524 /*
158158 }
159159
160160 /*
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 /*
161212 * Local Variables:
162213 * mode: c
163214 * c-basic-offset: 4
198198 int reqValue);
199199 MODULE_SCOPE void TkpWinToplevelDetachWindow(TkWindow *winPtr);
200200 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
201207
202208 /*
203209 * The following functions are not present in old versions of Windows
7676 static int Send(LPDISPATCH pdispInterp, Tcl_Interp *interp,
7777 int async, ClientData clientData, int objc,
7878 Tcl_Obj *const objv[]);
79 static Tcl_Obj * Win32ErrorObj(HRESULT hrError);
8079 static void SendTrace(const char *format, ...);
8180 static Tcl_EventProc SendEventProc;
8281
280279 if (objList != NULL) {
281280 Tcl_DecrRefCount(objList);
282281 }
283 Tcl_SetObjResult(interp, Win32ErrorObj(hr));
282 Tcl_SetObjResult(interp, TkWin32ErrorObj(hr));
284283 result = TCL_ERROR;
285284 }
286285
450449 pROT->lpVtbl->Release(pROT);
451450 }
452451 if (FAILED(hr) && result == TCL_OK) {
453 Tcl_SetObjResult(interp, Win32ErrorObj(hr));
452 Tcl_SetObjResult(interp, TkWin32ErrorObj(hr));
454453 result = TCL_ERROR;
455454 }
456455 return result;
808807 /*
809808 * ----------------------------------------------------------------------
810809 *
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 *
861810 * TkWinSend_SetExcepInfo --
862811 *
863812 * Convert the error information from a Tcl interpreter into a COM
7878 return TCL_OK;
7979 }
8080
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
81117 /*
82118 *----------------------------------------------------------------------
83119 *
243279 {
244280 HWND hwnd = 0;
245281 HWND child = 0;
282 HWND control;
246283 int id;
247284 char *rest;
248285 UINT message;
249286 WPARAM wParam;
250287 LPARAM lParam;
288 LRESULT result;
251289 static const TkStateMap messageMap[] = {
252290 {WM_LBUTTONDOWN, "WM_LBUTTONDOWN"},
253291 {WM_LBUTTONUP, "WM_LBUTTONUP"},
301339 return TCL_ERROR;
302340 }
303341 }
342
304343 message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3]));
305344 wParam = 0;
306345 lParam = 0;
317356 Tcl_DString ds;
318357 char buf[256];
319358
359 #if 0
320360 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
321372 Tcl_ExternalToUtfDString(NULL, buf, -1, &ds);
322373 Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
323374 Tcl_DStringFree(&ds);
325376 }
326377 case WM_SETTEXT: {
327378 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 }
330386 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));
332389 Tcl_DStringFree(&ds);
333390 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;
337394 }
338395 break;
339396 }
381438 Tcl_DString titleString, classString;
382439 HWND hwnd = NULL;
383440 int r = TCL_OK;
441 DWORD myPid;
384442
385443 Tcl_DStringInit(&classString);
386444 Tcl_DStringInit(&titleString);
394452 if (objc == 3) {
395453 class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString);
396454 }
397
455 if (title[0] == 0)
456 title = NULL;
457 #if 0
398458 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
399479
400480 if (hwnd == NULL) {
401481 Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1));
1919 </trustInfo>
2020 <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
2121 <application>
22 <!-- Windows 10 -->
23 <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
2224 <!-- Windows 8.1 -->
2325 <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
2426 <!-- Windows 8 -->