Check-in [6f79f912bb]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:update to Tk 8.6.3
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6f79f912bb010042a454648cb0ee115aeb7c8b26
User & Date: chw 2014-11-17 20:19:27
Context
2014-11-22
14:55
update to SQLite 3.8.7.2 check-in: 3365c5832b user: chw tags: trunk
2014-11-17
20:19
update to Tk 8.6.3 check-in: 6f79f912bb user: chw tags: trunk
20:14
update to Tcl 8.6.3 check-in: 0d95eaa631 user: chw tags: trunk
Changes

Changes to jni/sdl2tk/README.

1
2
3
4
5
6
7
8
9
README:  Tk
    This is the Tk 8.6.2 source distribution.
	http://sourceforge.net/projects/tcl/files/Tcl/
    You can get any source release of Tk from the URL above.

1. Introduction
---------------

This directory contains the sources and documentation for Tk, an X11

|







1
2
3
4
5
6
7
8
9
README:  Tk
    This is the Tk 8.6.3 source distribution.
	http://sourceforge.net/projects/tcl/files/Tcl/
    You can get any source release of Tk from the URL above.

1. Introduction
---------------

This directory contains the sources and documentation for Tk, an X11

Changes to jni/sdl2tk/changes.

7117
7118
7119
7120
7121
7122
7123
























2014-07-08 (workaround)[4955f5d] Ocaml trouble with tailcall splice (nijtmans)

2014-07-24 (bug fix) OSX [text] image display & scrolling (culler,walzer)

2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper)

--- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tk/ for details































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
2014-07-08 (workaround)[4955f5d] Ocaml trouble with tailcall splice (nijtmans)

2014-07-24 (bug fix) OSX [text] image display & scrolling (culler,walzer)

2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper)

--- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tk/ for details

2014-08-27 (bug) Cocoa: Crash after [$button destroy] (walzer)

2014-09-23 (bug) Cocoa: button and scroll display fixes (walzer)

2014-09-24 (bug) Cocoa: improved drawing performance (walzer)

2014-10-11 (bug)[9e487e] Phony button clicks from browsers to plugin (nijtmans)

2014-10-11 (bug)[810c43] [text] elide changes advance epoch (vogel)

2014-10-14 (bug)[fb35eb] fix PNG transparency appearance (walton,culler)

2014-10-18 (feature)[TIP 432] Win: updated file dialogs (nadkarni)

2014-10-26 Support for Windows 10 (nijtmans)

2014-10-28 (bug) OSX: Improved ttk notebook tab metrics for Yosemite (walzer)

2014-10-30 (bug)[3417012] [scale -digits $bigValue] segfault (vogel)

2014-11-07 (bug)[3529885] [scale] handling of negative resolution (vogel)

--- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tk/ for details

Changes to jni/sdl2tk/debian/changelog.







1
2
3
4
5
6
7
8
9
10
11






sdl2tk8.6 (8.6.2-1) unstable; urgency=low

  * Update to 8.6.2

 -- Christian Werner <chw@ch-werner.de>  Thu, 28 Aug 2014 10:17:26 +0200

sdl2tk8.6 (8.6.1-1) unstable; urgency=low

  * Initial packaging

 -- Christian Werner <chw@ch-werner.de>  Sun, 06 Apr 2014 08:51:26 +0200
>
>
>
>
>
>











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sdl2tk8.6 (8.6.3-1) unstable; urgency=low

  * Update to 8.6.3

 -- Christian Werner <chw@ch-werner.de>  Wed, 13 Nov 2014 01:30:00 +0100

sdl2tk8.6 (8.6.2-1) unstable; urgency=low

  * Update to 8.6.2

 -- Christian Werner <chw@ch-werner.de>  Thu, 28 Aug 2014 10:17:26 +0200

sdl2tk8.6 (8.6.1-1) unstable; urgency=low

  * Initial packaging

 -- Christian Werner <chw@ch-werner.de>  Sun, 06 Apr 2014 08:51:26 +0200

Changes to jni/sdl2tk/doc/chooseDirectory.n.

15
16
17
18
19
20
21
22
23



24
25
26
27
28
29
30
.PP
The procedure \fBtk_chooseDirectory\fR pops up a dialog box for the
user to select a directory. The following \fIoption\-value\fR pairs are
possible as command line arguments:
.TP
\fB\-initialdir\fR \fIdirname\fR
Specifies that the directories in \fIdirectory\fR should be displayed
when the dialog pops up. If this parameter is not specified, then
the directories in the current working directory are displayed. If the



parameter specifies a relative path, the return value will convert the
relative path to an absolute path.
.TP
\fB\-mustexist\fR \fIboolean\fR
Specifies whether the user may specify non-existent directories.  If
this parameter is true, then the user may only select directories that
already exist.  The default value is \fIfalse\fR.







|
|
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.PP
The procedure \fBtk_chooseDirectory\fR pops up a dialog box for the
user to select a directory. The following \fIoption\-value\fR pairs are
possible as command line arguments:
.TP
\fB\-initialdir\fR \fIdirname\fR
Specifies that the directories in \fIdirectory\fR should be displayed
when the dialog pops up. If this parameter is not specified,
the initial directory defaults to the current working directory 
on non-Windows systems and on Windows systems prior to Vista.
On Vista and later systems, the initial directory defaults to the last
user-selected directory for the application. If the
parameter specifies a relative path, the return value will convert the
relative path to an absolute path.
.TP
\fB\-mustexist\fR \fIboolean\fR
Specifies whether the user may specify non-existent directories.  If
this parameter is true, then the user may only select directories that
already exist.  The default value is \fIfalse\fR.

Changes to jni/sdl2tk/doc/getOpenFile.n.

61
62
63
64
65
66
67
68
69



70
71
72
73
74
75
76
particular platform then all files are listed regardless of their
types. See the section \fBSPECIFYING FILE PATTERNS\fR below for a
discussion on the contents of \fIfilePatternList\fR.
.TP
\fB\-initialdir\fR \fIdirectory\fR
.
Specifies that the files in \fIdirectory\fR should be displayed
when the dialog pops up. If this parameter is not specified, then
the files in the current working directory are displayed. If the



parameter specifies a relative path, the return value will convert the
relative path to an absolute path.
.TP
\fB\-initialfile\fR \fIfilename\fR
.
Specifies a filename to be displayed in the dialog when it pops up.
.TP







|
|
>
>
>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
particular platform then all files are listed regardless of their
types. See the section \fBSPECIFYING FILE PATTERNS\fR below for a
discussion on the contents of \fIfilePatternList\fR.
.TP
\fB\-initialdir\fR \fIdirectory\fR
.
Specifies that the files in \fIdirectory\fR should be displayed
when the dialog pops up. If this parameter is not specified, 
the initial directory defaults to the current working directory 
on non-Windows systems and on Windows systems prior to Vista.
On Vista and later systems, the initial directory defaults to the last
user-selected directory for the application. If the
parameter specifies a relative path, the return value will convert the
relative path to an absolute path.
.TP
\fB\-initialfile\fR \fIfilename\fR
.
Specifies a filename to be displayed in the dialog when it pops up.
.TP

Changes to jni/sdl2tk/generic/tk.h.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 * You may also need to update some of these files when the numbers change for
 * the version of Tcl that this release of Tk is compiled against.
 */

#define TK_MAJOR_VERSION	8
#define TK_MINOR_VERSION	6
#define TK_RELEASE_LEVEL	TCL_FINAL_RELEASE
#define TK_RELEASE_SERIAL	2

#define TK_VERSION		"8.6"
#define TK_PATCH_LEVEL		"8.6.2"
 
/*
 * A special definition used to allow this header file to be included from
 * windows or mac resource files so that they can obtain version information.
 * RC_INVOKED is defined by default by the windows RC tool and manually set
 * for macintosh.
 *







|


|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 * You may also need to update some of these files when the numbers change for
 * the version of Tcl that this release of Tk is compiled against.
 */

#define TK_MAJOR_VERSION	8
#define TK_MINOR_VERSION	6
#define TK_RELEASE_LEVEL	TCL_FINAL_RELEASE
#define TK_RELEASE_SERIAL	3

#define TK_VERSION		"8.6"
#define TK_PATCH_LEVEL		"8.6.3"
 
/*
 * A special definition used to allow this header file to be included from
 * windows or mac resource files so that they can obtain version information.
 * RC_INVOKED is defined by default by the windows RC tool and manually set
 * for macintosh.
 *

Changes to jni/sdl2tk/generic/tkMenu.c.

1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433
1434
1435

		if ((destroyThis != NULL)
			&& (destroyThis->masterMenuPtr == destroyThis)) {
		    destroyThis = NULL;
		}
	    }
	    UnhookCascadeEntry(mePtr);

	    if (menuRefPtr != NULL) {
		if (menuRefPtr->menuPtr == destroyThis) {
		    menuRefPtr->menuPtr = NULL;
		}

		if (destroyThis != NULL) {
		    TkDestroyMenu(destroyThis);
		}
	    }
	} else {
	    UnhookCascadeEntry(mePtr);
	}
    }
    if (mePtr->image != NULL) {
	Tk_FreeImage(mePtr->image);







>




>
|
|
<







1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436

		if ((destroyThis != NULL)
			&& (destroyThis->masterMenuPtr == destroyThis)) {
		    destroyThis = NULL;
		}
	    }
	    UnhookCascadeEntry(mePtr);
	    menuRefPtr = mePtr->childMenuRefPtr;
	    if (menuRefPtr != NULL) {
		if (menuRefPtr->menuPtr == destroyThis) {
		    menuRefPtr->menuPtr = NULL;
		}
	    }
	    if (destroyThis != NULL) {
		TkDestroyMenu(destroyThis);

	    }
	} else {
	    UnhookCascadeEntry(mePtr);
	}
    }
    if (mePtr->image != NULL) {
	Tk_FreeImage(mePtr->image);

Changes to jni/sdl2tk/generic/tkScale.c.

796
797
798
799
800
801
802



803
804
805
806
807
808
809
...
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
....
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
     * needed to represent any number on the scale and the most significant
     * digit of the smallest difference between numbers on the scale. In other
     * words, display enough digits so that at least one digit will be
     * different between any two adjacent positions of the scale.
     */

    numDigits = scalePtr->digits;



    if (numDigits <= 0) {
	if (scalePtr->resolution > 0) {
	    /*
	     * A resolution was specified for the scale, so just use it.
	     */

	    leastSigDigit = (int) floor(log10(scalePtr->resolution));
................................................................................
 *----------------------------------------------------------------------
 */

static void
ComputeScaleGeometry(
    register TkScale *scalePtr)	/* Information about widget. */
{
    char valueString[PRINT_CHARS];
    int tmp, valuePixels, x, y, extraSpace;
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    scalePtr->fontHeight = fm.linespace + SPACING;

    /*
................................................................................
 */

static void
ScaleSetVariable(
    register TkScale *scalePtr)	/* Info about widget. */
{
    if (scalePtr->varNamePtr != NULL) {
	char string[PRINT_CHARS];

	sprintf(string, scalePtr->format, scalePtr->value);
	scalePtr->flags |= SETTING_VAR;
	Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,
		Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);
	scalePtr->flags &= ~SETTING_VAR;
    }







>
>
>







 







|







 







|







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
...
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
....
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
     * needed to represent any number on the scale and the most significant
     * digit of the smallest difference between numbers on the scale. In other
     * words, display enough digits so that at least one digit will be
     * different between any two adjacent positions of the scale.
     */

    numDigits = scalePtr->digits;
    if (numDigits > TCL_MAX_PREC) {
	numDigits = 0;
    }
    if (numDigits <= 0) {
	if (scalePtr->resolution > 0) {
	    /*
	     * A resolution was specified for the scale, so just use it.
	     */

	    leastSigDigit = (int) floor(log10(scalePtr->resolution));
................................................................................
 *----------------------------------------------------------------------
 */

static void
ComputeScaleGeometry(
    register TkScale *scalePtr)	/* Information about widget. */
{
    char valueString[TCL_DOUBLE_SPACE];
    int tmp, valuePixels, x, y, extraSpace;
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    scalePtr->fontHeight = fm.linespace + SPACING;

    /*
................................................................................
 */

static void
ScaleSetVariable(
    register TkScale *scalePtr)	/* Info about widget. */
{
    if (scalePtr->varNamePtr != NULL) {
	char string[TCL_DOUBLE_SPACE];

	sprintf(string, scalePtr->format, scalePtr->value);
	scalePtr->flags |= SETTING_VAR;
	Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,
		Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);
	scalePtr->flags &= ~SETTING_VAR;
    }

Changes to jni/sdl2tk/generic/tkScale.h.

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
 * Space to leave between scale area and text, and between text and edge of
 * window.
 */

#define SPACING 2

/*
 * How many characters of space to provide when formatting the scale's value:
 */

#define PRINT_CHARS 150

/*
 * Declaration of procedures used in the implementation of the scale widget.
 */

MODULE_SCOPE void	TkEventuallyRedrawScale(TkScale *scalePtr, int what);
MODULE_SCOPE double	TkRoundToResolution(TkScale *scalePtr, double value);
MODULE_SCOPE TkScale *	TkpCreateScale(Tk_Window tkwin);







<
<
<
<
<
<







210
211
212
213
214
215
216






217
218
219
220
221
222
223
/*
 * Space to leave between scale area and text, and between text and edge of
 * window.
 */

#define SPACING 2







/*
 * Declaration of procedures used in the implementation of the scale widget.
 */

MODULE_SCOPE void	TkEventuallyRedrawScale(TkScale *scalePtr, int what);
MODULE_SCOPE double	TkRoundToResolution(TkScale *scalePtr, double value);
MODULE_SCOPE TkScale *	TkpCreateScale(Tk_Window tkwin);

Changes to jni/sdl2tk/library/demos/android_accel.tcl.

41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
	$canvas create text $::pos(x) $y2 -fill white -justify center \
	    -angle $::pos(t) -text "Accelerometer\nDemo" \
	    -tags a -font {{DejaVu Sans} 14 bold}
    }
}

wm attributes . -fullscreen 1

canvas .c -bg black -bd 0 -highlightthickness 0
pack .c -side top -fill both -expand 1 -padx 0 -pady 0
set f [open [info script]]
.c create text 20 120 -anchor nw -tag s -font {Courier 5} -text [read $f] \
    -fill gray50
close $f
button .c.x -text Exit -command {
    exit 0
}
bind .c.x <Return> {tk::ButtonInvoke %W}
.c create window 30 60 -anchor nw -tag x -window .c.x
bind . <<Accelerometer>> {showaccel .c %s %x}
sdltk accelerometer on







>













41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
	$canvas create text $::pos(x) $y2 -fill white -justify center \
	    -angle $::pos(t) -text "Accelerometer\nDemo" \
	    -tags a -font {{DejaVu Sans} 14 bold}
    }
}

wm attributes . -fullscreen 1
. configure -bg black
canvas .c -bg black -bd 0 -highlightthickness 0
pack .c -side top -fill both -expand 1 -padx 0 -pady 0
set f [open [info script]]
.c create text 20 120 -anchor nw -tag s -font {Courier 5} -text [read $f] \
    -fill gray50
close $f
button .c.x -text Exit -command {
    exit 0
}
bind .c.x <Return> {tk::ButtonInvoke %W}
.c create window 30 60 -anchor nw -tag x -window .c.x
bind . <<Accelerometer>> {showaccel .c %s %x}
sdltk accelerometer on

Changes to jni/sdl2tk/library/demos/android_zoom.tcl.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
	set y1 [expr {$y0 + $dist}]
	$canvas create arc $x0 $y0 $x1 $y1 -fill yellow -outline red -width 6 \
	    -start [expr {330 - $phi}] -extent -300.0 -tags a
    }
}

wm attributes . -fullscreen 1

sdltk touchtranslate 15 ;# turn <<PinchToZoom>> on
canvas .c -bg black -bd 0 -highlightthickness 0
pack .c -side top -fill both -expand 1 -padx 0 -pady 0
set f [open [info script]]
.c create text 30 120 -anchor nw -tag s -font {Courier 5} -text [read $f] \
    -fill gray50
close $f
.c create text 30 30 -anchor w -fill green -tag t -font {Helvetica 15} \
    -text "Try pinch-to-zoom with two fingers"
button .c.x -text Exit -command {exit 0}
.c create window 30 60 -anchor nw -tag x -window .c.x
bind .c <<PinchToZoom>> {showzoom %W %X %Y %x %y %s}







>












15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	set y1 [expr {$y0 + $dist}]
	$canvas create arc $x0 $y0 $x1 $y1 -fill yellow -outline red -width 6 \
	    -start [expr {330 - $phi}] -extent -300.0 -tags a
    }
}

wm attributes . -fullscreen 1
. configure -bg black
sdltk touchtranslate 15 ;# turn <<PinchToZoom>> on
canvas .c -bg black -bd 0 -highlightthickness 0
pack .c -side top -fill both -expand 1 -padx 0 -pady 0
set f [open [info script]]
.c create text 30 120 -anchor nw -tag s -font {Courier 5} -text [read $f] \
    -fill gray50
close $f
.c create text 30 30 -anchor w -fill green -tag t -font {Helvetica 15} \
    -text "Try pinch-to-zoom with two fingers"
button .c.x -text Exit -command {exit 0}
.c create window 30 60 -anchor nw -tag x -window .c.x
bind .c <<PinchToZoom>> {showzoom %W %X %Y %x %y %s}

Changes to jni/sdl2tk/library/pkgIndex.tcl.

1
2
if {[catch {package present Tcl 8.6}]} {return}
package ifneeded Tk 8.6.2 {load libtk[info sharedlibextension] Tk}

|
1
2
if {[catch {package present Tcl 8.6}]} {return}
package ifneeded Tk 8.6.3 {load libtk[info sharedlibextension] Tk}

Changes to jni/sdl2tk/library/scale.tcl.

219
220
221
222
223
224
225

226





227
228
229
230
231
232
233
	if {$inc < [$w cget -resolution]} {
	    set inc [$w cget -resolution]
	}
    } else {
	set inc [$w cget -resolution]
    }
    if {([$w cget -from] > [$w cget -to]) ^ ($dir eq "up")} {

	set inc [expr {-$inc}]





    }
    $w set [expr {[$w get] + $inc}]

    if {$repeat eq "again"} {
	set Priv(afterId) [after [$w cget -repeatinterval] \
		[list tk::ScaleIncrement $w $dir $big again]]
    } elseif {$repeat eq "initial"} {







>
|
>
>
>
>
>







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	if {$inc < [$w cget -resolution]} {
	    set inc [$w cget -resolution]
	}
    } else {
	set inc [$w cget -resolution]
    }
    if {([$w cget -from] > [$w cget -to]) ^ ($dir eq "up")} {
        if {$inc > 0} {
            set inc [expr {-$inc}]
        }
    } else {
        if {$inc < 0} {
            set inc [expr {-$inc}]
        }
    }
    $w set [expr {[$w get] + $inc}]

    if {$repeat eq "again"} {
	set Priv(afterId) [after [$w cget -repeatinterval] \
		[list tk::ScaleIncrement $w $dir $big again]]
    } elseif {$repeat eq "initial"} {

Changes to jni/sdl2tk/library/tk.tcl.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Insist on running with compatible version of Tcl
package require Tcl 8.6
# Verify that we have Tk binary and script components from the same release
package require -exact Tk  8.6.2
 
# Create a ::tk namespace
namespace eval ::tk {
    # Set up the msgcat commands
    namespace eval msgcat {
	namespace export mc mcmax
        if {[interp issafe] || [catch {package require msgcat}]} {







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Insist on running with compatible version of Tcl
package require Tcl 8.6
# Verify that we have Tk binary and script components from the same release
package require -exact Tk  8.6.3
 
# Create a ::tk namespace
namespace eval ::tk {
    # Set up the msgcat commands
    namespace eval msgcat {
	namespace export mc mcmax
        if {[interp issafe] || [catch {package require msgcat}]} {

Changes to jni/sdl2tk/macosx/configure.

1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
....
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
....
5523
5524
5525
5526
5527
5528
5529


5530





5531
5532
5533
5534
5535
5536
5537
....
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
....
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843




TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".2"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

................................................................................
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a'
	    TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a'
	    echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
if test "${ac_cv_cygwin+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
................................................................................
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)


		SHLIB_CFLAGS="-fPIC"





		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		if test $doRpath = yes; then

		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname=\$@"
	    TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$@"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then

        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        if test "${SHLIB_SUFFIX}" = ".dll"; then

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"

else








|







 







|
<







 







>
>
|
>
>
>
>
>







 







|
<







 







|







1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
....
4856
4857
4858
4859
4860
4861
4862
4863

4864
4865
4866
4867
4868
4869
4870
....
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
....
5596
5597
5598
5599
5600
5601
5602
5603

5604
5605
5606
5607
5608
5609
5610
....
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848




TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".3"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

................................................................................
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a"

	    echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
if test "${ac_cv_cygwin+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
................................................................................
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)
		case "$arch" in
		alpha|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)
		    SHLIB_CFLAGS="-fpic"
		    ;;
		esac
		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		if test $doRpath = yes; then

		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@"

	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then

        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        if test "${SHLIB_SUFFIX}" = ".dll"; then

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"

else

Changes to jni/sdl2tk/macosx/tkMacOSXButton.c.

62
63
64
65
66
67
68








69
70
71
72
73
74
75
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	    if (tkwin) {
		int parent_height = Tk_Height(Tk_Parent(tkwin));
		int widget_height = Tk_Height(tkwin);
		int y = Tk_Y(tkwin);
		if ( y > parent_height - 20 || y + widget_height < 0 ) {
		    return;
		}








	    }
	[super drawRect:dirtyRect];
    }
 }

@end

................................................................................
TkpDestroyButton(
    TkButton *butPtr)
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    [macButtonPtr->button setTag:(NSInteger)-1];

    TkMacOSXMakeCollectableAndRelease(macButtonPtr->button);
    TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
    TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
    TkMacOSXMakeCollectableAndRelease(macButtonPtr->tristateImage);
}
 
/*
 *----------------------------------------------------------------------
 *







>
>
>
>
>
>
>
>







 







|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
	    if (tkwin) {
		int parent_height = Tk_Height(Tk_Parent(tkwin));
		int widget_height = Tk_Height(tkwin);
		int y = Tk_Y(tkwin);
		if ( y > parent_height - 20 || y + widget_height < 0 ) {
		    return;
		}

	    /* 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. */
		int parent_width = Tk_Width(Tk_Parent(tkwin));
		int widget_width = Tk_Width(tkwin);
		int x = Tk_X(tkwin);
		if (x > parent_width - 50 || x < 0) { 
		    return;
		}
	    }
	[super drawRect:dirtyRect];
    }
 }

@end

................................................................................
TkpDestroyButton(
    TkButton *butPtr)
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    [macButtonPtr->button setTag:(NSInteger)-1];

    TkMacOSXMakeCollectableAndRelease(macButtonPtr->button);
    TkMacOSXMakeCollectableAndRelease(macButtonPtr->image);
    TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
    TkMacOSXMakeCollectableAndRelease(macButtonPtr->tristateImage);
}
 
/*
 *----------------------------------------------------------------------
 *

Changes to jni/sdl2tk/macosx/tkMacOSXDraw.c.

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
		    provider, decode, 0);
	}
    } else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
	/*
	 * Color image
	 */

	CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);

	bitsPerComponent = 8;
	bitsPerPixel = 32;
	bitmapInfo = (image->byte_order == MSBFirst ?
		kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) |
		kCGImageAlphaNoneSkipFirst;
	data = memcpy(ckalloc(len), image->data + image->xoffset, len);







|







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
		    provider, decode, 0);
	}
    } else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
	/*
	 * Color image
	 */

	CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);

	bitsPerComponent = 8;
	bitsPerPixel = 32;
	bitmapInfo = (image->byte_order == MSBFirst ?
		kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) |
		kCGImageAlphaNoneSkipFirst;
	data = memcpy(ckalloc(len), image->data + image->xoffset, len);

Changes to jni/sdl2tk/macosx/tkMacOSXInit.c.

232
233
234
235
236
237
238




239
240
241
242
243

244
245
246
247
248
249
250
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
#   error Mac OS X 10.5 required
#endif

	if (!uname(&name)) {
	    tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
	}




	if (tkMacOSXMacOSXVersion &&
		tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) {
	    Tcl_Panic("Mac OS X 10.%d or later required !",
		    (MAC_OS_X_VERSION_MIN_REQUIRED/10)-100);
	}


#ifdef TK_FRAMEWORK
	/*
	 * When Tk is in a framework, force tcl_findLibrary to look in the
	 * framework scripts directory.
	 * FIXME: Should we come up with a more generic way of doing this?
	 */







>
>
>
>
|




>







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
#   error Mac OS X 10.5 required
#endif

	if (!uname(&name)) {
	    tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
	}
       /*Check for new versioning scheme on Yosemite (10.10) and later.*/
	if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) {
		tkMacOSXMacOSXVersion = MAC_OS_X_VERSION_MIN_REQUIRED/100;
	    }
	if (tkMacOSXMacOSXVersion && MAC_OS_X_VERSION_MIN_REQUIRED < 100000 &&
		tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) {
	    Tcl_Panic("Mac OS X 10.%d or later required !",
		    (MAC_OS_X_VERSION_MIN_REQUIRED/10)-100);
	}
	

#ifdef TK_FRAMEWORK
	/*
	 * When Tk is in a framework, force tcl_findLibrary to look in the
	 * framework scripts directory.
	 * FIXME: Should we come up with a more generic way of doing this?
	 */

Changes to jni/sdl2tk/macosx/tkMacOSXScale.c.

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
TkpDisplayScale(
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    int result;
    char string[PRINT_CHARS];
    MacScale *macScalePtr = (MacScale *) clientData;
    Rect r;
    WindowRef windowRef;
    CGrafPtr destPort, savePort;
    Boolean portChanged;
    MacDrawable *macDraw;
    SInt32 initialValue, minValue, maxValue;







|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
TkpDisplayScale(
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    int result;
    char string[TCL_DOUBLE_SPACE];
    MacScale *macScalePtr = (MacScale *) clientData;
    Rect r;
    WindowRef windowRef;
    CGrafPtr destPort, savePort;
    Boolean portChanged;
    MacDrawable *macDraw;
    SInt32 initialValue, minValue, maxValue;

Changes to jni/sdl2tk/macosx/tkMacOSXScrlbr.c.

16
17
18
19
20
21
22
23


24



























































25
26
27
28
29
30
31
32
33
34
35
36
37
..
45
46
47
48
49
50
51

52
53
54
55
56
57
58
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
...
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
...
610
611
612
613
614
615
616







































617
618
619
620
621
622
623
624
625
#include "tkScrollbar.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_SCROLLBAR
#endif
*/



/*



























































 * Declaration of Mac specific scrollbar structure.
 */

typedef struct MacScrollbar {
    TkScrollbar info;
    NSScroller	*scroller;
    int variant;
} MacScrollbar;

typedef struct ScrollbarMetrics {
    SInt32 width, minThumbHeight;
    int minHeight, topArrowHeight, bottomArrowHeight;
    NSControlSize controlSize;
................................................................................
/*
 * Declarations for functions defined in this file.
 */

static void		UpdateScrollbarMetrics(void);
static void		ScrollbarEventProc(ClientData clientData,
			    XEvent *eventPtr);


/*
 * The class procedure table for the scrollbar widget.
 */

const Tk_ClassProcs tkpScrollbarProcs = {
    sizeof(Tk_ClassProcs),	/* size */
................................................................................
};
 
#pragma mark TKApplication(TKScrlbr)

#define NSAppleAquaScrollBarVariantChanged @"AppleAquaScrollBarVariantChanged"

@implementation TKApplication(TKScrlbr)
- (void) tkScroller: (NSScroller *) scroller
{
    NSScrollerPart hitPart = [scroller hitPart];
    TkScrollbar *scrollPtr = (TkScrollbar *)[scroller tag];
    Tcl_DString cmdString;
    Tcl_Interp *interp;
    int result;

................................................................................
 */

void
TkpDestroyScrollbar(
    TkScrollbar *scrollPtr)
{
    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
    NSScroller *scroller = macScrollPtr->scroller;
    [scroller setTag:(NSInteger)0];

    TkMacOSXMakeCollectableAndRelease(macScrollPtr->scroller);
}
 
/*
 *--------------------------------------------------------------
 *
................................................................................

void
TkpDisplayScrollbar(
    ClientData clientData)	/* Information about window. */
{
    TkScrollbar *scrollPtr = clientData;
    MacScrollbar *macScrollPtr = clientData;
    NSScroller *scroller = macScrollPtr->scroller;
    Tk_Window tkwin = scrollPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    MacDrawable *macWin =  (MacDrawable *) winPtr->window;
    TkMacOSXDrawingContext dc;
    NSView *view = TkMacOSXDrawableView(macWin);
    CGFloat viewHeight = [view bounds].size.height;
    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
................................................................................
    #endif
    if (!NSEqualRects(frame, [scroller frame])) {
	[scroller setFrame:frame];
    }
    [scroller setEnabled:(knobProportion < 1.0 &&
	    (scrollPtr->vertical ? frame.size.height : frame.size.width) >
	    metrics[macScrollPtr->variant].minHeight)];

    [scroller setDoubleValue:scrollPtr->firstFraction / (1.0 - knobProportion)];
    [scroller setKnobProportion:knobProportion];
    [scroller displayRectIgnoringOpacity:[scroller bounds]];
    TkMacOSXRestoreDrawingContext(&dc);
#ifdef TK_MAC_DEBUG_SCROLLBAR
    TKLog(@"scroller %s frame %@ width %d height %d",
	    ((TkWindow *)scrollPtr->tkwin)->pathName, NSStringFromRect(frame),
	    Tk_Width(tkwin), Tk_Height(tkwin));
#endif
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkpComputeScrollbarGeometry --
 *
................................................................................
void
TkpComputeScrollbarGeometry(
    register TkScrollbar *scrollPtr)
				/* Scrollbar whose geometry may have
				 * changed. */
{
    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
    NSScroller *scroller = macScrollPtr->scroller;
    int width, height, variant, fieldLength;

    if (scrollPtr->highlightWidth < 0) {
	scrollPtr->highlightWidth = 0;
    }
    scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
    width = Tk_Width(scrollPtr->tkwin) - 2 * scrollPtr->inset;
................................................................................
		[scroller removeFromSuperviewWithoutNeedingDisplay];
	    }
	    TkMacOSXMakeCollectableAndRelease(scroller);
	}
    }
    if (!scroller) {
	if ((width > height) ^ !scrollPtr->vertical) {
	    /* -[NSScroller initWithFrame:] determines horizonalness for the
	     * lifetime of the scroller via isHoriz = (width > height) */
	    if (scrollPtr->vertical) {
		width = height;
	    } else if (width > 1) {
		height = width - 1;
	    } else {
		height = 1;
		width = 2;
	    }
	}
	scroller = [[NSScroller alloc] initWithFrame:
		NSMakeRect(0, 0, width, height)];
	macScrollPtr->scroller = TkMacOSXMakeUncollectable(scroller);
	[scroller setAction:@selector(tkScroller:)];
	[scroller setTarget:NSApp];
	[scroller setTag:(NSInteger)scrollPtr];
    }
    [[scroller cell] setControlSize:metrics[variant].controlSize];
................................................................................

int
TkpScrollbarPosition(
    register TkScrollbar *scrollPtr,
				/* Scrollbar widget record. */
    int x, int y)		/* Coordinates within scrollPtr's window. */
{
    NSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
    MacDrawable *macWin =  (MacDrawable *)
	    ((TkWindow *) scrollPtr->tkwin)->window;
    NSView *view = TkMacOSXDrawableView(macWin);

    switch ([scroller testPart:NSMakePoint(macWin->xOff + x,
	    [view bounds].size.height - (macWin->yOff + y))]) {
    case NSScrollerDecrementLine:
................................................................................
    case DeactivateNotify:
	TkScrollbarEventuallyRedraw(scrollPtr);
	break;
    default:
	TkScrollbarEventProc(clientData, eventPtr);
    }
}







































 
/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */








>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|







 







>







 







|







 







|
|







 







|







 







>




|



|







 







|







 







|










|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
#include "tkScrollbar.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_SCROLLBAR
#endif
*/

NSRect                  TkMacOSXGetScrollFrame(TkScrollbar *scrlPtr);

/*
 * A subclass of NSScroller with sanity checking:
 *
 * NSScrollers created by Tk will have their tag set to a pointer to the
 * TkScrollbar which manages the NSScroller.  This allows an NSScroller to be
 * aware of the state of its Tk parent.  This subclass overrides the drawRect
 * method so that it will not draw itself if the widget is completely outside
 * of its container.
 */

@interface TkNSScroller: NSScroller
-(void) drawRect:(NSRect)dirtyRect;

@end

@implementation TkNSScroller

    - (void)drawRect:(NSRect)dirtyRect
    {
	NSInteger tag = [self tag];
	if ( tag != -1) {
	    TkScrollbar *scrollPtr = (TkScrollbar *)tag;
	    MacDrawable* macWin = (MacDrawable *)scrollPtr;
	    Tk_Window tkwin = scrollPtr->tkwin;
	    NSRect Tkframe = TkMacOSXGetScrollFrame(scrollPtr);
	    /* Do not draw if the widget is misplaced or unmapped. */
	    if ( NSIsEmptyRect(Tkframe) || 
		 ! macWin->winPtr->flags & TK_MAPPED ||
		 ! NSEqualRects(Tkframe, [self frame]) 
		 ) {
		return;
	    }

	    /*
	     * Do not draw if the widget is completely outside of its parent.
	     */
	    if (tkwin) {
		int parent_height = Tk_Height(Tk_Parent(tkwin));
		int widget_height = Tk_Height(tkwin);
		int y = Tk_Y(tkwin);
		if ( y > parent_height || y + widget_height < 0 ) {
		    return;
		}

		int parent_width = Tk_Width(Tk_Parent(tkwin));
		int widget_width = Tk_Width(tkwin);
		int x = Tk_X(tkwin);
		if (x > parent_width || x + widget_width < 0) {
		    return;
		}
	    }
	}
	[super drawRect:dirtyRect];
    }

@end



/*
 * Declaration of Mac specific scrollbar structure.
 */

typedef struct MacScrollbar {
    TkScrollbar info;
    TkNSScroller	*scroller;
    int variant;
} MacScrollbar;

typedef struct ScrollbarMetrics {
    SInt32 width, minThumbHeight;
    int minHeight, topArrowHeight, bottomArrowHeight;
    NSControlSize controlSize;
................................................................................
/*
 * Declarations for functions defined in this file.
 */

static void		UpdateScrollbarMetrics(void);
static void		ScrollbarEventProc(ClientData clientData,
			    XEvent *eventPtr);


/*
 * The class procedure table for the scrollbar widget.
 */

const Tk_ClassProcs tkpScrollbarProcs = {
    sizeof(Tk_ClassProcs),	/* size */
................................................................................
};
 
#pragma mark TKApplication(TKScrlbr)

#define NSAppleAquaScrollBarVariantChanged @"AppleAquaScrollBarVariantChanged"

@implementation TKApplication(TKScrlbr)
- (void) tkScroller: (TkNSScroller *) scroller
{
    NSScrollerPart hitPart = [scroller hitPart];
    TkScrollbar *scrollPtr = (TkScrollbar *)[scroller tag];
    Tcl_DString cmdString;
    Tcl_Interp *interp;
    int result;

................................................................................
 */

void
TkpDestroyScrollbar(
    TkScrollbar *scrollPtr)
{
    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
    TkNSScroller *scroller = macScrollPtr->scroller;
    [scroller setTag:(NSInteger)-1];

    TkMacOSXMakeCollectableAndRelease(macScrollPtr->scroller);
}
 
/*
 *--------------------------------------------------------------
 *
................................................................................

void
TkpDisplayScrollbar(
    ClientData clientData)	/* Information about window. */
{
    TkScrollbar *scrollPtr = clientData;
    MacScrollbar *macScrollPtr = clientData;
    TkNSScroller *scroller = macScrollPtr->scroller;
    Tk_Window tkwin = scrollPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    MacDrawable *macWin =  (MacDrawable *) winPtr->window;
    TkMacOSXDrawingContext dc;
    NSView *view = TkMacOSXDrawableView(macWin);
    CGFloat viewHeight = [view bounds].size.height;
    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
................................................................................
    #endif
    if (!NSEqualRects(frame, [scroller frame])) {
	[scroller setFrame:frame];
    }
    [scroller setEnabled:(knobProportion < 1.0 &&
	    (scrollPtr->vertical ? frame.size.height : frame.size.width) >
	    metrics[macScrollPtr->variant].minHeight)];
    // [scroller setEnabled: YES];
    [scroller setDoubleValue:scrollPtr->firstFraction / (1.0 - knobProportion)];
    [scroller setKnobProportion:knobProportion];
    [scroller displayRectIgnoringOpacity:[scroller bounds]];
    TkMacOSXRestoreDrawingContext(&dc);
    #ifdef TK_MAC_DEBUG_SCROLLBAR
    TKLog(@"scroller %s frame %@ width %d height %d",
	    ((TkWindow *)scrollPtr->tkwin)->pathName, NSStringFromRect(frame),
	    Tk_Width(tkwin), Tk_Height(tkwin));
    #endif
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkpComputeScrollbarGeometry --
 *
................................................................................
void
TkpComputeScrollbarGeometry(
    register TkScrollbar *scrollPtr)
				/* Scrollbar whose geometry may have
				 * changed. */
{
    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
    TkNSScroller *scroller = macScrollPtr->scroller;
    int width, height, variant, fieldLength;

    if (scrollPtr->highlightWidth < 0) {
	scrollPtr->highlightWidth = 0;
    }
    scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
    width = Tk_Width(scrollPtr->tkwin) - 2 * scrollPtr->inset;
................................................................................
		[scroller removeFromSuperviewWithoutNeedingDisplay];
	    }
	    TkMacOSXMakeCollectableAndRelease(scroller);
	}
    }
    if (!scroller) {
	if ((width > height) ^ !scrollPtr->vertical) {
	    /* -[NSScroller initWithFrame:] determines horizontalness for the
	     * lifetime of the scroller via isHoriz = (width > height) */
	    if (scrollPtr->vertical) {
		width = height;
	    } else if (width > 1) {
		height = width - 1;
	    } else {
		height = 1;
		width = 2;
	    }
	}
	scroller = [[TkNSScroller alloc] initWithFrame:
		NSMakeRect(0, 0, width, height)];
	macScrollPtr->scroller = TkMacOSXMakeUncollectable(scroller);
	[scroller setAction:@selector(tkScroller:)];
	[scroller setTarget:NSApp];
	[scroller setTag:(NSInteger)scrollPtr];
    }
    [[scroller cell] setControlSize:metrics[variant].controlSize];
................................................................................

int
TkpScrollbarPosition(
    register TkScrollbar *scrollPtr,
				/* Scrollbar widget record. */
    int x, int y)		/* Coordinates within scrollPtr's window. */
{
    TkNSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
    MacDrawable *macWin =  (MacDrawable *)
	    ((TkWindow *) scrollPtr->tkwin)->window;
    NSView *view = TkMacOSXDrawableView(macWin);

    switch ([scroller testPart:NSMakePoint(macWin->xOff + x,
	    [view bounds].size.height - (macWin->yOff + y))]) {
    case NSScrollerDecrementLine:
................................................................................
    case DeactivateNotify:
	TkScrollbarEventuallyRedraw(scrollPtr);
	break;
    default:
	TkScrollbarEventProc(clientData, eventPtr);
    }
}


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetScrollFrame --
 *
 *	Computes a frame for an NSScroller that will correspond to where
 *	Tk thinks the scroller is located.
 *
 * Results:
 *	Returns an NSRect describing a frame for an NSScrollbar.
 *
 * Side effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
NSRect TkMacOSXGetScrollFrame(
     TkScrollbar *scrlPtr)
{
    MacScrollbar *macscrlPtr = (MacScrollbar *) scrlPtr;
    Tk_Window tkwin = scrlPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    if (tkwin) {
	MacDrawable *macWin =  (MacDrawable *) winPtr->window;
	NSView *view = TkMacOSXDrawableView(macWin);
	CGFloat viewHeight = [view bounds].size.height;
	NSRect frame = NSMakeRect(macWin->xOff, macWin->yOff,
				  Tk_Width(tkwin), Tk_Height(tkwin));

	frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
	return frame;
    } else {
	return NSZeroRect;
    }
}


 
/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */

Changes to jni/sdl2tk/macosx/tkMacOSXWindowEvent.c.

352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
...
764
765
766
767
768
769
770


771
772
773
774
775
776
777
778
779











780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
...
797
798
799
800
801
802
803





804
805
806
807
808
809
810
...
816
817
818
819
820
821
822

823













824
825
826

827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859
860



861
862
863
864
865
866
867
...
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
    event.xany.display = Tk_Display(winPtr);
    event.type = Expose;
    event.xexpose.x = damageBounds.origin.x - bounds.origin.x;
    event.xexpose.y = damageBounds.origin.y - bounds.origin.y;
    event.xexpose.width = damageBounds.size.width;
    event.xexpose.height = damageBounds.size.height;
    event.xexpose.count = 0;
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);

#ifdef TK_MAC_DEBUG_DRAWING
    TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
	event.xexpose.y, event.xexpose.width, event.xexpose.height);
#endif

    /*
     * Generate updates for the children of this window
     */

    for (childPtr = winPtr->childList; childPtr != NULL;
	    childPtr = childPtr->nextPtr) {
................................................................................
	if (childPtr != NULL && Tk_IsMapped(childPtr)) {
	    GenerateUpdates(updateRgn, updateBounds, childPtr);
	}

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }

    return 1;
}
 
/*
 *----------------------------------------------------------------------
 *
................................................................................
 * during the normal AppKit drawing cycle, we supress drawing of all subviews
 * and instead send Expose events about the subviews that would be redrawn.
 */

@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIMutableShapeRef) shape;


- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
- (BOOL) acceptsFirstResponder;
- (void) keyDown: (NSEvent *) theEvent;
@end

@implementation TKContentView
@end












static Tk_RestrictAction
ExposeRestrictProc(
    ClientData arg,
    XEvent *eventPtr)
{
    return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg)
	    ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}


@implementation TKContentView(TKWindowEvent)

- (void) drawRect: (NSRect) rect
{
    const NSRect *rectsBeingDrawn;
    NSInteger rectsBeingDrawnCount;
................................................................................
#ifdef TK_MAC_DEBUG_DRAWING
    TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, NSStringFromRect(rect));
    [[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:.1] setFill];
    NSRectFillListUsingOperation(rectsBeingDrawn, rectsBeingDrawnCount,
	    NSCompositeSourceOver);
#endif






    CGFloat height = [self bounds].size.height;
    HIMutableShapeRef drawShape = HIShapeCreateMutable();

    while (rectsBeingDrawnCount--) {
	CGRect r = NSRectToCGRect(*rectsBeingDrawn++);

	r.origin.y = height - (r.origin.y + r.size.height);
................................................................................
	[self performSelectorOnMainThread:@selector(generateExposeEvents:)
		withObject:(id)drawShape waitUntilDone:NO
		modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
			NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
			nil]];
    }
    CFRelease(drawShape);

}














- (void) generateExposeEvents: (HIMutableShapeRef) shape
{

    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    unsigned long serial;
    CGRect updateBounds;

    if (!winPtr) {
	return;
    }

    HIShapeGetBounds(shape, &updateBounds);
    serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    if (GenerateUpdates(shape, &updateBounds, winPtr) &&
	    ![[NSRunLoop currentRunLoop] currentMode] &&
	    Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
	/*
	 * Ensure there are no pending idle-time redraws that could prevent the
	 * just posted Expose events from generating new redraws.
	 */

	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}

	/*
	 * For smoother drawing, process Expose events and resulting redraws
	 * immediately instead of at idle time.
	 */

	ClientData oldArg;
	Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
		UINT2PTR(serial), &oldArg);

	while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}

	Tk_RestrictEvents(oldProc, oldArg, &oldArg);
	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
    }
}




- (void) tkToolbarButton: (id) sender
{
#ifdef TK_MAC_DEBUG_EVENTS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd);
#endif
    XVirtualEvent event;
    int x, y;
................................................................................
	    &event.x_root, &event.y_root, &x, &y, &event.state);
    Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
    event.same_screen = true;
    event.name = Tk_GetUid("ToolbarButton");
    Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}

#ifdef TK_MAC_DEBUG_DRAWING
- (void) setFrameSize: (NSSize) newSize
{
    TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
	    NSStringFromSize(newSize));
    [super setFrameSize:newSize];
}

- (void) setNeedsDisplayInRect: (NSRect) invalidRect
{
    TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
	    NSStringFromRect(invalidRect));
    [super setNeedsDisplayInRect:invalidRect];
}
#endif

- (BOOL) isOpaque
{
    NSWindow *w = [self window];

    if (opaqueTag != NULL) {
      return YES;







|
>
|
|

|







 







|







 







>
>









>
>
>
>
>
>
>
>
>
>
>








>







 







>
>
>
>
>







 







>

>
>
>
>
>
>
>
>
>
>
>
>
>



>





|

>



|
|
|
|
|
|

|

|
|
|
|

|
|
|

|
>
|
|
|
|
|
>
>
>







 







<


<
<





<
<


<







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
...
921
922
923
924
925
926
927

928
929


930
931
932
933
934


935
936

937
938
939
940
941
942
943
    event.xany.display = Tk_Display(winPtr);
    event.type = Expose;
    event.xexpose.x = damageBounds.origin.x - bounds.origin.x;
    event.xexpose.y = damageBounds.origin.y - bounds.origin.y;
    event.xexpose.width = damageBounds.size.width;
    event.xexpose.height = damageBounds.size.height;
    event.xexpose.count = 0;
    Tk_HandleEvent(&event);

    #ifdef TK_MAC_DEBUG_DRAWING
    NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
	event.xexpose.y, event.xexpose.width, event.xexpose.height);
    #endif

    /*
     * Generate updates for the children of this window
     */

    for (childPtr = winPtr->childList; childPtr != NULL;
	    childPtr = childPtr->nextPtr) {
................................................................................
	if (childPtr != NULL && Tk_IsMapped(childPtr)) {
	    GenerateUpdates(updateRgn, updateBounds, childPtr);
	}

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }    

    return 1;
}
 
/*
 *----------------------------------------------------------------------
 *
................................................................................
 * during the normal AppKit drawing cycle, we supress drawing of all subviews
 * and instead send Expose events about the subviews that would be redrawn.
 */

@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIMutableShapeRef) shape;
- (void) viewDidEndLiveResize;
- (void) viewWillDraw;
- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
- (BOOL) acceptsFirstResponder;
- (void) keyDown: (NSEvent *) theEvent;
@end

@implementation TKContentView
@end

double drawTime;

/*
 * Set a minimum time for drawing to render. With removal of private NSView API's, default drawing
 * is slower and less responsive. This number, which seems feasible after some experimentatation, skips
 * some drawing to avoid lag. 
 */

#define MAX_DYNAMIC_TIME .000000001

/*Restrict event processing to Expose events.*/
static Tk_RestrictAction
ExposeRestrictProc(
    ClientData arg,
    XEvent *eventPtr)
{
    return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg)
	    ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}


@implementation TKContentView(TKWindowEvent)

- (void) drawRect: (NSRect) rect
{
    const NSRect *rectsBeingDrawn;
    NSInteger rectsBeingDrawnCount;
................................................................................
#ifdef TK_MAC_DEBUG_DRAWING
    TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, NSStringFromRect(rect));
    [[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:.1] setFill];
    NSRectFillListUsingOperation(rectsBeingDrawn, rectsBeingDrawnCount,
	    NSCompositeSourceOver);
#endif

    NSDate *beginTime=[NSDate date];

    /*Skip drawing during live resize if redraw is too slow.*/
    if([self inLiveResize] && drawTime>MAX_DYNAMIC_TIME) return;

    CGFloat height = [self bounds].size.height;
    HIMutableShapeRef drawShape = HIShapeCreateMutable();

    while (rectsBeingDrawnCount--) {
	CGRect r = NSRectToCGRect(*rectsBeingDrawn++);

	r.origin.y = height - (r.origin.y + r.size.height);
................................................................................
	[self performSelectorOnMainThread:@selector(generateExposeEvents:)
		withObject:(id)drawShape waitUntilDone:NO
		modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
			NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
			nil]];
    }
    CFRelease(drawShape);
    drawTime=-[beginTime timeIntervalSinceNow];
}

/*At conclusion of resize event, send notification and set view for redraw if earlier drawing was skipped because of lagginess.*/
- (void)viewDidEndLiveResize
{
    if(drawTime>MAX_DYNAMIC_TIME) {
    [self setNeedsDisplay:YES];
    [super viewDidEndLiveResize];
    }
}

-(void) viewWillDraw  {
	[self setNeedsDisplay:YES];
    } 

- (void) generateExposeEvents: (HIMutableShapeRef) shape
{

    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    unsigned long serial;
    CGRect updateBounds;

    if (!winPtr) {
		return;
    }

    HIShapeGetBounds(shape, &updateBounds);
    serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    if (GenerateUpdates(shape, &updateBounds, winPtr) &&
	![[NSRunLoop currentRunLoop] currentMode] &&
	Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
    	/*
    	 * Ensure there are no pending idle-time redraws that could prevent the
    	 * just posted Expose events from generating new redraws.
    	 */

    	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}

    	/*
    	 * For smoother drawing, process Expose events and resulting redraws
    	 * immediately instead of at idle time.
    	 */

    	ClientData oldArg;
    	Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
						     UINT2PTR(serial), &oldArg);

    	while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
 
    	Tk_RestrictEvents(oldProc, oldArg, &oldArg);
    	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}

    } 
   
}

/*This is no-op on 10.7 and up because Apple has removed this widget, but leaving here for backwards compatibility.*/
- (void) tkToolbarButton: (id) sender
{
#ifdef TK_MAC_DEBUG_EVENTS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd);
#endif
    XVirtualEvent event;
    int x, y;
................................................................................
	    &event.x_root, &event.y_root, &x, &y, &event.state);
    Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
    event.same_screen = true;
    event.name = Tk_GetUid("ToolbarButton");
    Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}


- (void) setFrameSize: (NSSize) newSize
{


    [super setFrameSize:newSize];
}

- (void) setNeedsDisplayInRect: (NSRect) invalidRect
{


    [super setNeedsDisplayInRect:invalidRect];
}


- (BOOL) isOpaque
{
    NSWindow *w = [self window];

    if (opaqueTag != NULL) {
      return YES;

Changes to jni/sdl2tk/macosx/ttkMacOSXTheme.c.

290
291
292
293
294
295
296

297
298
299
300
301
302
303






304

305
306
307
308
309
310
311
 * between the content in the tab view and the tab-view edges.
 *
 * <URL: http://developer.apple.com/documentation/userexperience/Conceptual/
 *       AppleHIGuidelines/XHIGControls/XHIGControls.html#//apple_ref/doc/uid/
 *       TP30000359-TPXREF116>
 */


static const int TAB_HEIGHT = 10;
static const int TAB_OVERLAP = 10;

static void TabElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{






    *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1;

}

static void TabElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);







>
|
|





>
>
>
>
>
>
|
>







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
 * between the content in the tab view and the tab-view edges.
 *
 * <URL: http://developer.apple.com/documentation/userexperience/Conceptual/
 *       AppleHIGuidelines/XHIGControls/XHIGControls.html#//apple_ref/doc/uid/
 *       TP30000359-TPXREF116>
 */


int TAB_HEIGHT = 0;
int TAB_OVERLAP = 0;

static void TabElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
       TAB_HEIGHT = 10;
       TAB_OVERLAP = 10;
       /*Different metrics on 10.10/Yosemite.*/
    if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) {
       TAB_OVERLAP = 5;
      }
     *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1;

}

static void TabElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);

Changes to jni/sdl2tk/sdl/SdlTkInt.c.

1906
1907
1908
1909
1910
1911
1912


1913
1914
1915
1916
1917
1918
1919
			    }
			} else {
			    SdlTkX.viewport.w = width;
			    SdlTkX.viewport.h = height;
			    SdlTkX.outrect = NULL;
			}
			SdlTkSendViewportUpdate();


		    } else {
			if (newsurf != NULL) {
			    SDL_FreeSurface(newsurf);
			}
			if (newtex != NULL) {
			    SDL_DestroyTexture(newtex);
			}







>
>







1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
			    }
			} else {
			    SdlTkX.viewport.w = width;
			    SdlTkX.viewport.h = height;
			    SdlTkX.outrect = NULL;
			}
			SdlTkSendViewportUpdate();
			SDL_SetRenderTarget(SdlTkX.sdlrend, NULL);
			SDL_RenderSetViewport(SdlTkX.sdlrend, NULL);
		    } else {
			if (newsurf != NULL) {
			    SDL_FreeSurface(newsurf);
			}
			if (newtex != NULL) {
			    SDL_DestroyTexture(newtex);
			}

Changes to jni/sdl2tk/sdl/SdlTkUtils.c.

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
    result = Tcl_EvalEx(interp, "glob -nocomplain -directory "
			"[file join $tk_library fonts] * "
			"[glob -nocomplain -directory ~/.fonts -types f *.ttf]",
			-1, TCL_EVAL_GLOBAL);
#endif
    if (result != TCL_OK) {
fonterr:
        Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "error initializing fonts", (char *) NULL);
	goto error;
    }
    if (Tcl_SplitList(interp, Tcl_GetStringResult(interp), &argc, &argv)
	!= TCL_OK) {
        goto fonterr;
    }







|







798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
    result = Tcl_EvalEx(interp, "glob -nocomplain -directory "
			"[file join $tk_library fonts] * "
			"[glob -nocomplain -directory ~/.fonts -types f *.ttf]",
			-1, TCL_EVAL_GLOBAL);
#endif
    if (result != TCL_OK) {
fonterr:
	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "error initializing fonts", (char *) NULL);
	goto error;
    }
    if (Tcl_SplitList(interp, Tcl_GetStringResult(interp), &argc, &argv)
	!= TCL_OK) {
        goto fonterr;
    }

Changes to jni/sdl2tk/sdl/SdlTkX.c.

6415
6416
6417
6418
6419
6420
6421
6422

6423
6424
6425
6426
6427
6428
6429
....
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
....
6618
6619
6620
6621
6622
6623
6624

6625



6626
6627
6628
6629
6630
6631
6632


6633
6634
6635
6636
6637
6638
6639
....
6658
6659
6660
6661
6662
6663
6664
6665
6666

6667
6668
6669
6670
6671
6672
6673

	tex = SDL_CreateTexture(SdlTkX.sdlrend,
				SDL_PIXELFORMAT_ABGR8888,
				SDL_TEXTUREACCESS_TARGET_3D,
				_w->atts.width, _w->atts.height);
	if (tex != NULL) {
#ifndef ANDROID
	    SDL_SetRenderTargetQuick(SdlTkX.sdlrend, tex);

#endif
	    _w->gl_tex = tex;
	    _w->gl_ctx = ctx;
	} else {
	    SDL_GL_DeleteContext(ctx);
	    ctx = NULL;
	}
................................................................................
		SDL_SetRenderTargetQuick(SdlTkX.sdlrend, NULL);
		SdlTkX.gl_ctx = NULL;
	    }
	}
#else
	SDL_GL_MakeCurrentQuick(SdlTkX.sdlscreen, ctx);
	if ((ctx != NULL) && (_w->gl_tex)) {
	    SDL_SetRenderTargetQuick(SdlTkX.sdlrend, _w->gl_tex);
	} else {
	    SDL_SetRenderTargetQuick(SdlTkX.sdlrend, NULL);
	}
#endif
    }
done:
    SdlTkUnlock(display);
}

................................................................................
	    SDL_Texture *tex;

	    tex = SDL_CreateTexture(SdlTkX.sdlrend,
				    SDL_PIXELFORMAT_ABGR8888,
				    SDL_TEXTUREACCESS_TARGET_3D,
				    _w->atts.width, _w->atts.height);
	    if (tex != NULL) {

		SDL_SetRenderTargetQuick(SdlTkX.sdlrend, tex);



		SDL_DestroyTexture(_w->gl_tex);
		_w->gl_tex = tex;
		SdlTkGenerateConfigureNotify(w);
#ifdef ANDROID
		SDL_GL_MakeCurrent(SdlTkX.sdlscreen, NULL);
		SdlTkX.gl_ctx = NULL;
		Tcl_ConditionNotify(&ctx_cond);


#endif
		goto done;
	    }
	}
	SDL_QueryTexture(_w->gl_tex, NULL, NULL, &width, &height);
	surf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
				    SdlTkX.sdlsurf->format->BitsPerPixel,
................................................................................
		p.next = NULL;
		SdlTkGfxCopyArea((Pixmap) &p, w, &xgc, 0, 0,
				 width, height, 0, 0);
		SdlTkScreenChanged();
		SdlTkDirtyArea(w, 0, 0, width, height);
	    }
	    SDL_FreeSurface(surf);
#ifdef ANDROID
	    SDL_SetRenderTarget(SdlTkX.sdlrend, NULL);

	    SDL_GL_MakeCurrent(SdlTkX.sdlscreen, NULL);
	    SdlTkX.gl_ctx = NULL;
	    Tcl_ConditionNotify(&ctx_cond);
	    Tcl_ConditionWait(&time_cond, &xlib_lock, NULL);
#endif
	}
    }







|
>







 







|

|







 







>

>
>
>







>
>







 







<

>







6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
....
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
....
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
....
6665
6666
6667
6668
6669
6670
6671

6672
6673
6674
6675
6676
6677
6678
6679
6680

	tex = SDL_CreateTexture(SdlTkX.sdlrend,
				SDL_PIXELFORMAT_ABGR8888,
				SDL_TEXTUREACCESS_TARGET_3D,
				_w->atts.width, _w->atts.height);
	if (tex != NULL) {
#ifndef ANDROID
	    SDL_SetRenderTarget(SdlTkX.sdlrend, tex);
	    SDL_SetRenderTarget(SdlTkX.sdlrend, NULL);
#endif
	    _w->gl_tex = tex;
	    _w->gl_ctx = ctx;
	} else {
	    SDL_GL_DeleteContext(ctx);
	    ctx = NULL;
	}
................................................................................
		SDL_SetRenderTargetQuick(SdlTkX.sdlrend, NULL);
		SdlTkX.gl_ctx = NULL;
	    }
	}
#else
	SDL_GL_MakeCurrentQuick(SdlTkX.sdlscreen, ctx);
	if ((ctx != NULL) && (_w->gl_tex)) {
	    SDL_SetRenderTarget(SdlTkX.sdlrend, _w->gl_tex);
	} else {
	    SDL_SetRenderTarget(SdlTkX.sdlrend, NULL);
	}
#endif
    }
done:
    SdlTkUnlock(display);
}

................................................................................
	    SDL_Texture *tex;

	    tex = SDL_CreateTexture(SdlTkX.sdlrend,
				    SDL_PIXELFORMAT_ABGR8888,
				    SDL_TEXTUREACCESS_TARGET_3D,
				    _w->atts.width, _w->atts.height);
	    if (tex != NULL) {
#ifdef ANDROID
		SDL_SetRenderTargetQuick(SdlTkX.sdlrend, tex);
#else
		SDL_SetRenderTarget(SdlTkX.sdlrend, tex);
#endif
		SDL_DestroyTexture(_w->gl_tex);
		_w->gl_tex = tex;
		SdlTkGenerateConfigureNotify(w);
#ifdef ANDROID
		SDL_GL_MakeCurrent(SdlTkX.sdlscreen, NULL);
		SdlTkX.gl_ctx = NULL;
		Tcl_ConditionNotify(&ctx_cond);
#else
		SDL_SetRenderTarget(SdlTkX.sdlrend, NULL);
#endif
		goto done;
	    }
	}
	SDL_QueryTexture(_w->gl_tex, NULL, NULL, &width, &height);
	surf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
				    SdlTkX.sdlsurf->format->BitsPerPixel,
................................................................................
		p.next = NULL;
		SdlTkGfxCopyArea((Pixmap) &p, w, &xgc, 0, 0,
				 width, height, 0, 0);
		SdlTkScreenChanged();
		SdlTkDirtyArea(w, 0, 0, width, height);
	    }
	    SDL_FreeSurface(surf);

	    SDL_SetRenderTarget(SdlTkX.sdlrend, NULL);
#ifdef ANDROID
	    SDL_GL_MakeCurrent(SdlTkX.sdlscreen, NULL);
	    SdlTkX.gl_ctx = NULL;
	    Tcl_ConditionNotify(&ctx_cond);
	    Tcl_ConditionWait(&time_cond, &xlib_lock, NULL);
#endif
	}
    }

Changes to jni/sdl2tk/sdl/tkSDLScale.c.

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int rightEdge)		/* X-coordinate of right edge of text,
				 * specified in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int y, width, length;
    char valueString[PRINT_CHARS];
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
................................................................................
	    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
    if (scalePtr->flags & REDRAW_OTHER) {
	/*
	 * Display the tick marks.
	 */

	if (tickInterval != 0) {
	    char valueString[PRINT_CHARS];
	    double ticks, maxTicks;

	    /*
	     * Ensure that we will only draw enough of the tick values such
	     * that they don't overlap. We base this off the width that
	     * fromValue would take. Not exact, but better than no constraint.
	     */
................................................................................
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int top)			/* Y-coordinate of top edge of text, specified
				 * in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int x, y, length, width;
    char valueString[PRINT_CHARS];
    Tk_FontMetrics fm;

    x = TkScaleValueToPixel(scalePtr, value);
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = top + fm.ascent;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
................................................................................
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    Pixmap pixmap;
    int result;
    char string[PRINT_CHARS];
    XRectangle drawnArea;
    Tcl_DString buf;

    scalePtr->flags &= ~REDRAW_PENDING;
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
	goto done;
    }







|







 







|







 







|







 







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int rightEdge)		/* X-coordinate of right edge of text,
				 * specified in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int y, width, length;
    char valueString[TCL_DOUBLE_SPACE];
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
................................................................................
	    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
    if (scalePtr->flags & REDRAW_OTHER) {
	/*
	 * Display the tick marks.
	 */

	if (tickInterval != 0) {
	    char valueString[TCL_DOUBLE_SPACE];
	    double ticks, maxTicks;

	    /*
	     * Ensure that we will only draw enough of the tick values such
	     * that they don't overlap. We base this off the width that
	     * fromValue would take. Not exact, but better than no constraint.
	     */
................................................................................
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int top)			/* Y-coordinate of top edge of text, specified
				 * in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int x, y, length, width;
    char valueString[TCL_DOUBLE_SPACE];
    Tk_FontMetrics fm;

    x = TkScaleValueToPixel(scalePtr, value);
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = top + fm.ascent;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
................................................................................
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    Pixmap pixmap;
    int result;
    char string[TCL_DOUBLE_SPACE];
    XRectangle drawnArea;
    Tcl_DString buf;

    scalePtr->flags &= ~REDRAW_PENDING;
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
	goto done;
    }

Changes to jni/sdl2tk/tests/canvText.test.

869
870
871
872
873
874
875

876
877
878
879
880
881
882
    set x2 [lindex $bbox 2]
    set y2 [lindex $bbox 3]
    incr y2
    update
    .c find enclosed 99 99 [expr $x2 + 1] [expr $y2 + 1]
} -cleanup {
    destroy .c

} -result 1

test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup {
    destroy .c
    set c [canvas .c -bg black -width 964]
    pack $c
    $c delete all







>







869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
    set x2 [lindex $bbox 2]
    set y2 [lindex $bbox 3]
    incr y2
    update
    .c find enclosed 99 99 [expr $x2 + 1] [expr $y2 + 1]
} -cleanup {
    destroy .c
    unset -nocomplain bbox x2 y2
} -result 1

test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup {
    destroy .c
    set c [canvas .c -bg black -width 964]
    pack $c
    $c delete all

Changes to jni/sdl2tk/tests/font.test.

8
9
10
11
12
13
14















15



16
17
18
19
20
21
22
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
...
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

















catch {eval font delete [font names]}



deleteWindows
# Toplevel used (in some tests) of the whole file
toplevel .t
wm geom .t +0+0
update idletasks

switch [tk windowingsystem] {
................................................................................
    # (objc == 3) so objPtr = NULL
    font create xyz -family xyz
    lindex [font configure xyz] 1
} -cleanup {
	font delete xyz
} -result xyz
test font-5.5 {font command: configure: get one option} -setup {
    catch {eval font delete [font names]}
} -body {
    # (objc == 4) so objPtr = objv[3]
    font create xyz -family xyz
    font configure xyz -family
	font names
} -cleanup {
	font delete xyz
} -result xyz
test font-5.6 {font command: configure: update existing font} -setup {
    catch {font delete xyz}
} -body {
    # else result = ConfigAttributesObj()
................................................................................
    font configure xyz -style
} -cleanup {
	font delete xyz
} -returnCodes error -result {bad option "-style": must be -family, -size, -weight, -slant, -underline, or -overstrike}


test font-6.1 {font command: create: make up name} -setup {
    catch {eval font delete [font names]}
} -body {
    # (objc < 3) so name = NULL
    font create
    font names
} -cleanup {
    font delete font1
} -result {font1}
test font-6.2 {font command: create: name specified} -setup {
    catch {eval font delete [font names]}
} -body {
    # not (objc < 3)
    font create xyz
    font names
} -cleanup {
	font delete xyz
} -result {xyz}
test font-6.3 {font command: create: name not really specified} -setup {
    catch {eval font delete [font names]}
} -body {
    # (name[0] == '-') so name = NULL
    font create -family xyz
    font names
} -cleanup {
    font delete font1
} -result {font1}
test font-6.4 {font command: create: generate name} -setup {
    catch {eval font delete [font names]}
} -body {
    # (name == NULL)
    font create -family one
    font create -family two
    font create -family three
    font delete font2
    font create -family four
    font configure font2 -family
} -cleanup {
    catch {eval font delete [font names]}
} -result {four}
test font-6.5 {font command: create: bad option creating new font} -setup {
    catch {font delete xyz}
} -body {
    # name was specified so skip = 3 
    font create xyz -xyz times
} -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
test font-6.6 {font command: create: bad option creating new font} -setup {
    catch {eval font delete [font names]}
} -body {
    # name was not specified so skip = 2 
    font create -xyz times
} -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
test font-6.7 {font command: create: already exists} -setup {
    catch {font delete xyz}
} -body {
................................................................................
} -returnCodes error -result {named font "xyz" already exists}

test font-7.1 {font command: delete: arguments} -body {
    # (objc < 3) 
    font delete
} -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"}
test font-7.2 {font command: delete: loop test} -setup {
    catch {eval font delete [font names]}
	set x {}
} -body {
    # for (i = 2; i < objc; i++) 
    font create a -underline 1
    font create b -underline 1
    font create c -underline 1
    font create d -underline 1
    font create e -underline 1
    lappend x [lsort [font names]]
    font delete a e c b
    lappend x [lsort [font names]]
} -cleanup {
    catch {eval font delete [font names]}
} -result {{a b c d e} d}
test font-7.3 {font command: delete: loop test} -setup {
    catch {eval font delete [font names]}
	set x {}
} -body {
    # (namedHashPtr == NULL) in middle of loop
    font create a -underline 1
    font create b -underline 1
    font create c -underline 1
    font create d -underline 1
    font create e -underline 1
    lappend x [lsort [font names]]
    catch {font delete a d q c e b}
    lappend x [lsort [font names]]
} -cleanup {
    catch {eval font delete [font names]}
} -result {{a b c d e} {b c e}}
test font-7.4 {font command: delete: non-existent} -setup {
    catch {font delete xyz}
} -body {
    # (namedHashPtr == NULL) 
    font delete xyz
} -returnCodes error -result {named font "xyz" doesn't exist}
................................................................................


test font-11.1 {font command: names: arguments} -body {
    # (objc != 2)
    font names xyz
} -returnCodes error -result {wrong # args: should be "font names"}
test font-11.2 {font command: names: loop test: no passes} -setup {
    catch {eval font delete [font names]}
} -body {
    font names
} -result {}
test font-11.3 {font command: names: loop test: one pass} -setup {
    catch {eval font delete [font names]}
} -body {
    font create
    font names
} -result {font1}
test font-11.4 {font command: names: loop test: multiple passes} -setup {
    catch {eval font delete [font names]}
} -body {
    font create xyz
    font create abc
    font create def
    lsort [font names]
} -cleanup {
    catch {eval font delete [font names]}
} -result {abc def xyz}
test font-11.5 {font command: names: skip deletePending fonts} -setup {
    destroy .t.f
    catch {eval font delete [font names]}
    pack [label .t.f]
    update
    set x {}
} -body {
    # (nfPtr->deletePending == 0)
    font create xyz
    font create abc
    lappend x [lsort [font names]]
    .t.f config -font xyz
    font delete xyz
    lappend x [font names]
} -cleanup {
    catch {eval font delete [font names]}
} -result {{abc xyz} abc}


test font-12.1 {UpdateDependantFonts procedure: no users} -setup {
    catch {font delete xyz}
} -body {
    # (nfPtr->refCount == 0)
................................................................................


test font-13.1 {CreateNamedFont: new named font} -setup {
    catch {font delete xyz}
	set x {}
} -body {
    # not (new == 0)
    lappend x [font names]
    font create xyz
    lappend x [font names]
} -cleanup {
	font delete xyz
} -result {{} xyz}
test font-13.2 {CreateNamedFont: named font already exists} -setup {
    catch {font delete xyz}
} -body {
    # (new == 0)
................................................................................
    # not (fontPtr == NULL) 
    .t.f config -font fixed
} -result {}
test font-15.8 {Tk_AllocFontFromObj procedure: get native font} -constraints {
	win 
} -setup {
    destroy .t.f
	catch {eval font delete [font names]}
    pack [label .t.f]
    update
} -body {
    # not (fontPtr == NULL) 
    .t.f config -font oemfixed
} -cleanup {
	destroy .t.f
................................................................................
    destroy .t.f
    .t.b cget -font
} -cleanup {
    destroy .t.b
} -result {-family fixed}
test font-17.4 {Tk_FreeFont procedure: named font} -setup {
    destroy .t.f
    catch {eval font delete [font names]}
    pack [label .t.f]
    update
} -body {
    # (fontPtr->namedHashPtr != NULL) 
    font create xyz
    .t.f config -font xyz
    destroy .t.f
    font names
} -result {xyz}
test font-17.5 {Tk_FreeFont procedure: named font} -setup {
    destroy .t.f
    catch {font delete xyz}
    pack [label .t.f]
    update
} -body {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>







 







|




|







 







|



|




|



|




|



|




<









|








|







 







|








|

|

|


|








|

|

|







 







|

|


|


|


|




|

|



|







|


|

|







 







|

|







 







|







 







|







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
...
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands


set defaultfontlist [font names]

proc getnondefaultfonts {} {
    global defaultfontlist
    set nondeffonts [list ]
    foreach afont [font names] {
        if {$afont ni $defaultfontlist} {
            lappend nondeffonts $afont
        }
    }
    set nondeffonts
}

proc clearnondefaultfonts {} {
    foreach afont [getnondefaultfonts] {
        font delete $afont
    }
}

deleteWindows
# Toplevel used (in some tests) of the whole file
toplevel .t
wm geom .t +0+0
update idletasks

switch [tk windowingsystem] {
................................................................................
    # (objc == 3) so objPtr = NULL
    font create xyz -family xyz
    lindex [font configure xyz] 1
} -cleanup {
	font delete xyz
} -result xyz
test font-5.5 {font command: configure: get one option} -setup {
    clearnondefaultfonts
} -body {
    # (objc == 4) so objPtr = objv[3]
    font create xyz -family xyz
    font configure xyz -family
	getnondefaultfonts
} -cleanup {
	font delete xyz
} -result xyz
test font-5.6 {font command: configure: update existing font} -setup {
    catch {font delete xyz}
} -body {
    # else result = ConfigAttributesObj()
................................................................................
    font configure xyz -style
} -cleanup {
	font delete xyz
} -returnCodes error -result {bad option "-style": must be -family, -size, -weight, -slant, -underline, or -overstrike}


test font-6.1 {font command: create: make up name} -setup {
    clearnondefaultfonts
} -body {
    # (objc < 3) so name = NULL
    font create
    getnondefaultfonts
} -cleanup {
    font delete font1
} -result {font1}
test font-6.2 {font command: create: name specified} -setup {
    clearnondefaultfonts
} -body {
    # not (objc < 3)
    font create xyz
    getnondefaultfonts
} -cleanup {
	font delete xyz
} -result {xyz}
test font-6.3 {font command: create: name not really specified} -setup {
    clearnondefaultfonts
} -body {
    # (name[0] == '-') so name = NULL
    font create -family xyz
    getnondefaultfonts
} -cleanup {
    font delete font1
} -result {font1}
test font-6.4 {font command: create: generate name} -setup {

} -body {
    # (name == NULL)
    font create -family one
    font create -family two
    font create -family three
    font delete font2
    font create -family four
    font configure font2 -family
} -cleanup {
    font delete font1 font2 font3
} -result {four}
test font-6.5 {font command: create: bad option creating new font} -setup {
    catch {font delete xyz}
} -body {
    # name was specified so skip = 3 
    font create xyz -xyz times
} -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
test font-6.6 {font command: create: bad option creating new font} -setup {
    clearnondefaultfonts
} -body {
    # name was not specified so skip = 2 
    font create -xyz times
} -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
test font-6.7 {font command: create: already exists} -setup {
    catch {font delete xyz}
} -body {
................................................................................
} -returnCodes error -result {named font "xyz" already exists}

test font-7.1 {font command: delete: arguments} -body {
    # (objc < 3) 
    font delete
} -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"}
test font-7.2 {font command: delete: loop test} -setup {
    clearnondefaultfonts
	set x {}
} -body {
    # for (i = 2; i < objc; i++) 
    font create a -underline 1
    font create b -underline 1
    font create c -underline 1
    font create d -underline 1
    font create e -underline 1
    lappend x [lsort [getnondefaultfonts]]
    font delete a e c b
    lappend x [lsort [getnondefaultfonts]]
} -cleanup {
    getnondefaultfonts
} -result {{a b c d e} d}
test font-7.3 {font command: delete: loop test} -setup {
    clearnondefaultfonts
	set x {}
} -body {
    # (namedHashPtr == NULL) in middle of loop
    font create a -underline 1
    font create b -underline 1
    font create c -underline 1
    font create d -underline 1
    font create e -underline 1
    lappend x [lsort [getnondefaultfonts]]
    catch {font delete a d q c e b}
    lappend x [lsort [getnondefaultfonts]]
} -cleanup {
    clearnondefaultfonts
} -result {{a b c d e} {b c e}}
test font-7.4 {font command: delete: non-existent} -setup {
    catch {font delete xyz}
} -body {
    # (namedHashPtr == NULL) 
    font delete xyz
} -returnCodes error -result {named font "xyz" doesn't exist}
................................................................................


test font-11.1 {font command: names: arguments} -body {
    # (objc != 2)
    font names xyz
} -returnCodes error -result {wrong # args: should be "font names"}
test font-11.2 {font command: names: loop test: no passes} -setup {
    clearnondefaultfonts
} -body {
    getnondefaultfonts
} -result {}
test font-11.3 {font command: names: loop test: one pass} -setup {
    clearnondefaultfonts
} -body {
    font create
    getnondefaultfonts
} -result {font1}
test font-11.4 {font command: names: loop test: multiple passes} -setup {
    clearnondefaultfonts
} -body {
    font create xyz
    font create abc
    font create def
    lsort [getnondefaultfonts]
} -cleanup {
    clearnondefaultfonts
} -result {abc def xyz}
test font-11.5 {font command: names: skip deletePending fonts} -setup {
    destroy .t.f
    clearnondefaultfonts
    pack [label .t.f]
    update
    set x {}
} -body {
    # (nfPtr->deletePending == 0)
    font create xyz
    font create abc
    lappend x [lsort [getnondefaultfonts]]
    .t.f config -font xyz
    font delete xyz
    lappend x [getnondefaultfonts]
} -cleanup {
    clearnondefaultfonts
} -result {{abc xyz} abc}


test font-12.1 {UpdateDependantFonts procedure: no users} -setup {
    catch {font delete xyz}
} -body {
    # (nfPtr->refCount == 0)
................................................................................


test font-13.1 {CreateNamedFont: new named font} -setup {
    catch {font delete xyz}
	set x {}
} -body {
    # not (new == 0)
    lappend x [getnondefaultfonts]
    font create xyz
    lappend x [getnondefaultfonts]
} -cleanup {
	font delete xyz
} -result {{} xyz}
test font-13.2 {CreateNamedFont: named font already exists} -setup {
    catch {font delete xyz}
} -body {
    # (new == 0)
................................................................................
    # not (fontPtr == NULL) 
    .t.f config -font fixed
} -result {}
test font-15.8 {Tk_AllocFontFromObj procedure: get native font} -constraints {
	win 
} -setup {
    destroy .t.f
    clearnondefaultfonts
    pack [label .t.f]
    update
} -body {
    # not (fontPtr == NULL) 
    .t.f config -font oemfixed
} -cleanup {
	destroy .t.f
................................................................................
    destroy .t.f
    .t.b cget -font
} -cleanup {
    destroy .t.b
} -result {-family fixed}
test font-17.4 {Tk_FreeFont procedure: named font} -setup {
    destroy .t.f
    clearnondefaultfonts
    pack [label .t.f]
    update
} -body {
    # (fontPtr->namedHashPtr != NULL) 
    font create xyz
    .t.f config -font xyz
    destroy .t.f
    getnondefaultfonts
} -result {xyz}
test font-17.5 {Tk_FreeFont procedure: named font} -setup {
    destroy .t.f
    catch {font delete xyz}
    pack [label .t.f]
    update
} -body {

Changes to jni/sdl2tk/tests/scale.test.

684
685
686
687
688
689
690





691
692
693
694
695
696
697
....
1352
1353
1354
1355
1356
1357
1358


































1359
1360
1361
1362
1363
1364
    .s get
} -result {1001.23}
test scale-6.20 {ComputeFormat procedure} -body {
    .s configure -length 200 -from 1000 -to 1001.8 -resolution 0 -digits 0
    .s set 1001.23456789
    .s get
} -result {1001.235}





destroy .s


test scale-7.1 {ComputeScaleGeometry procedure} -constraints {
    nonPortable fonts
} -setup {
    deleteWindows
................................................................................
    } msg] $msg
} -cleanup {
    unset ::error
    rename bgerror {}
    destroy .s
} -result {0 {}}




































option clear

# cleanup
cleanupTests
return







>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
....
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
    .s get
} -result {1001.23}
test scale-6.20 {ComputeFormat procedure} -body {
    .s configure -length 200 -from 1000 -to 1001.8 -resolution 0 -digits 0
    .s set 1001.23456789
    .s get
} -result {1001.235}
test scale-6.21 {ComputeFormat procedure} -body {
    .s configure -length 200 -from 1000 -to 1001.8 -resolution 0 -digits 200
    .s set 1001.23456789
    .s get
} -result {1001.235}
destroy .s


test scale-7.1 {ComputeScaleGeometry procedure} -constraints {
    nonPortable fonts
} -setup {
    deleteWindows
................................................................................
    } msg] $msg
} -cleanup {
    unset ::error
    rename bgerror {}
    destroy .s
} -result {0 {}}


test scale-19 {Bug [3529885fff] - Click in through goes in wrong direction} \
    -setup {
        catch {destroy .s}
        catch {destroy .s1 .s2 .s3 .s4}
        unset -nocomplain x1 x2 x3 x4 x y
        scale .s1 -from 0 -to 100 -resolution 1  -variable x1 -digits 4 -orient horizontal -length 100
        scale .s2 -from 0 -to 100 -resolution -1 -variable x2 -digits 4 -orient horizontal -length 100
        scale .s3 -from 100 -to 0 -resolution 1  -variable x3 -digits 4 -orient horizontal -length 100
        scale .s4 -from 100 -to 0 -resolution -1 -variable x4 -digits 4 -orient horizontal -length 100
        pack .s1 .s2 .s3 .s4 -side left
        update
    } \
    -body {
        foreach {x y} [.s1 coord 50] {}
        event generate .s1 <1> -x $x -y $y
        event generate .s1 <ButtonRelease-1> -x $x -y $y
        foreach {x y} [.s2 coord 50] {}
        event generate .s2 <1> -x $x -y $y
        event generate .s2 <ButtonRelease-1> -x $x -y $y
        foreach {x y} [.s3 coord 50] {}
        event generate .s3 <1> -x $x -y $y
        event generate .s3 <ButtonRelease-1> -x $x -y $y
        foreach {x y} [.s4 coord 50] {}
        event generate .s4 <1> -x $x -y $y
        event generate .s4 <ButtonRelease-1> -x $x -y $y
        update
        list $x1 $x2 $x3 $x4
    } \
    -cleanup {
        unset x1 x2 x3 x4 x y
        destroy .s1 .s2 .s3 .s4
    } \
    -result {1.0 1.0 1.0 1.0}

option clear

# cleanup
cleanupTests
return

Changes to jni/sdl2tk/tests/textDisp.test.

23
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39
....
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381

3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
....
3406
3407
3408
3409
3410
3411
3412

3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428

3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444

3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455

proc scrollError args {
    error "scrolling error"
}

# Create entries in the option database to be sure that geometry options
# like border width have predictable values.



option add *Text.borderWidth 2
option add *Text.highlightThickness 2

# The frame .f is needed to make sure that the overall window is always
# fairly wide, even if the text window is very narrow.  This is needed
# because some window managers don't allow the overall width of a window
# to get very narrow.

catch {destroy .f .t}
................................................................................
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list 0.0 [expr {14.0/30}]] 300x50+5+[expr {$fixedDiff + 18}] [list 12 [expr {$fixedDiff + 68}] 7 $fixedHeight]]
test textDisp-29.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f

    .t2.t xview scroll 1 unit
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list [expr {7.0/300}] 0.49] 300x50+-2+[expr {$fixedDiff + 18}] [list 5 [expr {$fixedDiff + 68}] 7 $fixedHeight]]
test textDisp-29.2.1 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap none -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 1\n
    .t2.t insert end [string repeat "abc" 30]

    .t2.t xview scroll 5 unit
    update
    .t2.t xview
} [list [expr {5.0/90}] [expr {25.0/90}]]
test textDisp-29.2.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
................................................................................
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f

    .t2.t xview scroll 2 unit
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list [expr {14.0/300}] [expr {154.0/300}]] 300x50+-9+[expr {$fixedDiff + 18}] {}]
test textDisp-29.2.3 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f

    .t2.t xview scroll 7 pixels
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list [expr {7.0/300}] 0.49] 300x50+-2+[expr {$fixedDiff + 18}] [list 5 [expr {$fixedDiff + 68}] 7 $fixedHeight]]
test textDisp-29.2.4 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f

    .t2.t xview scroll 17 pixels
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list [expr {17.0/300}] [expr {157.0/300}]] 300x50+-12+[expr {$fixedDiff + 18}] {}]
test textDisp-29.2.5 {miscellaneous: can show last character} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 121x141+200+200
    text .t2.t -width 5 -height 5 -font {Arial 10} \
      -wrap none -xscrollcommand ".t2.s set" \
      -bd 2 -highlightthickness 0 -padx 1







<
>
>
|
|







 







|












>



|











>







 







>



|












>



|












>



|







23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
....
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
....
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461

proc scrollError args {
    error "scrolling error"
}

# Create entries in the option database to be sure that geometry options
# like border width have predictable values.

set twbw 2
set twht 2
option add *Text.borderWidth $twbw
option add *Text.highlightThickness $twht

# The frame .f is needed to make sure that the overall window is always
# fairly wide, even if the text window is very narrow.  This is needed
# because some window managers don't allow the overall width of a window
# to get very narrow.

catch {destroy .f .t}
................................................................................
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [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]]
test textDisp-29.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f
    update
    .t2.t xview scroll 1 unit
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [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]]
test textDisp-29.2.1 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap none -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 1\n
    .t2.t insert end [string repeat "abc" 30]
    update
    .t2.t xview scroll 5 unit
    update
    .t2.t xview
} [list [expr {5.0/90}] [expr {25.0/90}]]
test textDisp-29.2.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
................................................................................
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f
    update
    .t2.t xview scroll 2 unit
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list [expr {2.0*$fixedWidth/300}] [expr {22.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1 - 2*$fixedWidth}]+[expr {$twbw + $twht + $fixedHeight + 1}] {}]
test textDisp-29.2.3 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f
    update
    .t2.t xview scroll 7 pixels
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [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]]
test textDisp-29.2.4 {miscellaneous: lines wrap but are still too long} {textfonts} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 +0+0
    text .t2.t -width 20 -height 10 -font $fixedFont \
	    -wrap char -xscrollcommand ".t2.s set"
    pack .t2.t -side top
    scrollbar .t2.s -orient horizontal -command ".t2.t xview"
    pack .t2.s -side bottom -fill x
    .t2.t insert end 123
    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
    .t2.t window create 1.1 -window .t2.t.f
    update
    .t2.t xview scroll 17 pixels
    update
    list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
} [list [list [expr {17.0/300}] [expr {(20.0*$fixedWidth + 17)/300}]] 300x50+[expr {$twbw + $twht + 1 - 17}]+[expr {$twbw + $twht + $fixedHeight + 1}] {}]
test textDisp-29.2.5 {miscellaneous: can show last character} {
    catch {destroy .t2}
    toplevel .t2
    wm geometry .t2 121x141+200+200
    text .t2.t -width 5 -height 5 -font {Arial 10} \
      -wrap none -xscrollcommand ".t2.s set" \
      -bd 2 -highlightthickness 0 -padx 1

Changes to jni/sdl2tk/tests/winDialog.test.

17
18
19
20
21
22
23
















24
25
26
27

28
29
30
31
32
33
34
35
36



37
38
39
40
41
42












43
44
45
46
47
48
49

50
51
52
53
54
55
56
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272




273





274
275
276
277
278


279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324



325
326
327
328
329
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
...
354
355
356
357
358
359
360



361
362
363
364




365








366
367
368
369
370
371
372

373
374
375
376
377
378
379
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
}

# Locale identifier LANG_ENGLISH is 0x09
testConstraint english [expr {
    [llength [info commands testwinlocale]]
    && (([testwinlocale] & 0xff) == 9)
}]

















proc start {arg} {
    set ::tk_dialog 0
    set ::iter_after 0


    after 1 $arg
}

proc then {cmd} {
    set ::command $cmd
    set ::dialogresult {}
    set ::testfont {}




    afterbody
    vwait ::dialogresult
    return $::dialogresult
}

proc afterbody {} {












    if {$::tk_dialog == 0} {
        if {[incr ::iter_after] > 30} {
            set ::dialogresult ">30 iterations waiting on tk_dialog"
            return
        }
        after 150 {afterbody}
        return

    }
    uplevel #0 {set dialogresult [eval $command]}
}

proc Click {button} {
    switch -exact -- $button {
        ok     { set button 1 }
................................................................................
    nt
} -body {
    tk_getOpenFile -foo
} -returnCodes error -result {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}
test winDialog-5.3 {GetFileName: many arguments} -constraints {
    nt testwinevent
} -body {
    start {tk_getOpenFile -initialdir c:/ -parent . -title test -initialfile foo}
    then {
        Click cancel
    }
} -result {0}
test winDialog-5.4 {GetFileName: Tcl_GetIndexFromObj() != TCL_OK} -constraints {
    nt
} -body {
................................................................................
    nt
} -body {
    tk_getOpenFile -initialdir bar -title
} -returnCodes error -result {value for "-title" missing}
test winDialog-5.7 {GetFileName: extension begins with .} -constraints {
    nt testwinevent
} -body {
#    if (string[0] == '.') {
#    string++;
#    }

    start {set x [tk_getSaveFile -defaultextension .foo -title Save]}
    set msg {}
    then {
	if {[catch {SetText 0x47C bar} msg]} {
	    Click cancel
	} else {
	    Click ok
	}
    }
    string totitle $x$msg
} -cleanup {
    unset msg
} -result [string totitle [file join [pwd] bar.foo]]
test winDialog-5.8 {GetFileName: extension doesn't begin with .} -constraints {
    nt testwinevent
} -body {
    start {set x [tk_getSaveFile -defaultextension foo -title Save]}
    set msg {}
    then {
	if {[catch {SetText 0x47C bar} msg]} {
	    Click cancel
	} else {
	    Click ok
	}
    }
    string totitle $x$msg
} -cleanup {
    unset msg
} -result [string totitle [file join [pwd] bar.foo]]
test winDialog-5.9 {GetFileName: file types} -constraints {
    nt testwinevent
} -body {
#        case FILE_TYPES:

    start {tk_getSaveFile -filetypes {{"foo files" .foo FOOF}} -title Foo}




    then {





        set x [GetText 0x470]
        Click cancel
    }
    return $x
} -result {foo files (*.foo)}


test winDialog-5.10 {GetFileName: file types: MakeFilter() fails} -constraints {
    nt
} -body {
#        if (MakeFilter(interp, string, &utfFilterString) != TCL_OK)

    tk_getSaveFile -filetypes {{"foo" .foo FOO}}
} -returnCodes error -result {bad Macintosh file type "FOO"}
if {[info exists ::env(TEMP)]} {
test winDialog-5.11 {GetFileName: initial directory} -constraints {
    nt testwinevent
} -body {
#        case FILE_INITDIR:

    start {set x [tk_getSaveFile \
                      -initialdir [file normalize $::env(TEMP)] \
                      -initialfile "12x 455" -title Foo]}
    then {
        Click ok
    }
    return $x
} -result [file join [file normalize $::env(TEMP)] "12x 455"]
}
test winDialog-5.12 {GetFileName: initial directory: Tcl_TranslateFilename()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string, &ds) == NULL)

    tk_getOpenFile -initialdir ~12x/455
} -returnCodes error -result {user "12x" doesn't exist}
................................................................................
} -body {
#        case FILE_INITFILE:

    start {set x [tk_getSaveFile -initialfile "12x 456" -title Foo]}
    then {
        Click ok
    }
    string totitle $x
} -result [string totitle [file join [pwd] "12x 456"]]
test winDialog-5.14 {GetFileName: initial file: Tcl_TranslateFileName()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string, &ds) == NULL)
    tk_getOpenFile -initialfile ~12x/455
} -returnCodes error -result {user "12x" doesn't exist}



test winDialog-5.15 {GetFileName: initial file: long name} -constraints {
    nt testwinevent
} -body {
    start {
        set dialogresult [catch {
            tk_getSaveFile -initialfile [string repeat a 1024] -title Long
        } x]
    }
    then {
        Click ok
    }
    list $dialogresult [string match "invalid filename *" $x]
} -result {1 1}

test winDialog-5.16 {GetFileName: parent} -constraints {
    nt
} -body {
#        case FILE_PARENT:

    toplevel .t
    set x 0
................................................................................
#        case FILE_TITLE:
   
    start {tk_getOpenFile -title Narf}
    then {
        Click cancel
    }
} -result {0}



test winDialog-5.18 {GetFileName: no filter specified} -constraints {
    nt testwinevent
} -body {
#    if (ofn.lpstrFilter == NULL)













    start {tk_getOpenFile -title Filter}
    then {
    set x [GetText 0x470]
        Click cancel
    }
    return $x
} -result {All Files (*.*)}

test winDialog-5.19 {GetFileName: parent HWND doesn't yet exist} -constraints {
    nt
} -setup {
    destroy .t
} -body {
#    if (Tk_WindowId(parent) == None)

................................................................................
    start {tk_getSaveFile -title Save}
    then {
        set x [GetText ok]
        Click cancel
    }
    return $x
} -result {&Save}
if {[info exists ::env(TEMP)]} {
test winDialog-5.23 {GetFileName: convert \ to /} -constraints {
    nt testwinevent
} -body {
    set msg {}
    start {set x [tk_getSaveFile -title Back]}
    then {
	if {[catch {SetText 0x47C [file nativename \
		[file join [file normalize $::env(TEMP)] "12x 457"]]} msg]} {
	    Click cancel
	} else {
	    Click ok
	}
    }
    return $x$msg
} -cleanup {
    unset msg
} -result [file join [file normalize $::env(TEMP)] "12x 457"]
}
test winDialog-5.24 {GetFileName: file types: MakeFilter() succeeds} -constraints {
    nt
} -body {
    # MacOS type that is correct, but has embedded nulls.

    start {set x [catch {tk_getSaveFile -filetypes {{"foo" .foo {\0\0\0\0}}}}]}
    then {
................................................................................
} -body {
    tk_chooseDirectory -foo
} -returnCodes error -result {bad option "-foo": must be -initialdir, -mustexist, -parent, or -title}
test winDialog-9.3 {Tk_ChooseDirectoryObjCmd: many arguments} -constraints {
    nt testwinevent
} -body {
    start {
    tk_chooseDirectory -initialdir c:/ -mustexist 1 -parent . -title test
    }
    then {
        Click cancel
    }
} -result {0}
test winDialog-9.4 {Tk_ChooseDirectoryObjCmd: Tcl_GetIndexFromObj() != TCL_OK} -constraints {
    nt
................................................................................
    tk_chooseDirectory -initialdir bar -title
} -returnCodes error -result {value for "-title" missing}
test winDialog-9.7 {Tk_ChooseDirectoryObjCmd: -initialdir} -constraints {
    nt testwinevent
} -body {
#        case DIR_INITIAL:

    start {set x [tk_chooseDirectory -initialdir c:/ -title Foo]}
    then {
        Click ok
    }
    string tolower [set x]
} -result {c:/}
test winDialog-9.8 {Tk_ChooseDirectoryObjCmd: initial directory: Tcl_TranslateFilename()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string,
#            &utfDirString) == NULL)
   
    tk_chooseDirectory -initialdir ~12x/455







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>









>
>
>
|





>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
>







 







|







 







<
<
<
<



|





|


|






|





|


|



|
|

>
>
>
>
|
>
>
>
>
>
|
|
|
<
|
>
>







<




|
|
|





|
<







 







|
|






>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
>







 







>
>
>
|
|
|
|
>
>
>
>
|
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
>







 







<






|
|








|
<







 







|







 







|




|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
260
261
262
263
264
265
266




267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
...
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
...
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
}

# Locale identifier LANG_ENGLISH is 0x09
testConstraint english [expr {
    [llength [info commands testwinlocale]]
    && (([testwinlocale] & 0xff) == 9)
}]

proc vista? {{prevista 0} {postvista 1}} {
    lassign [split $::tcl_platform(osVersion) .] major
    return [expr {$major >= 6 ? $postvista : $prevista}]
}

# What directory to use in initialdir tests. Old code used to use
# c:/. However, on Vista/later that is a protected directory if you
# are not running privileged. Moreover, not everyone has a drive c:
# but not having a TEMP would break a lot Windows programs
proc initialdir {} {
    # file join to return in Tcl canonical format (/ separator, not \)
    #return [file join $::env(TEMP)]
    return [tcltest::temporaryDirectory]
}


proc start {arg} {
    set ::tk_dialog 0
    set ::iter_after 0
    set ::dialogclass "#32770"

    after 1 $arg
}

proc then {cmd} {
    set ::command $cmd
    set ::dialogresult {}
    set ::testfont {}

    # Do not make the delay too short. The newer Vista dialogs take
    # time to come up. Even if the testforwindow returns true, the
    # controls are not ready to accept messages
    after 500 afterbody
    vwait ::dialogresult
    return $::dialogresult
}

proc afterbody {} {
    # On Vista and later, using the new file dialogs we have to find
    # the window using its title as tk_dialog will not be set at the C level
    if {[vista?]} {
        if {[catch {testfindwindow "" $::dialogclass} ::tk_dialog]} {
            if {[incr ::iter_after] > 30} {
                set ::dialogresult ">30 iterations waiting on tk_dialog"
                return
            }
            after 150 {afterbody}
            return
        }
    } else {
        if {$::tk_dialog == 0} {
            if {[incr ::iter_after] > 30} {
                set ::dialogresult ">30 iterations waiting on tk_dialog"
                return
            }
            after 150 {afterbody}
            return
        }
    }
    uplevel #0 {set dialogresult [eval $command]}
}

proc Click {button} {
    switch -exact -- $button {
        ok     { set button 1 }
................................................................................
    nt
} -body {
    tk_getOpenFile -foo
} -returnCodes error -result {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}
test winDialog-5.3 {GetFileName: many arguments} -constraints {
    nt testwinevent
} -body {
    start {tk_getOpenFile -initialdir [initialdir] -parent . -title test -initialfile foo}
    then {
        Click cancel
    }
} -result {0}
test winDialog-5.4 {GetFileName: Tcl_GetIndexFromObj() != TCL_OK} -constraints {
    nt
} -body {
................................................................................
    nt
} -body {
    tk_getOpenFile -initialdir bar -title
} -returnCodes error -result {value for "-title" missing}
test winDialog-5.7 {GetFileName: extension begins with .} -constraints {
    nt testwinevent
} -body {




    start {set x [tk_getSaveFile -defaultextension .foo -title Save]}
    set msg {}
    then {
	if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} {
	    Click cancel
	} else {
	    Click ok
	}
    }
    set x "[file tail $x]$msg"
} -cleanup {
    unset msg
} -result bar.foo
test winDialog-5.8 {GetFileName: extension doesn't begin with .} -constraints {
    nt testwinevent
} -body {
    start {set x [tk_getSaveFile -defaultextension foo -title Save]}
    set msg {}
    then {
	if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} {
	    Click cancel
	} else {
	    Click ok
	}
    }
    set x "[file tail $x]$msg"
} -cleanup {
    unset msg
} -result bar.foo
test winDialog-5.9 {GetFileName: file types} -constraints {
    nt testwinevent
} -body {
    #        case FILE_TYPES:
    
    start {tk_getSaveFile -filetypes {{"foo files" .foo FOOF}} -title Foo}
    # XXX - currently disabled for vista style dialogs because the file
    # types control has no control ID and we don't have a mechanism to
    # locate it.
    if {[vista?]} {
        then {
            Click cancel
        }
        return 1
    } else {
        then {
            set x [GetText 0x470]
            Click cancel
        }

        return [string equal $x {foo files (*.foo)}]
    }
} -result 1
test winDialog-5.10 {GetFileName: file types: MakeFilter() fails} -constraints {
    nt
} -body {
#        if (MakeFilter(interp, string, &utfFilterString) != TCL_OK)

    tk_getSaveFile -filetypes {{"foo" .foo FOO}}
} -returnCodes error -result {bad Macintosh file type "FOO"}

test winDialog-5.11 {GetFileName: initial directory} -constraints {
    nt testwinevent
} -body {
#        case FILE_INITDIR:
    unset -nocomplain x
    start {set x [tk_getSaveFile \
                      -initialdir [initialdir] \
                      -initialfile "12x 455" -title Foo]}
    then {
        Click ok
    }
    return $x
} -result [file join [initialdir] "12x 455"]

test winDialog-5.12 {GetFileName: initial directory: Tcl_TranslateFilename()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string, &ds) == NULL)

    tk_getOpenFile -initialdir ~12x/455
} -returnCodes error -result {user "12x" doesn't exist}
................................................................................
} -body {
#        case FILE_INITFILE:

    start {set x [tk_getSaveFile -initialfile "12x 456" -title Foo]}
    then {
        Click ok
    }
    file tail $x
} -result "12x 456"
test winDialog-5.14 {GetFileName: initial file: Tcl_TranslateFileName()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string, &ds) == NULL)
    tk_getOpenFile -initialfile ~12x/455
} -returnCodes error -result {user "12x" doesn't exist}
if {![vista?]} {
    # XXX - disabled for Vista because the new dialogs allow long file
    # names to be specified but force the user to change it.
    test winDialog-5.15 {GetFileName: initial file: long name} -constraints {
        nt testwinevent
    } -body {
        start {
            set dialogresult [catch {
                tk_getSaveFile -initialfile [string repeat a 1024] -title Long
            } x]
        }
        then {
            Click ok
        }
        list $dialogresult [string match "invalid filename *" $x]
    } -result {1 1}
}
test winDialog-5.16 {GetFileName: parent} -constraints {
    nt
} -body {
#        case FILE_PARENT:

    toplevel .t
    set x 0
................................................................................
#        case FILE_TITLE:
   
    start {tk_getOpenFile -title Narf}
    then {
        Click cancel
    }
} -result {0}
if {[vista?]} {
    # In the newer file dialogs, the file type widget does not even exist
    # if no file types specified
    test winDialog-5.18 {GetFileName: no filter specified} -constraints {
        nt testwinevent
    } -body {
        #    if (ofn.lpstrFilter == NULL)
        start {tk_getOpenFile -title Filter}
        then {
            catch {set x [GetText 0x470]} y
            Click cancel
        }
        return $y
    } -result {Could not find control with id 1136}
} else {
    test winDialog-5.18 {GetFileName: no filter specified} -constraints {
        nt testwinevent
    } -body {
        #    if (ofn.lpstrFilter == NULL)

        start {tk_getOpenFile -title Filter}
        then {
            set x [GetText 0x470]
            Click cancel
        }
        return $x
    } -result {All Files (*.*)}
}
test winDialog-5.19 {GetFileName: parent HWND doesn't yet exist} -constraints {
    nt
} -setup {
    destroy .t
} -body {
#    if (Tk_WindowId(parent) == None)

................................................................................
    start {tk_getSaveFile -title Save}
    then {
        set x [GetText ok]
        Click cancel
    }
    return $x
} -result {&Save}

test winDialog-5.23 {GetFileName: convert \ to /} -constraints {
    nt testwinevent
} -body {
    set msg {}
    start {set x [tk_getSaveFile -title Back]}
    then {
	if {[catch {SetText [vista? 0x47C 0x3e9] [file nativename \
		[file join [initialdir] "12x 457"]]} msg]} {
	    Click cancel
	} else {
	    Click ok
	}
    }
    return $x$msg
} -cleanup {
    unset msg
} -result [file join [initialdir] "12x 457"]

test winDialog-5.24 {GetFileName: file types: MakeFilter() succeeds} -constraints {
    nt
} -body {
    # MacOS type that is correct, but has embedded nulls.

    start {set x [catch {tk_getSaveFile -filetypes {{"foo" .foo {\0\0\0\0}}}}]}
    then {
................................................................................
} -body {
    tk_chooseDirectory -foo
} -returnCodes error -result {bad option "-foo": must be -initialdir, -mustexist, -parent, or -title}
test winDialog-9.3 {Tk_ChooseDirectoryObjCmd: many arguments} -constraints {
    nt testwinevent
} -body {
    start {
        tk_chooseDirectory -initialdir [initialdir] -mustexist 1 -parent . -title test
    }
    then {
        Click cancel
    }
} -result {0}
test winDialog-9.4 {Tk_ChooseDirectoryObjCmd: Tcl_GetIndexFromObj() != TCL_OK} -constraints {
    nt
................................................................................
    tk_chooseDirectory -initialdir bar -title
} -returnCodes error -result {value for "-title" missing}
test winDialog-9.7 {Tk_ChooseDirectoryObjCmd: -initialdir} -constraints {
    nt testwinevent
} -body {
#        case DIR_INITIAL:

    start {set x [tk_chooseDirectory -initialdir [initialdir] -title Foo]}
    then {
        Click ok
    }
    string tolower [set x]
} -result [string tolower [initialdir]]
test winDialog-9.8 {Tk_ChooseDirectoryObjCmd: initial directory: Tcl_TranslateFilename()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string,
#            &utfDirString) == NULL)
   
    tk_chooseDirectory -initialdir ~12x/455

Changes to jni/sdl2tk/unix/configure.

1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
....
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
....
5515
5516
5517
5518
5519
5520
5521


5522





5523
5524
5525
5526
5527
5528
5529
....
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
....
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835




TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".2"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

................................................................................
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a'
	    TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a'
	    echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
if test "${ac_cv_cygwin+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
................................................................................
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)


		SHLIB_CFLAGS="-fPIC"





		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		if test $doRpath = yes; then

		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname=\$@"
	    TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$@"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then

        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        if test "${SHLIB_SUFFIX}" = ".dll"; then

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"

else








|







 







|
<







 







>
>
|
>
>
>
>
>







 







|
<







 







|







1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
....
4848
4849
4850
4851
4852
4853
4854
4855

4856
4857
4858
4859
4860
4861
4862
....
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
....
5588
5589
5590
5591
5592
5593
5594
5595

5596
5597
5598
5599
5600
5601
5602
....
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840




TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".3"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

................................................................................
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a"

	    echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
if test "${ac_cv_cygwin+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
................................................................................
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)
		case "$arch" in
		alpha|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)
		    SHLIB_CFLAGS="-fpic"
		    ;;
		esac
		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		if test $doRpath = yes; then

		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@"

	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
................................................................................
fi

    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then

        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        if test "${SHLIB_SUFFIX}" = ".dll"; then

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"

else

Changes to jni/sdl2tk/unix/configure.in.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    /* override */ #undef PACKAGE_TARNAME
    #endif /* _TKCONFIG */])
])

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".2"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------








|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    /* override */ #undef PACKAGE_TARNAME
    #endif /* _TKCONFIG */])
])

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".3"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

Changes to jni/sdl2tk/unix/tcl.m4.

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
....
1472
1473
1474
1475
1476
1477
1478


1479





1480
1481
1482
1483
1484
1485
1486
....
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
....
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$[@].a'
	    TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$[@].a'
	    AC_CACHE_CHECK(for Cygwin version of gcc,
		ac_cv_cygwin,
		AC_TRY_COMPILE([
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		], [],
................................................................................
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)


		SHLIB_CFLAGS="-fPIC"





		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		AS_IF([test $doRpath = yes], [
		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
................................................................................
	    	LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname=\$[@]"
	    TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
................................................................................
	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
    AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
	UNSHARED_LIB_SUFFIX='${VERSION}.a'])
    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
        ], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
        ])
    ], [







|
<







 







>
>
|
>
>
>
>
>







 







|
<







 







|







1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
....
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
....
1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
....
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"

	    AC_CACHE_CHECK(for Cygwin version of gcc,
		ac_cv_cygwin,
		AC_TRY_COMPILE([
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		], [],
................................................................................
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)
		case "$arch" in
		alpha|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)
		    SHLIB_CFLAGS="-fpic"
		    ;;
		esac
		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		AS_IF([test $doRpath = yes], [
		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
................................................................................
	    	LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"

	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
................................................................................
	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
    AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
	UNSHARED_LIB_SUFFIX='${VERSION}.a'])
    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
        ], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
        ])
    ], [

Changes to jni/sdl2tk/unix/tk.spec.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This file is the basis for a binary Tk Linux RPM.

%{!?directory:%define directory /usr/local}

Name:          tk
Summary:       Tk graphical toolkit for the Tcl scripting language.
Version:       8.6.2
Release:       2
License:       BSD
Group:         Development/Languages
Source:        http://prdownloads.sourceforge.net/tcl/tk%{version}-src.tar.gz
URL:           http://www.tcl.tk/
Buildroot:     /var/tmp/%{name}%{version}
Buildrequires: XFree86-devel tcl >= %version






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This file is the basis for a binary Tk Linux RPM.

%{!?directory:%define directory /usr/local}

Name:          tk
Summary:       Tk graphical toolkit for the Tcl scripting language.
Version:       8.6.3
Release:       2
License:       BSD
Group:         Development/Languages
Source:        http://prdownloads.sourceforge.net/tcl/tk%{version}-src.tar.gz
URL:           http://www.tcl.tk/
Buildroot:     /var/tmp/%{name}%{version}
Buildrequires: XFree86-devel tcl >= %version

Changes to jni/sdl2tk/unix/tkUnixScale.c.

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int rightEdge)		/* X-coordinate of right edge of text,
				 * specified in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int y, width, length;
    char valueString[PRINT_CHARS];
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
................................................................................
	    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
    if (scalePtr->flags & REDRAW_OTHER) {
	/*
	 * Display the tick marks.
	 */

	if (tickInterval != 0) {
	    char valueString[PRINT_CHARS];
	    double ticks, maxTicks;

	    /*
	     * Ensure that we will only draw enough of the tick values such
	     * that they don't overlap. We base this off the width that
	     * fromValue would take. Not exact, but better than no constraint.
	     */
................................................................................
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int top)			/* Y-coordinate of top edge of text, specified
				 * in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int x, y, length, width;
    char valueString[PRINT_CHARS];
    Tk_FontMetrics fm;

    x = TkScaleValueToPixel(scalePtr, value);
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = top + fm.ascent;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
................................................................................
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    Pixmap pixmap;
    int result;
    char string[PRINT_CHARS];
    XRectangle drawnArea;
    Tcl_DString buf;

    scalePtr->flags &= ~REDRAW_PENDING;
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
	goto done;
    }







|







 







|







 







|







 







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int rightEdge)		/* X-coordinate of right edge of text,
				 * specified in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int y, width, length;
    char valueString[TCL_DOUBLE_SPACE];
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
................................................................................
	    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
    if (scalePtr->flags & REDRAW_OTHER) {
	/*
	 * Display the tick marks.
	 */

	if (tickInterval != 0) {
	    char valueString[TCL_DOUBLE_SPACE];
	    double ticks, maxTicks;

	    /*
	     * Ensure that we will only draw enough of the tick values such
	     * that they don't overlap. We base this off the width that
	     * fromValue would take. Not exact, but better than no constraint.
	     */
................................................................................
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int top)			/* Y-coordinate of top edge of text, specified
				 * in pixels. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    int x, y, length, width;
    char valueString[TCL_DOUBLE_SPACE];
    Tk_FontMetrics fm;

    x = TkScaleValueToPixel(scalePtr, value);
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = top + fm.ascent;
    sprintf(valueString, scalePtr->format, value);
    length = (int) strlen(valueString);
................................................................................
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    Pixmap pixmap;
    int result;
    char string[TCL_DOUBLE_SPACE];
    XRectangle drawnArea;
    Tcl_DString buf;

    scalePtr->flags &= ~REDRAW_PENDING;
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
	goto done;
    }

Changes to jni/sdl2tk/win/configure.

1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".2"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then







|







1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".3"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then

Changes to jni/sdl2tk/win/configure.in.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".2"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".3"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then

Changes to jni/sdl2tk/win/tkWinButton.c.

1261
1262
1263
1264
1265
1266
1267







1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
	 * cleared the REDRAW_PENDING flag.
	 */

	Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr);
	return 0;
    }
    case BN_CLICKED: {







	int code;
	Tcl_Interp *interp = butPtr->info.interp;

	if (butPtr->info.state != STATE_DISABLED) {
	    Tcl_Preserve((ClientData)interp);
	    code = TkInvokeButton((TkButton*)butPtr);
	    if (code != TCL_OK && code != TCL_CONTINUE
		    && code != TCL_BREAK) {
		Tcl_AddErrorInfo(interp, "\n    (button invoke)");
		Tcl_BackgroundException(interp, code);
	    }
	    Tcl_Release((ClientData)interp);
	}
	Tcl_ServiceAll();
	return 0;

    }

    default:
	if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	    return result;
	}
    }







>
>
>
>
>
>
>
|
|

|
|
|
|
|
|
|
|
|
|
|
|
>







1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
	 * cleared the REDRAW_PENDING flag.
	 */

	Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr);
	return 0;
    }
    case BN_CLICKED: {
	/*
	 * OOPS: chromium fires WM_NULL regularly to ping if plugin is still
	 * alive. When using an external window (i.e. via the tcl plugin), this
	 * causes all buttons to fire once a second, so we need to make sure
	 * that we are not dealing with the chromium life check.
	*/
        if (wParam != 0 || lParam != 0) {
	    int code;
	    Tcl_Interp *interp = butPtr->info.interp;

	    if (butPtr->info.state != STATE_DISABLED) {
		Tcl_Preserve((ClientData)interp);
		code = TkInvokeButton((TkButton*)butPtr);
		if (code != TCL_OK && code != TCL_CONTINUE
			&& code != TCL_BREAK) {
		    Tcl_AddErrorInfo(interp, "\n    (button invoke)");
		    Tcl_BackgroundException(interp, code);
		}
		Tcl_Release((ClientData)interp);
	    }
	    Tcl_ServiceAll();
	    return 0;
	}
    }

    default:
	if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	    return result;
	}
    }

Changes to jni/sdl2tk/win/tkWinDialog.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23


24
25


26
27
28

29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
..
53
54
55
56
57
58
59




60
61
62
63
64
65
66
...
154
155
156
157
158
159
160
161













































































































































































































































































































































































































162
163
164
165
166
167
168








169
170
171




172
173
174
175
176
177
178
179
180




























































181
182
183
184
185
186
187
...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531

532




















533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561

562
563
564
565
566
567
568
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598












599
600
601
602
603
604
605
606





607






608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657

658
659
660
661
662
663















664
665











































































































































































































































666










667



668
669

































































































670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709



710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
...
888
889
890
891
892
893
894


895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911











































912
913
914
915
916
917
918
...
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
....
1228
1229
1230
1231
1232
1233
1234











































































































































1235
1236
1237
1238
1239
1240
1241
....
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322

1323


1324
1325

1326
1327
1328
1329
1330



1331
1332




1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
....
1451
1452
1453
1454
1455
1456
1457




1458
1459
1460
1461
1462
1463
1464
....
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
 */

#include "tkWinInt.h"
#include "tkFileFilter.h"
#include "tkFont.h"

#include <commdlg.h>		/* includes common dialog functionality */
#ifdef _MSC_VER
#   pragma comment (lib, "comdlg32.lib")
#endif
#include <dlgs.h>		/* includes common dialog template defines */
#include <cderr.h>		/* includes the common dialog error codes */

#include <shlobj.h>		/* includes SHBrowseForFolder */


#ifdef _MSC_VER
#   pragma comment (lib, "shell32.lib")


#endif

/* These needed for compilation with VC++ 5.2 */

#ifndef BIF_EDITBOX
#define BIF_EDITBOX 0x10
#endif

#ifndef BIF_VALIDATE
#define BIF_VALIDATE 0x0020
#endif


#ifndef BIF_NEWDIALOGSTYLE
#define BIF_NEWDIALOGSTYLE 0x0040
#endif

#ifndef BFFM_VALIDATEFAILED
#ifdef UNICODE
#define BFFM_VALIDATEFAILED 4
................................................................................
    Tcl_Interp *debugInterp;	/* Interpreter to used for debugging. */
    UINT WM_LBSELCHANGED;	/* Holds a registered windows event used for
				 * communicating between the Directory Chooser
				 * dialog and its hook proc. */
    HHOOK hMsgBoxHook;		/* Hook proc for tk_messageBox and the */
    HICON hSmallIcon;		/* icons used by a parent to be used in */
    HICON hBigIcon;		/* the message box */




} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following structures are used by Tk_MessageBoxCmd() to parse arguments
 * and return results.
 */
................................................................................
				 * for setting the "tk_dialog" variable. */
    int dynFileBufferSize;	/* Dynamic filename buffer size, stored to
				 * avoid shrinking and expanding the buffer
				 * when selection changes */
    TCHAR *dynFileBuffer;	/* Dynamic filename buffer */
} OFNData;

/*













































































































































































































































































































































































































 * Definitions of functions used only in this file.
 */

static UINT APIENTRY	ChooseDirectoryValidateProc(HWND hdlg, UINT uMsg,
			    LPARAM wParam, LPARAM lParam);
static UINT CALLBACK	ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam,
			    LPARAM lParam);








static int 		GetFileName(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], int isOpen);




static int 		MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr,
			    Tcl_DString *dsPtr, Tcl_Obj *initialPtr,
			    int *indexPtr);
static UINT APIENTRY	OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam,
			    LPARAM lParam);
static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam);
static void		SetTkDialog(ClientData clientData);
static const char *ConvertExternalFilename(TCHAR *filename,
			    Tcl_DString *dsPtr);




























































 
/*
 *-------------------------------------------------------------------------
 *
 * EatSpuriousMessageBugFix --
 *
 *	In the file open/save dialog, double clicking on a list item causes
................................................................................
int
Tk_GetOpenFileObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return GetFileName(clientData, interp, objc, objv, 1);
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tk_GetSaveFileCmd --
 *
................................................................................
int
Tk_GetSaveFileObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return GetFileName(clientData, interp, objc, objv, 0);
}
 
/*
 *----------------------------------------------------------------------
 *
 * GetFileName --
 *
 *	Calls GetOpenFileName() or GetSaveFileName().
 *
 * Results:
 *	See user documentation.
 *
 * Side effects:
 *	See user documentation.

 *




















 *----------------------------------------------------------------------
 */

static int
GetFileName(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    int open)			/* 1 to call GetOpenFileName(), 0 to call
				 * GetSaveFileName(). */
{
    OPENFILENAME ofn;
    TCHAR file[TK_MULTI_MAX_PATH];
    OFNData ofnData;
    int cdlgerr;
    int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0;
    int confirmOverwrite = 1;
    const char *extension = NULL, *title = NULL;
    Tk_Window tkwin = clientData;
    HWND hWnd;
    Tcl_Obj *filterObj = NULL, *initialTypeObj = NULL, *typeVariableObj = NULL;
    Tcl_DString utfFilterString, utfDirString, ds;
    Tcl_DString extString, filterString, dirString, titleString;
    ThreadSpecificData *tsdPtr =
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    enum options {
	FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, FILE_PARENT,
	FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW

    };
    struct Options {
	const char *name;
	enum options value;
    };
    static const struct Options saveOptions[] = {
	{"-confirmoverwrite",	FILE_CONFIRMOW},
................................................................................
	{"-initialfile",	FILE_INITFILE},
	{"-multiple",		FILE_MULTIPLE},
	{"-parent",		FILE_PARENT},
	{"-title",		FILE_TITLE},
	{"-typevariable",	FILE_TYPEVARIABLE},
	{NULL,			FILE_DEFAULT/*ignored*/ }
    };
    const struct Options *const options = open ? openOptions : saveOptions;

    file[0] = '\0';
    ZeroMemory(&ofnData, sizeof(OFNData));
    Tcl_DStringInit(&utfFilterString);
    Tcl_DStringInit(&utfDirString);

    /*
     * Parse the arguments.
     */













    for (i = 1; i < objc; i += 2) {
	int index;
	const char *string;
	Tcl_Obj *valuePtr = objv[i + 1];

	if (Tcl_GetIndexFromObjStruct(interp, objv[i], options,
		sizeof(struct Options), "option", 0, &index) != TCL_OK) {





	    goto end;






	} else if (i + 1 == objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "value for \"%s\" missing", options[index].name));
	    Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
	    goto end;
	}

	string = Tcl_GetString(valuePtr);
	switch (options[index].value) {
	case FILE_DEFAULT:
	    if (string[0] == '.') {
		string++;
	    }
	    extension = string;
	    break;
	case FILE_TYPES:
	    filterObj = valuePtr;
	    break;
	case FILE_INITDIR:
	    Tcl_DStringFree(&utfDirString);
	    if (Tcl_TranslateFileName(interp, string,
		    &utfDirString) == NULL) {
		goto end;
	    }
	    break;
	case FILE_INITFILE:
	    if (Tcl_TranslateFileName(interp, string, &ds) == NULL) {
		goto end;
	    }
	    Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(),
		    Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL,

		    (char *) file, sizeof(file), NULL, NULL, NULL);
	    Tcl_DStringFree(&ds);
	    break;
	case FILE_PARENT:
	    tkwin = Tk_NameToWindow(interp, string, tkwin);
	    if (tkwin == NULL) {
		goto end;
	    }
	    break;
	case FILE_TITLE:
	    title = string;

	    break;
	case FILE_TYPEVARIABLE:
	    typeVariableObj = valuePtr;
	    initialTypeObj = Tcl_ObjGetVar2(interp, typeVariableObj, NULL,
		    TCL_GLOBAL_ONLY);
	    break;
	case FILE_MULTIPLE:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr, &multi) != TCL_OK) {

		return TCL_ERROR;
	    }
	    break;
	case FILE_CONFIRMOW:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr,
		    &confirmOverwrite) != TCL_OK) {















		return TCL_ERROR;
	    }











































































































































































































































	    break;










	}



    }


































































































    if (MakeFilter(interp, filterObj, &utfFilterString, initialTypeObj,
	    &filterIndex) != TCL_OK) {
	goto end;
    }

    Tk_MakeWindowExist(tkwin);
    hWnd = Tk_GetHWND(Tk_WindowId(tkwin));

    ZeroMemory(&ofn, sizeof(OPENFILENAME));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hWnd;
    ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
    ofn.lpstrFile = file;
    ofn.nMaxFile = TK_MULTI_MAX_PATH;
    ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR
	    | OFN_EXPLORER | OFN_ENABLEHOOK| OFN_ENABLESIZING;
    ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
    ofn.lCustData = (LPARAM) &ofnData;

    if (open != 0) {
	ofn.Flags |= OFN_FILEMUSTEXIST;
    } else if (confirmOverwrite) {
	ofn.Flags |= OFN_OVERWRITEPROMPT;
    }
    if (tsdPtr->debugFlag != 0) {
	ofnData.interp = interp;
    }
    if (multi != 0) {
	ofn.Flags |= OFN_ALLOWMULTISELECT;

	/*
	 * Starting buffer size. The buffer will be expanded by the OFN dialog
	 * procedure when necessary
	 */

	ofnData.dynFileBufferSize = 512;
	ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR));
    }

    if (extension != NULL) {



	Tcl_WinUtfToTChar(extension, -1, &extString);
	ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString);
    }

    Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString),
	    Tcl_DStringLength(&utfFilterString), &filterString);
    ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString);
    ofn.nFilterIndex = filterIndex;

    if (Tcl_DStringValue(&utfDirString)[0] != '\0') {
	Tcl_WinUtfToTChar(Tcl_DStringValue(&utfDirString),
		Tcl_DStringLength(&utfDirString), &dirString);
    } else {
	/*
	 * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure
	 * that we set the [pwd] if the user didn't specify anything else.
	 */

	Tcl_DString cwd;

	Tcl_DStringFree(&utfDirString);
	if ((Tcl_GetCwd(interp, &utfDirString) == NULL) ||
		(Tcl_TranslateFileName(interp,
			Tcl_DStringValue(&utfDirString), &cwd) == NULL)) {
	    Tcl_ResetResult(interp);
	} else {
	    Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd),
		    Tcl_DStringLength(&cwd), &dirString);
	}
	Tcl_DStringFree(&cwd);
    }
    ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString);

    if (title != NULL) {
	Tcl_WinUtfToTChar(title, -1, &titleString);
	ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString);
    }

    /*
     * Popup the dialog.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
    if (open != 0) {
	winCode = GetOpenFileName(&ofn);
    } else {
	winCode = GetSaveFileName(&ofn);
    }
    Tcl_SetServiceMode(oldMode);
    EatSpuriousMessageBugFix();

................................................................................
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    ConvertExternalFilename(ofn.lpstrFile, &ds), -1));
	    gotFilename = (Tcl_DStringLength(&ds) > 0);
	    Tcl_DStringFree(&ds);
	}
	result = TCL_OK;
	if ((ofn.nFilterIndex > 0) && gotFilename && typeVariableObj
		&& filterObj) {
	    int listObjc, count;
	    Tcl_Obj **listObjv = NULL;
	    Tcl_Obj **typeInfo = NULL;

	    if (Tcl_ListObjGetElements(interp, filterObj,
		    &listObjc, &listObjv) != TCL_OK) {
		result = TCL_ERROR;
	    } else if (Tcl_ListObjGetElements(interp,
		    listObjv[ofn.nFilterIndex - 1], &count,
		    &typeInfo) != TCL_OK) {
		result = TCL_ERROR;
	    } else if (Tcl_ObjSetVar2(interp, typeVariableObj, NULL,
		    typeInfo[0], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
	}
    } else if (cdlgerr == FNERR_INVALIDFILENAME) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"invalid filename \"%s\"",
		ConvertExternalFilename(ofn.lpstrFile, &ds)));
................................................................................
	result = TCL_OK;
    }

    if (ofn.lpstrTitle != NULL) {
	Tcl_DStringFree(&titleString);
    }
    if (ofn.lpstrInitialDir != NULL) {


	Tcl_DStringFree(&dirString);
    }
    Tcl_DStringFree(&filterString);
    if (ofn.lpstrDefExt != NULL) {
	Tcl_DStringFree(&extString);
    }

  end:
    Tcl_DStringFree(&utfDirString);
    Tcl_DStringFree(&utfFilterString);
    if (ofnData.dynFileBuffer != NULL) {
	ckfree(ofnData.dynFileBuffer);
	ofnData.dynFileBuffer = NULL;
    }

    return result;
}











































 
/*
 *-------------------------------------------------------------------------
 *
 * OFNHookProc --
 *
 *	Dialog box hook function. This is used to sets the "tk_dialog"
................................................................................
	     */

	    ofnPtr = notifyPtr->lpOFN;
	    ofnData = (OFNData *) ofnPtr->lCustData;
	    buffer = ofnData->dynFileBuffer;
	    hdlg = GetParent(hdlg);

	    selsize = SendMessage(hdlg, CDM_GETSPEC, 0, 0);
	    dirsize = SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0);
	    buffersize = (selsize + dirsize + 1);

	    /*
	     * Just empty the buffer if dirsize indicates an error. [Bug
	     * 3071836]
	     */

................................................................................
    TkFreeFileFilters(&flist);
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *











































































































































 * Tk_ChooseDirectoryObjCmd --
 *
 *	This function implements the "tk_chooseDirectory" dialog box for the
 *	Windows platform. See the user documentation for details on what it
 *	does. Uses the newer SHBrowseForFolder explorer type interface.
 *
 * Results:
................................................................................
Tk_ChooseDirectoryObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    TCHAR path[MAX_PATH];
    int oldMode, result = TCL_ERROR, i;
    LPCITEMIDLIST pidl;		/* Returned by browser */
    BROWSEINFO bInfo;		/* Used by browser */
    ChooseDir cdCBData;	    /* Structure to pass back and forth */
    LPMALLOC pMalloc;		/* Used by shell */
    Tk_Window tkwin = clientData;
    HWND hWnd;
    const char *utfTitle = NULL;/* Title for window */
    TCHAR saveDir[MAX_PATH];
    Tcl_DString titleString;	/* Title */
    Tcl_DString initDirString;	/* Initial directory */
    Tcl_DString tempString;	/* temporary */
    Tcl_Obj *objPtr;

    static const char *const optionStrings[] = {


	"-initialdir", "-mustexist",  "-parent",  "-title", NULL
    };

    enum options {
	DIR_INITIAL,   DIR_EXIST,  DIR_PARENT, FILE_TITLE
    };

    /*



     * Initialize
     */





    path[0] = '\0';
    ZeroMemory(&cdCBData, sizeof(ChooseDir));
    cdCBData.interp = interp;


    /*
     * Process the command line options
     */

    for (i = 1; i < objc; i += 2) {
	int index;
	const char *string;

	const TCHAR *uniStr;
	Tcl_Obj *optionPtr, *valuePtr;

	optionPtr = objv[i];
	valuePtr = objv[i + 1];

	if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings,
		sizeof(char *), "option", 0, &index) != TCL_OK) {
	    goto cleanup;
	}
	if (i + 1 == objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "value for \"%s\" missing", Tcl_GetString(optionPtr)));
	    Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL);
	    goto cleanup;
	}

	string = Tcl_GetString(valuePtr);
	switch ((enum options) index) {
	case DIR_INITIAL:
	    if (Tcl_TranslateFileName(interp,string,&initDirString) == NULL) {
		goto cleanup;
	    }
	    Tcl_WinUtfToTChar(Tcl_DStringValue(&initDirString), -1,
		    &tempString);
	    uniStr = (TCHAR *) Tcl_DStringValue(&tempString);

	    /*
	     * Convert possible relative path to full path to keep dialog
	     * happy.
	     */

	    GetFullPathName(uniStr, MAX_PATH, saveDir, NULL);
	    _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH);
	    Tcl_DStringFree(&initDirString);
	    Tcl_DStringFree(&tempString);
	    break;
	case DIR_EXIST:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr,
		    &cdCBData.mustExist) != TCL_OK) {
		goto cleanup;
	    }
	    break;
	case DIR_PARENT:
	    tkwin = Tk_NameToWindow(interp, string, tkwin);
	    if (tkwin == NULL) {
		goto cleanup;
	    }
	    break;
	case FILE_TITLE:
	    utfTitle = string;
	    break;

	}
    }

    /*
     * Get ready to call the browser
     */

    Tk_MakeWindowExist(tkwin);
    hWnd = Tk_GetHWND(Tk_WindowId(tkwin));

    /*
     * Setup the parameters used by SHBrowseForFolder
     */

    bInfo.hwndOwner = hWnd;
    bInfo.pszDisplayName = path;
    bInfo.pidlRoot = NULL;
    if (_tcslen(cdCBData.initDir) == 0) {
	GetCurrentDirectory(MAX_PATH, cdCBData.initDir);
    }
    bInfo.lParam = (LPARAM) &cdCBData;

    if (utfTitle != NULL) {
	Tcl_WinUtfToTChar(utfTitle, -1, &titleString);
	bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString);
    } else {
	bInfo.lpszTitle = TEXT("Please choose a directory, then select OK.");
    }

    /*
     * Set flags to add edit box, status text line and use the new ui. Allow
................................................................................
     * user a chance to change their mind on an invalid folder if mustexist is
     * 0.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
    GetCurrentDirectory(MAX_PATH, saveDir);
    if (SHGetMalloc(&pMalloc) == NOERROR) {




	pidl = SHBrowseForFolder(&bInfo);

	/*
	 * This is a fix for Windows 2000, which seems to modify the folder
	 * name buffer even when the dialog is canceled (in this case the
	 * buffer contains garbage). See [Bug #3002230]
	 */
................................................................................
	Tcl_DString ds;

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		ConvertExternalFilename(path, &ds), -1));
	Tcl_DStringFree(&ds);
    }

    result = TCL_OK;

    if (utfTitle != NULL) {
	Tcl_DStringFree(&titleString);
    }

  cleanup:
    return result;
}
 
/*
 *----------------------------------------------------------------------
 *
 * ChooseDirectoryValidateProc --
 *







<
<
<




>
>


>
>



>








>







 







>
>
>
>







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>
>
>
>
>
>

|
|
>
>
>
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|





|

|


|


|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|




|
|

<
<
<
|
<
<
<
<
<
<
|
<
<
<


|
>







 







|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>








>
>
>
>
>
|
>
>
>
>
>
>




|





|
<
<
<


|


|

|
|
<


|
|
<

|
>
|



|
|
|
<


<
>


|
|
|


|
>
|
<



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|



|
|





|


|



|

|





|











|
>
>
>
|








|
|
|








|
|

|









|
|








|







 







|
|




|






|
|







 







>
>







|
<








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|




<

<


<


>
|
>
>
|
<
>
|
<
<

<
>
>
>
|
<
>
>
>
>




>

<
|
<
<
<
<
<
>

<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|

<
|
<
<

|
|
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
>
|
<
<




|
|













|
|







 







>
>
>
>







 







|
<
<
<
<
<
<
|







10
11
12
13
14
15
16



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041



1042






1043



1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
....
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127



1128
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

1151
1152

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
....
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
....
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
....
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
....
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
....
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364

2365

2366
2367

2368
2369
2370
2371
2372
2373
2374

2375
2376


2377

2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2389
2390
2391

2392





2393
2394

2395




















2396
2397
2398
2399

2400


2401
2402
2403







2404





2405




2406
2407


2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
....
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
....
2514
2515
2516
2517
2518
2519
2520
2521






2522
2523
2524
2525
2526
2527
2528
2529
 */

#include "tkWinInt.h"
#include "tkFileFilter.h"
#include "tkFont.h"

#include <commdlg.h>		/* includes common dialog functionality */



#include <dlgs.h>		/* includes common dialog template defines */
#include <cderr.h>		/* includes the common dialog error codes */

#include <shlobj.h>		/* includes SHBrowseForFolder */
#include <shobjidl.h>

#ifdef _MSC_VER
#   pragma comment (lib, "shell32.lib")
#   pragma comment (lib, "comdlg32.lib")
#   pragma comment (lib, "uuid.lib")
#endif

/* These needed for compilation with VC++ 5.2 */
/* XXX - remove these since need at least VC 6 */
#ifndef BIF_EDITBOX
#define BIF_EDITBOX 0x10
#endif

#ifndef BIF_VALIDATE
#define BIF_VALIDATE 0x0020
#endif

/* This "new" dialog style is now actually the "old" dialog style post-Vista */
#ifndef BIF_NEWDIALOGSTYLE
#define BIF_NEWDIALOGSTYLE 0x0040
#endif

#ifndef BFFM_VALIDATEFAILED
#ifdef UNICODE
#define BFFM_VALIDATEFAILED 4
................................................................................
    Tcl_Interp *debugInterp;	/* Interpreter to used for debugging. */
    UINT WM_LBSELCHANGED;	/* Holds a registered windows event used for
				 * communicating between the Directory Chooser
				 * dialog and its hook proc. */
    HHOOK hMsgBoxHook;		/* Hook proc for tk_messageBox and the */
    HICON hSmallIcon;		/* icons used by a parent to be used in */
    HICON hBigIcon;		/* the message box */
    int   newFileDialogsState;
#define FDLG_STATE_INIT 0       /* Uninitialized */
#define FDLG_STATE_USE_NEW 1    /* Use the new dialogs */
#define FDLG_STATE_USE_OLD 2    /* Use the old dialogs */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following structures are used by Tk_MessageBoxCmd() to parse arguments
 * and return results.
 */
................................................................................
				 * for setting the "tk_dialog" variable. */
    int dynFileBufferSize;	/* Dynamic filename buffer size, stored to
				 * avoid shrinking and expanding the buffer
				 * when selection changes */
    TCHAR *dynFileBuffer;	/* Dynamic filename buffer */
} OFNData;

/*
 * The following structure is used to gather options used by various
 * file dialogs
 */
typedef struct OFNOpts {
    Tk_Window tkwin;            /* Owner window for dialog */
    Tcl_Obj *extObj;            /* Default extension */
    Tcl_Obj *titleObj;          /* Title for dialog */
    Tcl_Obj *filterObj;         /* File type filter list */
    Tcl_Obj *typeVariableObj;   /* Variable in which to store type selected */
    Tcl_Obj *initialTypeObj;    /* Initial value of above, or NULL */
    Tcl_DString utfDirString;   /* Initial dir */
    int multi;                  /* Multiple selection enabled */
    int confirmOverwrite;       /* Confirm before overwriting */
    int mustExist;              /* Used only for  */
    int forceXPStyle;          /* XXX - Force XP style even on newer systems */
    TCHAR file[TK_MULTI_MAX_PATH]; /* File name
                                      XXX - fixed size because it was so
                                      historically. Why not malloc'ed ?
                                      XXX - also, TCHAR should really be WCHAR
                                      because TkWinGetUnicodeEncoding is always
                                      UCS2.
                                   */
} OFNOpts;

/* Define the operation for which option parsing is to be done. */
enum OFNOper {
    OFN_FILE_SAVE,              /* tk_getOpenFile */
    OFN_FILE_OPEN,              /* tk_getSaveFile */
    OFN_DIR_CHOOSE              /* tk_chooseDirectory */
};


/*
 * The following definitions are required when using older versions of
 * Visual C++ (like 6.0) and possibly MingW. Those headers do not contain
 * required definitions for interfaces new to Vista that we need for
 * the new file dialogs. Duplicating definitions is OK because they
 * should forever remain unchanged.
 *
 * XXX - is there a better/easier way to use new data definitions with
 * older compilers? Should we prefix definitions with Tcl_ instead
 * of using the same names as in the SDK?
 */
#ifndef __IShellItemArray_INTERFACE_DEFINED__
#define __IShellItemArray_INTERFACE_DEFINED__

typedef enum SIATTRIBFLAGS {
    SIATTRIBFLAGS_AND	= 0x1,
    SIATTRIBFLAGS_OR	= 0x2,
    SIATTRIBFLAGS_APPCOMPAT	= 0x3,
    SIATTRIBFLAGS_MASK	= 0x3,
    SIATTRIBFLAGS_ALLITEMS	= 0x4000
} SIATTRIBFLAGS;
#ifdef __MSVCRT__
typedef ULONG SFGAOF;

typedef struct IShellItem IShellItem;

typedef enum __MIDL_IShellItem_0001 {
    SIGDN_NORMALDISPLAY = 0,SIGDN_PARENTRELATIVEPARSING = 0x80018001,SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
    SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,SIGDN_PARENTRELATIVEEDITING = 0x80031001,SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
    SIGDN_FILESYSPATH = 0x80058000,SIGDN_URL = 0x80068000
} SIGDN;

typedef DWORD SICHINTF;

typedef struct IShellItemVtbl
{
    BEGIN_INTERFACE

    HRESULT (STDMETHODCALLTYPE *QueryInterface)(IShellItem *, REFIID, void **);
    ULONG (STDMETHODCALLTYPE *AddRef)(IShellItem *);
    ULONG (STDMETHODCALLTYPE *Release)(IShellItem *);
    HRESULT (STDMETHODCALLTYPE *BindToHandler)(IShellItem *, IBindCtx *, REFGUID, REFIID, void **);
    HRESULT (STDMETHODCALLTYPE *GetParent)(IShellItem *, IShellItem **);
    HRESULT (STDMETHODCALLTYPE *GetDisplayName)(IShellItem *, SIGDN, LPOLESTR *);
    HRESULT (STDMETHODCALLTYPE *GetAttributes)(IShellItem *, SFGAOF, SFGAOF *);
    HRESULT (STDMETHODCALLTYPE *Compare)(IShellItem *, IShellItem *, SICHINTF, int *);

    END_INTERFACE
} IShellItemVtbl;
struct IShellItem {
    CONST_VTBL struct IShellItemVtbl *lpVtbl;
};
#endif /* __MSVCRT__ */
typedef struct IShellItemArray IShellItemArray;
typedef struct IShellItemArrayVtbl
{
    BEGIN_INTERFACE

    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
        IShellItemArray *, REFIID riid,void **ppvObject);
    ULONG ( STDMETHODCALLTYPE *AddRef )(IShellItemArray *);
    ULONG ( STDMETHODCALLTYPE *Release )(IShellItemArray *);
    HRESULT ( STDMETHODCALLTYPE *BindToHandler )(IShellItemArray *,
        IBindCtx *, REFGUID, REFIID, void **);
    /* flags is actually is enum GETPROPERTYSTOREFLAGS */
    HRESULT ( STDMETHODCALLTYPE *GetPropertyStore )(
        IShellItemArray *, int,  REFIID, void **);
    /* keyType actually REFPROPERTYKEY */
    HRESULT ( STDMETHODCALLTYPE *GetPropertyDescriptionList )(
         IShellItemArray *, void *, REFIID, void **);
    HRESULT ( STDMETHODCALLTYPE *GetAttributes )(IShellItemArray *,
        SIATTRIBFLAGS, SFGAOF, SFGAOF *);
    HRESULT ( STDMETHODCALLTYPE *GetCount )(
        IShellItemArray *, DWORD *);
    HRESULT ( STDMETHODCALLTYPE *GetItemAt )(
        IShellItemArray *, DWORD, IShellItem **);
    /* ppenumShellItems actually (IEnumShellItems **) */
    HRESULT ( STDMETHODCALLTYPE *EnumItems )(
        IShellItemArray *, void **);

    END_INTERFACE
} IShellItemArrayVtbl;

struct IShellItemArray {
    CONST_VTBL struct IShellItemArrayVtbl *lpVtbl;
};

#endif /* __IShellItemArray_INTERFACE_DEFINED__ */

/*
 * Older compilers do not define these CLSIDs so we do so here under
 * a slightly different name so as to not clash with the definitions
 * in new compilers
 */
static const CLSID ClsidFileOpenDialog = {
    0xDC1C5A9C, 0xE88A, 0X4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}
};
static const CLSID ClsidFileSaveDialog = {
    0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}
};
static const IID IIDIFileOpenDialog = {
    0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60}
};
static const IID IIDIFileSaveDialog = {
    0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB}
};
static const IID IIDIShellItem = {
	0x43826D1E, 0xE718, 0x42EE, {0xBC, 0x55, 0xA1, 0xE2, 0x61, 0xC3, 0x7B, 0xFE}
};

#ifdef __IFileDialog_INTERFACE_DEFINED__
# define TCLCOMDLG_FILTERSPEC COMDLG_FILTERSPEC
#else

/* Forward declarations for structs that are referenced but not used */
typedef struct IPropertyStore IPropertyStore;
typedef struct IPropertyDescriptionList IPropertyDescriptionList;
typedef struct IFileOperationProgressSink IFileOperationProgressSink;
typedef enum FDAP {
    FDAP_BOTTOM	= 0,
    FDAP_TOP	= 1
} FDAP;

typedef struct {
    LPCWSTR pszName;
    LPCWSTR pszSpec;
} TCLCOMDLG_FILTERSPEC;

enum _FILEOPENDIALOGOPTIONS {
    FOS_OVERWRITEPROMPT	= 0x2,
    FOS_STRICTFILETYPES	= 0x4,
    FOS_NOCHANGEDIR	= 0x8,
    FOS_PICKFOLDERS	= 0x20,
    FOS_FORCEFILESYSTEM	= 0x40,
    FOS_ALLNONSTORAGEITEMS	= 0x80,
    FOS_NOVALIDATE	= 0x100,
    FOS_ALLOWMULTISELECT	= 0x200,
    FOS_PATHMUSTEXIST	= 0x800,
    FOS_FILEMUSTEXIST	= 0x1000,
    FOS_CREATEPROMPT	= 0x2000,
    FOS_SHAREAWARE	= 0x4000,
    FOS_NOREADONLYRETURN	= 0x8000,
    FOS_NOTESTFILECREATE	= 0x10000,
    FOS_HIDEMRUPLACES	= 0x20000,
    FOS_HIDEPINNEDPLACES	= 0x40000,
    FOS_NODEREFERENCELINKS	= 0x100000,
    FOS_DONTADDTORECENT	= 0x2000000,
    FOS_FORCESHOWHIDDEN	= 0x10000000,
    FOS_DEFAULTNOMINIMODE	= 0x20000000,
    FOS_FORCEPREVIEWPANEON	= 0x40000000
} ;
typedef DWORD FILEOPENDIALOGOPTIONS;

typedef struct IFileDialog IFileDialog;
typedef struct IFileDialogVtbl
{
    BEGIN_INTERFACE

    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
         IFileDialog *, REFIID, void **);
    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileDialog *);
    ULONG ( STDMETHODCALLTYPE *Release )( IFileDialog *);
    HRESULT ( STDMETHODCALLTYPE *Show )( IFileDialog *, HWND);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileDialog *,
        UINT, const TCLCOMDLG_FILTERSPEC *);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(IFileDialog *, UINT);
    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(IFileDialog *, UINT *);
    /* XXX - Actually pfde is IFileDialogEvents* but we do not use
       this call and do not want to define IFileDialogEvents as that
       pulls in a whole bunch of other stuff. */
    HRESULT ( STDMETHODCALLTYPE *Advise )(
        IFileDialog *, void *, DWORD *);
    HRESULT ( STDMETHODCALLTYPE *Unadvise )(IFileDialog *, DWORD);
    HRESULT ( STDMETHODCALLTYPE *SetOptions )(
        IFileDialog *, FILEOPENDIALOGOPTIONS);
    HRESULT ( STDMETHODCALLTYPE *GetOptions )(
        IFileDialog *, FILEOPENDIALOGOPTIONS *);
    HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )(
        IFileDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *SetFolder )(
        IFileDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *GetFolder )(
        IFileDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )(
        IFileDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *SetFileName )(
        IFileDialog *,  LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *GetFileName )(
        IFileDialog *,  LPWSTR *);
    HRESULT ( STDMETHODCALLTYPE *SetTitle )(
        IFileDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )(
        IFileDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )(
        IFileDialog *,  LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *GetResult )(
        IFileDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *AddPlace )(
        IFileDialog *, IShellItem *, FDAP);
    HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )(
         IFileDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *Close )( IFileDialog *, HRESULT);
    HRESULT ( STDMETHODCALLTYPE *SetClientGuid )(
        IFileDialog *, REFGUID);
    HRESULT ( STDMETHODCALLTYPE *ClearClientData )( IFileDialog *);
    /* pFilter actually IShellItemFilter. But deprecated in Win7 AND we do
       not use it anyways. So define as void* */
    HRESULT ( STDMETHODCALLTYPE *SetFilter )(
         IFileDialog *, void *);

    END_INTERFACE
} IFileDialogVtbl;

struct IFileDialog {
    CONST_VTBL struct IFileDialogVtbl *lpVtbl;
};


typedef struct IFileSaveDialog IFileSaveDialog;
typedef struct IFileSaveDialogVtbl {
    BEGIN_INTERFACE

    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
        IFileSaveDialog *, REFIID, void **);
    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileSaveDialog *);
    ULONG ( STDMETHODCALLTYPE *Release )( IFileSaveDialog *);
    HRESULT ( STDMETHODCALLTYPE *Show )(
        IFileSaveDialog *, HWND);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileSaveDialog * this,
        UINT, const TCLCOMDLG_FILTERSPEC *);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(
        IFileSaveDialog *, UINT);
    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(
         IFileSaveDialog *, UINT *);
    /* Actually pfde is IFileSaveDialogEvents* */
    HRESULT ( STDMETHODCALLTYPE *Advise )(
         IFileSaveDialog *, void *, DWORD *);
    HRESULT ( STDMETHODCALLTYPE *Unadvise )( IFileSaveDialog *, DWORD);
    HRESULT ( STDMETHODCALLTYPE *SetOptions )(
         IFileSaveDialog *, FILEOPENDIALOGOPTIONS);
    HRESULT ( STDMETHODCALLTYPE *GetOptions )(
         IFileSaveDialog *, FILEOPENDIALOGOPTIONS *);
    HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )(
         IFileSaveDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *SetFolder )(
        IFileSaveDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *GetFolder )(
         IFileSaveDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )(
         IFileSaveDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *SetFileName )(
         IFileSaveDialog *,  LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *GetFileName )(
         IFileSaveDialog *,  LPWSTR *);
    HRESULT ( STDMETHODCALLTYPE *SetTitle )(
         IFileSaveDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )(
         IFileSaveDialog *,  LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )(
         IFileSaveDialog *,  LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *GetResult )(
         IFileSaveDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *AddPlace )(
         IFileSaveDialog *, IShellItem *, FDAP);
    HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )(
         IFileSaveDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *Close )( IFileSaveDialog *, HRESULT);
    HRESULT ( STDMETHODCALLTYPE *SetClientGuid )(
        IFileSaveDialog *, REFGUID);
    HRESULT ( STDMETHODCALLTYPE *ClearClientData )( IFileSaveDialog *);
    /* pFilter Actually IShellItemFilter* */
    HRESULT ( STDMETHODCALLTYPE *SetFilter )(
        IFileSaveDialog *, void *);
    HRESULT ( STDMETHODCALLTYPE *SetSaveAsItem )(
        IFileSaveDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *SetProperties )(
        IFileSaveDialog *, IPropertyStore *);
    HRESULT ( STDMETHODCALLTYPE *SetCollectedProperties )(
        IFileSaveDialog *, IPropertyDescriptionList *, BOOL);
    HRESULT ( STDMETHODCALLTYPE *GetProperties )(
        IFileSaveDialog *, IPropertyStore **);
    HRESULT ( STDMETHODCALLTYPE *ApplyProperties )(
        IFileSaveDialog *, IShellItem *, IPropertyStore *,
        HWND, IFileOperationProgressSink *);

    END_INTERFACE

} IFileSaveDialogVtbl;

struct IFileSaveDialog {
    CONST_VTBL struct IFileSaveDialogVtbl *lpVtbl;
};

typedef struct IFileOpenDialog IFileOpenDialog;
typedef struct IFileOpenDialogVtbl {
    BEGIN_INTERFACE

    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
        IFileOpenDialog *, REFIID, void **);
    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileOpenDialog *);
    ULONG ( STDMETHODCALLTYPE *Release )( IFileOpenDialog *);
    HRESULT ( STDMETHODCALLTYPE *Show )( IFileOpenDialog *, HWND);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileOpenDialog *,
        UINT, const TCLCOMDLG_FILTERSPEC *);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(
        IFileOpenDialog *, UINT);
    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(
        IFileOpenDialog *, UINT *);
    /* Actually pfde is IFileDialogEvents* */
    HRESULT ( STDMETHODCALLTYPE *Advise )(
        IFileOpenDialog *, void *, DWORD *);
    HRESULT ( STDMETHODCALLTYPE *Unadvise )( IFileOpenDialog *, DWORD);
    HRESULT ( STDMETHODCALLTYPE *SetOptions )(
        IFileOpenDialog *, FILEOPENDIALOGOPTIONS);
    HRESULT ( STDMETHODCALLTYPE *GetOptions )(
        IFileOpenDialog *, FILEOPENDIALOGOPTIONS *);
    HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )(
        IFileOpenDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *SetFolder )(
        IFileOpenDialog *, IShellItem *);
    HRESULT ( STDMETHODCALLTYPE *GetFolder )(
        IFileOpenDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )(
        IFileOpenDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *SetFileName )(
        IFileOpenDialog *,  LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *GetFileName )(
        IFileOpenDialog *, LPWSTR *);
    HRESULT ( STDMETHODCALLTYPE *SetTitle )(
        IFileOpenDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )(
        IFileOpenDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )(
        IFileOpenDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *GetResult )(
        IFileOpenDialog *, IShellItem **);
    HRESULT ( STDMETHODCALLTYPE *AddPlace )(
        IFileOpenDialog *, IShellItem *, FDAP);
    HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )(
        IFileOpenDialog *, LPCWSTR);
    HRESULT ( STDMETHODCALLTYPE *Close )( IFileOpenDialog *, HRESULT);
    HRESULT ( STDMETHODCALLTYPE *SetClientGuid )(
        IFileOpenDialog *, REFGUID);
    HRESULT ( STDMETHODCALLTYPE *ClearClientData )(
        IFileOpenDialog *);
    HRESULT ( STDMETHODCALLTYPE *SetFilter )(
        IFileOpenDialog *,
        /* pFilter is actually IShellItemFilter */
        void *);
    HRESULT ( STDMETHODCALLTYPE *GetResults )(
        IFileOpenDialog *, IShellItemArray **);
    HRESULT ( STDMETHODCALLTYPE *GetSelectedItems )(
        IFileOpenDialog *, IShellItemArray **);

    END_INTERFACE
} IFileOpenDialogVtbl;

struct IFileOpenDialog
{
    CONST_VTBL struct IFileOpenDialogVtbl *lpVtbl;
};

#endif /* __IFileDialog_INTERFACE_DEFINED__ */

/*
 * Definitions of functions used only in this file.
 */

static UINT APIENTRY	ChooseDirectoryValidateProc(HWND hdlg, UINT uMsg,
			    LPARAM wParam, LPARAM lParam);
static UINT CALLBACK	ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam,
			    LPARAM lParam);
static void             CleanupOFNOptions(OFNOpts *optsPtr);
static int              ParseOFNOptions(ClientData clientData,
                            Tcl_Interp *interp, int objc,
                            Tcl_Obj *const objv[], enum OFNOper oper, OFNOpts *optsPtr);
static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr,
                         enum OFNOper oper);
static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr,
                            enum OFNOper oper);
static int 		GetFileName(ClientData clientData,
                                    Tcl_Interp *interp, int objc,
                                    Tcl_Obj *const objv[], enum OFNOper oper);
static int MakeFilterVista(Tcl_Interp *interp, OFNOpts *optsPtr,
               DWORD *countPtr, TCLCOMDLG_FILTERSPEC **dlgFilterPtrPtr,
               DWORD *defaultFilterIndexPtr);
static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr);
static int 		MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr,
			    Tcl_DString *dsPtr, Tcl_Obj *initialPtr,
			    int *indexPtr);
static UINT APIENTRY	OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam,
			    LPARAM lParam);
static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam);
static void		SetTkDialog(ClientData clientData);
static const char *ConvertExternalFilename(TCHAR *filename,
			    Tcl_DString *dsPtr);
static void             LoadShellProcs(void);


/* Definitions of dynamically loaded Win32 calls */
typedef HRESULT (STDAPICALLTYPE SHCreateItemFromParsingNameProc)(
    PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
struct ShellProcPointers {
    SHCreateItemFromParsingNameProc *SHCreateItemFromParsingName;
} ShellProcs;

 
/*
 *-------------------------------------------------------------------------
 *
 * LoadShellProcs --
 *
 *     Some shell functions are not available on older versions of
 *     Windows. This function dynamically loads them and stores pointers
 *     to them in ShellProcs. Any function that is not available has
 *     the corresponding pointer set to NULL.
 *
 *     Note this call never fails. Unavailability of a function is not
 *     a reason for failure. Caller should check whether a particular
 *     function pointer is NULL or not. Once loaded a function stays
 *     forever loaded.
 *
 *     XXX - we load the function pointers into global memory. This implies
 *     there is a potential (however small) for race conditions between
 *     threads. However, Tk is in any case meant to be loaded in exactly
 *     one thread so this should not be an issue and saves us from
 *     unnecessary bookkeeping.
 *
 * Return value:
 *     None.
 *
 * Side effects:
 *     ShellProcs is populated.
 *-------------------------------------------------------------------------
 */
static void LoadShellProcs()
{
    static HMODULE shell32_handle = NULL;

    if (shell32_handle != NULL)
        return; /* We have already been through here. */

    /*
     * XXX - Note we never call FreeLibrary. There is no point because
     * shell32.dll is loaded at startup anyways and stays for the duration
     * of the process so why bother with keeping track of when to unload
     */
    shell32_handle = LoadLibrary(TEXT("shell32.dll"));
    if (shell32_handle == NULL) /* Should never happen but check anyways. */
        return;

    ShellProcs.SHCreateItemFromParsingName =
        (SHCreateItemFromParsingNameProc*) GetProcAddress(shell32_handle,
                                                         "SHCreateItemFromParsingName");
}

 
/*
 *-------------------------------------------------------------------------
 *
 * EatSpuriousMessageBugFix --
 *
 *	In the file open/save dialog, double clicking on a list item causes
................................................................................
int
Tk_GetOpenFileObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return GetFileName(clientData, interp, objc, objv, OFN_FILE_OPEN);
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tk_GetSaveFileCmd --
 *
................................................................................
int
Tk_GetSaveFileObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return GetFileName(clientData, interp, objc, objv, OFN_FILE_SAVE);
}
 
/*
 *----------------------------------------------------------------------
 *
 * CleanupOFNOptions --
 *
 *	Cleans up any storage allocated by ParseOFNOptions
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Releases resources held by *optsPtr
 *----------------------------------------------------------------------
 */
static void CleanupOFNOptions(OFNOpts *optsPtr)
{
    Tcl_DStringFree(&optsPtr->utfDirString);
}


 
/*
 *----------------------------------------------------------------------
 *
 * ParseOFNOptions --
 *
 *	Option parsing for tk_get{Open,Save}File
 *
 * Results:
 *	TCL_OK on success, TCL_ERROR otherwise
 *
 * Side effects:
 *	Returns option values in *optsPtr. Note these may include string
 *      pointers into objv[]
 *----------------------------------------------------------------------
 */

static int
ParseOFNOptions(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    enum OFNOper oper,			/* 1 for Open, 0 for Save */
    OFNOpts *optsPtr)           /* Output, uninitialized on entry */
{



    int i;






    Tcl_DString ds;



    enum options {
	FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, FILE_PARENT,
	FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW,
        FILE_MUSTEXIST,
    };
    struct Options {
	const char *name;
	enum options value;
    };
    static const struct Options saveOptions[] = {
	{"-confirmoverwrite",	FILE_CONFIRMOW},
................................................................................
	{"-initialfile",	FILE_INITFILE},
	{"-multiple",		FILE_MULTIPLE},
	{"-parent",		FILE_PARENT},
	{"-title",		FILE_TITLE},
	{"-typevariable",	FILE_TYPEVARIABLE},
	{NULL,			FILE_DEFAULT/*ignored*/ }
    };
    static const struct Options dirOptions[] = {
	{"-initialdir", FILE_INITDIR},
        {"-mustexist",  FILE_MUSTEXIST},
	{"-parent",	FILE_PARENT},
	{"-title",	FILE_TITLE},
	{NULL,		FILE_DEFAULT/*ignored*/ }
    };

    const struct Options *options = NULL;

    switch (oper) {
    case OFN_FILE_SAVE: options = saveOptions; break;
    case OFN_DIR_CHOOSE: options = dirOptions; break;
    case OFN_FILE_OPEN: options = openOptions; break;
    }

    ZeroMemory(optsPtr, sizeof(*optsPtr));
    // optsPtr->forceXPStyle = 1;
    optsPtr->tkwin = clientData;
    optsPtr->confirmOverwrite = 1; /* By default we ask for confirmation */
    Tcl_DStringInit(&optsPtr->utfDirString);
    optsPtr->file[0] = 0;

    for (i = 1; i < objc; i += 2) {
	int index;
	const char *string;
	Tcl_Obj *valuePtr = objv[i + 1];

	if (Tcl_GetIndexFromObjStruct(interp, objv[i], options,
		sizeof(struct Options), "option", 0, &index) != TCL_OK) {
            /*
             * XXX -xpstyle is explicitly checked for as it is undocumented
             * and we do not want it to show in option error messages.
             */
            if (strcmp(Tcl_GetString(objv[i]), "-xpstyle"))
                goto error_return;
	    if (Tcl_GetBooleanFromObj(interp, valuePtr,
                                      &optsPtr->forceXPStyle) != TCL_OK)
                goto error_return;

            continue;

	} else if (i + 1 == objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "value for \"%s\" missing", options[index].name));
	    Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
	    goto error_return;
	}

	string = Tcl_GetString(valuePtr);
	switch (options[index].value) {
	case FILE_DEFAULT:
	    optsPtr->extObj = valuePtr;



	    break;
	case FILE_TYPES:
	    optsPtr->filterObj = valuePtr;
	    break;
	case FILE_INITDIR:
	    Tcl_DStringFree(&optsPtr->utfDirString);
	    if (Tcl_TranslateFileName(interp, string,
                                      &optsPtr->utfDirString) == NULL)
		goto error_return;

	    break;
	case FILE_INITFILE:
	    if (Tcl_TranslateFileName(interp, string, &ds) == NULL)
		goto error_return;

	    Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(),
                              Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL,
                              (char *) &optsPtr->file[0], sizeof(optsPtr->file),
                              NULL, NULL, NULL);
	    Tcl_DStringFree(&ds);
	    break;
	case FILE_PARENT:
	    optsPtr->tkwin = Tk_NameToWindow(interp, string, clientData);
	    if (optsPtr->tkwin == NULL)
		goto error_return;

	    break;
	case FILE_TITLE:

	    optsPtr->titleObj = valuePtr;
	    break;
	case FILE_TYPEVARIABLE:
	    optsPtr->typeVariableObj = valuePtr;
	    optsPtr->initialTypeObj = Tcl_ObjGetVar2(interp, valuePtr,
                                                     NULL, TCL_GLOBAL_ONLY);
	    break;
	case FILE_MULTIPLE:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr,
                                      &optsPtr->multi) != TCL_OK)
                goto error_return;

	    break;
	case FILE_CONFIRMOW:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr,
                                      &optsPtr->confirmOverwrite) != TCL_OK)
                goto error_return;
	    break;
        case FILE_MUSTEXIST:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr,
                                      &optsPtr->mustExist) != TCL_OK)
                goto error_return;
            break;
	}
    }

    return TCL_OK;

error_return:                   /* interp should already hold error */
    /* On error, we need to clean up anything we might have allocated */
    CleanupOFNOptions(optsPtr);
    return TCL_ERROR;
}

 
/*
 *----------------------------------------------------------------------
 * VistaFileDialogsAvailable
 *
 *      Checks whether the new (Vista) file dialogs can be used on
 *      the system.
 *
 * Returns:
 *      1 if new dialogs are available, 0 otherwise
 *
 * Side effects:
 *      Loads required procedures dynamically if available.
 *      If new dialogs are available, COM is also initialized.
 *----------------------------------------------------------------------
 */
static int VistaFileDialogsAvailable()
{
    HRESULT hr;
    IFileDialog *fdlgPtr = NULL;
    ThreadSpecificData *tsdPtr =
        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->newFileDialogsState == FDLG_STATE_INIT) {
        tsdPtr->newFileDialogsState = FDLG_STATE_USE_OLD;
        LoadShellProcs();
        if (ShellProcs.SHCreateItemFromParsingName != NULL) {
            hr = CoInitialize(0);
            /* XXX - need we schedule CoUninitialize at thread shutdown ? */

            /* Ensure all COM interfaces we use are available */
            if (SUCCEEDED(hr)) {
                hr = CoCreateInstance(&ClsidFileOpenDialog, NULL,
                                      CLSCTX_INPROC_SERVER, &IIDIFileOpenDialog, (void **) &fdlgPtr);
                if (SUCCEEDED(hr)) {
                    fdlgPtr->lpVtbl->Release(fdlgPtr);
                    hr = CoCreateInstance(&ClsidFileSaveDialog, NULL,
                             CLSCTX_INPROC_SERVER, &IIDIFileSaveDialog,
                                          (void **) &fdlgPtr);
                    if (SUCCEEDED(hr)) {
                        fdlgPtr->lpVtbl->Release(fdlgPtr);

                        /* Looks like we have all we need */
                        tsdPtr->newFileDialogsState = FDLG_STATE_USE_NEW;
                    }
                }
            }
        }
    }

    return (tsdPtr->newFileDialogsState == FDLG_STATE_USE_NEW);
}
 
/*
 *----------------------------------------------------------------------
 *
 * GetFileNameVista --
 *
 *	Displays the new file dialogs on Vista and later.
 *      This function must generally not be called unless the
 *      tsdPtr->newFileDialogsState is FDLG_STATE_USE_NEW but if
 *      it is, it will just pass the call to the older GetFileNameXP
 *
 * Results:
 *	TCL_OK - dialog was successfully displayed, results returned in interp
 *      TCL_ERROR - error return
 *
 * Side effects:
 *      Dialogs is displayed
 *----------------------------------------------------------------------
 */
static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr,
                            enum OFNOper oper)
{
    HRESULT hr;
    HWND hWnd;
    DWORD flags, nfilters, defaultFilterIndex;
    TCLCOMDLG_FILTERSPEC *filterPtr = NULL;
    IFileDialog *fdlgIf = NULL;
    IShellItem *dirIf = NULL;
    LPWSTR wstr;
    Tcl_Obj *resultObj = NULL;
    ThreadSpecificData *tsdPtr =
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    int oldMode;

    if (tsdPtr->newFileDialogsState != FDLG_STATE_USE_NEW) {
        /* XXX - should be an assert but Tcl does not seem to have one? */
        Tcl_SetResult(interp, "Internal error: GetFileNameVista: IFileDialog API not available", TCL_STATIC);
        return TCL_ERROR;
    }

    /*
     * At this point new interfaces are supposed to be available.
     * fdlgIf is actually a IFileOpenDialog or IFileSaveDialog
     * both of which inherit from IFileDialog. We use the common
     * IFileDialog interface for the most part, casting only for
     * type-specific calls.
     */
    Tk_MakeWindowExist(optsPtr->tkwin);
    hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin));

    /*
     * The only validation we need to do w.r.t caller supplied data
     * is the filter specification so do that before creating
     */
    if (MakeFilterVista(interp, optsPtr, &nfilters, &filterPtr,
                        &defaultFilterIndex) != TCL_OK)
        return TCL_ERROR;

    /*
     * Beyond this point, do not just return on error as there will be
     * resources that need to be released/freed.
     */

    if (oper == OFN_FILE_OPEN || oper == OFN_DIR_CHOOSE)
        hr = CoCreateInstance(&ClsidFileOpenDialog, NULL,
                              CLSCTX_INPROC_SERVER, &IIDIFileOpenDialog, (void **) &fdlgIf);
    else
        hr = CoCreateInstance(&ClsidFileSaveDialog, NULL,
                              CLSCTX_INPROC_SERVER, &IIDIFileSaveDialog, (void **) &fdlgIf);

    if (FAILED(hr))
        goto vamoose;

    /*
     * Get current settings first because we want to preserve existing
     * settings like whether to show hidden files etc. based on the
     * user's existing preference
     */
    hr = fdlgIf->lpVtbl->GetOptions(fdlgIf, &flags);
    if (FAILED(hr))
        goto vamoose;

    if (filterPtr) {
        flags |= FOS_STRICTFILETYPES;
        hr = fdlgIf->lpVtbl->SetFileTypes(fdlgIf, nfilters, filterPtr);
        if (FAILED(hr))
            goto vamoose;
        hr = fdlgIf->lpVtbl->SetFileTypeIndex(fdlgIf, defaultFilterIndex);
        if (FAILED(hr))
            goto vamoose;
    }

    /* Flags are equivalent to those we used in the older API */

    /*
     * Following flags must be set irrespective of original setting
     * XXX - should FOS_NOVALIDATE be there ? Note FOS_NOVALIDATE has different
     * semantics than OFN_NOVALIDATE in the old API.
     */
    flags |=
        FOS_FORCEFILESYSTEM | /* Only want files, not other shell items */
        FOS_NOVALIDATE |           /* Don't check for access denied etc. */
        FOS_PATHMUSTEXIST;           /* The *directory* path must exist */


    if (oper == OFN_DIR_CHOOSE) {
        flags |= FOS_PICKFOLDERS;
        if (optsPtr->mustExist)
            flags |= FOS_FILEMUSTEXIST; /* XXX - check working */
    } else
        flags &= ~ FOS_PICKFOLDERS;

    if (optsPtr->multi)
        flags |= FOS_ALLOWMULTISELECT;
    else
        flags &= ~FOS_ALLOWMULTISELECT;

    if (optsPtr->confirmOverwrite)
        flags |= FOS_OVERWRITEPROMPT;
    else
        flags &= ~FOS_OVERWRITEPROMPT;

    hr = fdlgIf->lpVtbl->SetOptions(fdlgIf, flags);
    if (FAILED(hr))
        goto vamoose;

    if (optsPtr->extObj != NULL) {
        wstr = Tcl_GetUnicode(optsPtr->extObj);
        if (wstr[0] == L'.')
            ++wstr;
        hr = fdlgIf->lpVtbl->SetDefaultExtension(fdlgIf, wstr);
        if (FAILED(hr))
            goto vamoose;
    }

    if (optsPtr->titleObj != NULL) {
        hr = fdlgIf->lpVtbl->SetTitle(fdlgIf,
                                       Tcl_GetUnicode(optsPtr->titleObj));
        if (FAILED(hr))
            goto vamoose;
    }

    if (optsPtr->file[0]) {
        hr = fdlgIf->lpVtbl->SetFileName(fdlgIf, optsPtr->file);
        if (FAILED(hr))
            goto vamoose;
    }

    if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') {
        Tcl_DString dirString;
	Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString),
               Tcl_DStringLength(&optsPtr->utfDirString), &dirString);
        hr = ShellProcs.SHCreateItemFromParsingName(
            (TCHAR *) Tcl_DStringValue(&dirString), NULL,
            &IIDIShellItem, (void **) &dirIf);
        /* XXX - Note on failure we do not raise error, simply ignore ini dir */
        if (SUCCEEDED(hr)) {
            /* Note we use SetFolder, not SetDefaultFolder - see MSDN docs */
            fdlgIf->lpVtbl->SetFolder(fdlgIf, dirIf); /* Ignore errors */
        }
        Tcl_DStringFree(&dirString);
    }

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
    hr = fdlgIf->lpVtbl->Show(fdlgIf, hWnd);
    Tcl_SetServiceMode(oldMode);

    if (SUCCEEDED(hr)) {
        if ((oper == OFN_FILE_OPEN) && optsPtr->multi) {
            IShellItemArray *multiIf;
            DWORD dw, count;
            IFileOpenDialog *fodIf = (IFileOpenDialog *) fdlgIf;
            hr = fodIf->lpVtbl->GetResults(fodIf, &multiIf);
            if (SUCCEEDED(hr)) {
                Tcl_Obj *multiObj;
                hr = multiIf->lpVtbl->GetCount(multiIf, &count);
                multiObj = Tcl_NewListObj(count, NULL);
                if (SUCCEEDED(hr)) {
                    IShellItem *itemIf;
                    for (dw = 0; dw < count; ++dw) {
                        hr = multiIf->lpVtbl->GetItemAt(multiIf, dw, &itemIf);
                        if (FAILED(hr))
                            break;
                        hr = itemIf->lpVtbl->GetDisplayName(itemIf,
                                        SIGDN_FILESYSPATH, &wstr);
                        if (SUCCEEDED(hr)) {
                            Tcl_DString fnds;
                            ConvertExternalFilename(wstr, &fnds);
                            CoTaskMemFree(wstr);
                            Tcl_ListObjAppendElement(
                                interp, multiObj,
                                Tcl_NewStringObj(Tcl_DStringValue(&fnds),
                                                 Tcl_DStringLength(&fnds)));
                        }
                        itemIf->lpVtbl->Release(itemIf);
                        if (FAILED(hr))
                            break;
                    }
                }
                multiIf->lpVtbl->Release(multiIf);
                if (SUCCEEDED(hr))
                    resultObj = multiObj;
                else
                    Tcl_DecrRefCount(multiObj);
            }
        } else {
            IShellItem *resultIf;
            hr = fdlgIf->lpVtbl->GetResult(fdlgIf, &resultIf);
            if (SUCCEEDED(hr)) {
                hr = resultIf->lpVtbl->GetDisplayName(resultIf, SIGDN_FILESYSPATH,
                                                      &wstr);
                if (SUCCEEDED(hr)) {
                    Tcl_DString fnds;
                    ConvertExternalFilename(wstr, &fnds);
                    resultObj = Tcl_NewStringObj(Tcl_DStringValue(&fnds),
                                                 Tcl_DStringLength(&fnds));
                    CoTaskMemFree(wstr);
                }
                resultIf->lpVtbl->Release(resultIf);
            }
        }
        if (SUCCEEDED(hr)) {
            if (filterPtr && optsPtr->typeVariableObj) {
                UINT ftix;
                hr = fdlgIf->lpVtbl->GetFileTypeIndex(fdlgIf, &ftix);
                if (SUCCEEDED(hr)) {
                    /* Note ftix is a 1-based index */
                    if (ftix > 0 && ftix <= nfilters) {
                        Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,
                               Tcl_NewUnicodeObj(filterPtr[ftix-1].pszName, -1),
                               TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
                    }
                }
            }
        }
    } else {
        if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
            hr = 0;             /* User cancelled, return empty string */
    }

vamoose: /* (hr != 0) => error */
    if (dirIf)
        dirIf->lpVtbl->Release(dirIf);
    if (fdlgIf)
        fdlgIf->lpVtbl->Release(fdlgIf);

    if (filterPtr)
        FreeFilterVista(nfilters, filterPtr);

    if (hr == 0) {
        if (resultObj)          /* May be NULL if user cancelled */
            Tcl_SetObjResult(interp, resultObj);
        return TCL_OK;
    } else {
        if (resultObj)
            Tcl_DecrRefCount(resultObj);
        Tcl_SetObjResult(interp, TkWin32ErrorObj(hr));
        return TCL_ERROR;
    }
}

 
/*
 *----------------------------------------------------------------------
 *
 * GetFileNameXP --
 *
 *	Displays the old pre-Vista file dialogs.
 *
 * Results:
 *	TCL_OK - if dialog was successfully displayed
 *      TCL_ERROR - error return
 *
 * Side effects:
 *      See user documentation.
 *----------------------------------------------------------------------
 */
static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr, enum OFNOper oper)
{
    OPENFILENAME ofn;
    OFNData ofnData;
    int cdlgerr;
    int filterIndex = 0, result = TCL_ERROR, winCode, oldMode;
    HWND hWnd;
    Tcl_DString utfFilterString, ds;
    Tcl_DString extString, filterString, dirString, titleString;
    const char *str;
    ThreadSpecificData *tsdPtr =
        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    ZeroMemory(&ofnData, sizeof(OFNData));
    Tcl_DStringInit(&utfFilterString);
    Tcl_DStringInit(&dirString); /* XXX - original code was missing this
                                    leaving dirString uninitialized for
                                    the unlikely code path where cwd failed */

    if (MakeFilter(interp, optsPtr->filterObj, &utfFilterString,
                   optsPtr->initialTypeObj, &filterIndex) != TCL_OK) {
	goto end;
    }

    Tk_MakeWindowExist(optsPtr->tkwin);
    hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin));

    ZeroMemory(&ofn, sizeof(OPENFILENAME));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hWnd;
    ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
    ofn.lpstrFile = optsPtr->file;
    ofn.nMaxFile = TK_MULTI_MAX_PATH;
    ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR
	    | OFN_EXPLORER| OFN_ENABLEHOOK| OFN_ENABLESIZING;
    ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
    ofn.lCustData = (LPARAM) &ofnData;

    if (oper != OFN_FILE_SAVE) {
	ofn.Flags |= OFN_FILEMUSTEXIST;
    } else if (optsPtr->confirmOverwrite) {
	ofn.Flags |= OFN_OVERWRITEPROMPT;
    }
    if (tsdPtr->debugFlag != 0) {
	ofnData.interp = interp;
    }
    if (optsPtr->multi != 0) {
	ofn.Flags |= OFN_ALLOWMULTISELECT;

	/*
	 * Starting buffer size. The buffer will be expanded by the OFN dialog
	 * procedure when necessary
	 */

	ofnData.dynFileBufferSize = 512;
	ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR));
    }

    if (optsPtr->extObj != NULL) {
        str = Tcl_GetString(optsPtr->extObj);
        if (str[0] == '.')
            ++str;
	Tcl_WinUtfToTChar(str, -1, &extString);
	ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString);
    }

    Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString),
	    Tcl_DStringLength(&utfFilterString), &filterString);
    ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString);
    ofn.nFilterIndex = filterIndex;

    if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') {
	Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString),
		Tcl_DStringLength(&optsPtr->utfDirString), &dirString);
    } else {
	/*
	 * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure
	 * that we set the [pwd] if the user didn't specify anything else.
	 */

	Tcl_DString cwd;

	Tcl_DStringFree(&optsPtr->utfDirString);
	if ((Tcl_GetCwd(interp, &optsPtr->utfDirString) == NULL) ||
		(Tcl_TranslateFileName(interp,
                     Tcl_DStringValue(&optsPtr->utfDirString), &cwd) == NULL)) {
	    Tcl_ResetResult(interp);
	} else {
	    Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd),
		    Tcl_DStringLength(&cwd), &dirString);
	}
	Tcl_DStringFree(&cwd);
    }
    ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString);

    if (optsPtr->titleObj != NULL) {
	Tcl_WinUtfToTChar(Tcl_GetString(optsPtr->titleObj), -1, &titleString);
	ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString);
    }

    /*
     * Popup the dialog.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
    if (oper != OFN_FILE_SAVE) {
	winCode = GetOpenFileName(&ofn);
    } else {
	winCode = GetSaveFileName(&ofn);
    }
    Tcl_SetServiceMode(oldMode);
    EatSpuriousMessageBugFix();

................................................................................
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    ConvertExternalFilename(ofn.lpstrFile, &ds), -1));
	    gotFilename = (Tcl_DStringLength(&ds) > 0);
	    Tcl_DStringFree(&ds);
	}
	result = TCL_OK;
	if ((ofn.nFilterIndex > 0) && gotFilename && optsPtr->typeVariableObj
		&& optsPtr->filterObj) {
	    int listObjc, count;
	    Tcl_Obj **listObjv = NULL;
	    Tcl_Obj **typeInfo = NULL;

	    if (Tcl_ListObjGetElements(interp, optsPtr->filterObj,
		    &listObjc, &listObjv) != TCL_OK) {
		result = TCL_ERROR;
	    } else if (Tcl_ListObjGetElements(interp,
		    listObjv[ofn.nFilterIndex - 1], &count,
		    &typeInfo) != TCL_OK) {
		result = TCL_ERROR;
	    } else if (Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,
                   typeInfo[0], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
	}
    } else if (cdlgerr == FNERR_INVALIDFILENAME) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"invalid filename \"%s\"",
		ConvertExternalFilename(ofn.lpstrFile, &ds)));
................................................................................
	result = TCL_OK;
    }

    if (ofn.lpstrTitle != NULL) {
	Tcl_DStringFree(&titleString);
    }
    if (ofn.lpstrInitialDir != NULL) {
        /* XXX - huh? lpstrInitialDir is set from Tcl_DStringValue which
           can never return NULL */
	Tcl_DStringFree(&dirString);
    }
    Tcl_DStringFree(&filterString);
    if (ofn.lpstrDefExt != NULL) {
	Tcl_DStringFree(&extString);
    }

end:

    Tcl_DStringFree(&utfFilterString);
    if (ofnData.dynFileBuffer != NULL) {
	ckfree(ofnData.dynFileBuffer);
	ofnData.dynFileBuffer = NULL;
    }

    return result;
}

 
/*
 *----------------------------------------------------------------------
 *
 * GetFileName --
 *
 *	Calls GetOpenFileName() or GetSaveFileName().
 *
 * Results:
 *	See user documentation.
 *
 * Side effects:
 *	See user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
GetFileName(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    enum OFNOper oper)  	/* 1 to call GetOpenFileName(), 0 to call
				 * GetSaveFileName(). */
{
    OFNOpts ofnOpts;
    int result;

    result = ParseOFNOptions(clientData, interp, objc, objv, oper, &ofnOpts);
    if (result != TCL_OK)
        return result;

    if (VistaFileDialogsAvailable() && ! ofnOpts.forceXPStyle)
        result = GetFileNameVista(interp, &ofnOpts, oper);
    else
        result = GetFileNameXP(interp, &ofnOpts, oper);

    CleanupOFNOptions(&ofnOpts);
    return result;
}

 
/*
 *-------------------------------------------------------------------------
 *
 * OFNHookProc --
 *
 *	Dialog box hook function. This is used to sets the "tk_dialog"
................................................................................
	     */

	    ofnPtr = notifyPtr->lpOFN;
	    ofnData = (OFNData *) ofnPtr->lCustData;
	    buffer = ofnData->dynFileBuffer;
	    hdlg = GetParent(hdlg);

	    selsize = (int) SendMessage(hdlg, CDM_GETSPEC, 0, 0);
	    dirsize = (int) SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0);
	    buffersize = (selsize + dirsize + 1);

	    /*
	     * Just empty the buffer if dirsize indicates an error. [Bug
	     * 3071836]
	     */

................................................................................
    TkFreeFileFilters(&flist);
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * FreeFilterVista
 *
 *      Frees storage previously allocated by MakeFilterVista.
 *      count is the number of elements in dlgFilterPtr[]
 */
static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr)
{
    if (dlgFilterPtr != NULL) {
        DWORD dw;
        for (dw = 0; dw < count; ++dw) {
            if (dlgFilterPtr[dw].pszName != NULL)
                ckfree(dlgFilterPtr[dw].pszName);
            if (dlgFilterPtr[dw].pszSpec != NULL)
                ckfree(dlgFilterPtr[dw].pszSpec);
        }
        ckfree(dlgFilterPtr);
    }
}
 
/*
 *----------------------------------------------------------------------
 *
 * MakeFilterVista --
 *
 *	Returns file type filters in a format required
 *	by the Vista file dialogs.
 *
 * Results:
 *	A standard TCL return value.
 *
 * Side effects:
 *      Various values are returned through the parameters as
 *      described in the comments below.
 *----------------------------------------------------------------------
 */
static int MakeFilterVista(
    Tcl_Interp *interp,		/* Current interpreter. */
    OFNOpts *optsPtr,           /* Caller specified options */
    DWORD *countPtr,            /* Will hold number of filters */
    TCLCOMDLG_FILTERSPEC **dlgFilterPtrPtr, /* Will hold pointer to filter array.
                                         Set to NULL if no filters specified.
                                         Must be freed by calling
                                         FreeFilterVista */
    DWORD *initialIndexPtr)     /* Will hold index of default type */
{
    TCLCOMDLG_FILTERSPEC *dlgFilterPtr;
    const char *initial = NULL;
    FileFilterList flist;
    FileFilter *filterPtr;
    DWORD initialIndex = 0;
    Tcl_DString ds, patterns;
    int       i;

    if (optsPtr->filterObj == NULL) {
        *dlgFilterPtrPtr = NULL;
        *countPtr = 0;
        return TCL_OK;
    }

    if (optsPtr->initialTypeObj)
	initial = Tcl_GetString(optsPtr->initialTypeObj);

    TkInitFileFilters(&flist);
    if (TkGetFileFilters(interp, &flist, optsPtr->filterObj, 1) != TCL_OK)
	return TCL_ERROR;

    if (flist.filters == NULL) {
        *dlgFilterPtrPtr = NULL;
        *countPtr = 0;
        return TCL_OK;
    }

    Tcl_DStringInit(&ds);
    Tcl_DStringInit(&patterns);
    dlgFilterPtr = ckalloc(flist.numFilters * sizeof(*dlgFilterPtr));

    for (i = 0, filterPtr = flist.filters;
         filterPtr;
         filterPtr = filterPtr->next, ++i) {
        const char *sep;
        FileFilterClause *clausePtr;
        int nbytes;

        /* Check if this entry should be shown as the default */
        if (initial && strcmp(initial, filterPtr->name) == 0)
            initialIndex = i+1; /* Windows filter indices are 1-based */

        /* First stash away the text description of the pattern */
	Tcl_WinUtfToTChar(filterPtr->name, -1, &ds);
        nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
        nbytes += sizeof(WCHAR);         /* Terminating \0 */
        dlgFilterPtr[i].pszName = ckalloc(nbytes);
        memmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes);
        Tcl_DStringFree(&ds);

        /*
         * Loop through and join patterns with a ";" Each "clause"
         * corresponds to a single textual description (called typename)
         * in the tk_getOpenFile docs. Each such typename may occur
         * multiple times and all these form a single filter entry
         * with one clause per occurence. Further each clause may specify
         * multiple patterns. Hence the nested loop here.
         */
        sep = "";
        for (clausePtr=filterPtr->clauses ; clausePtr;
             clausePtr=clausePtr->next) {
            GlobPattern *globPtr;
            for (globPtr = clausePtr->patterns; globPtr;
                 globPtr = globPtr->next) {
                Tcl_DStringAppend(&patterns, sep, -1);
                Tcl_DStringAppend(&patterns, globPtr->pattern, -1);
                sep = ";";
            }
        }

        /* Again we need a Unicode form of the string */
	Tcl_WinUtfToTChar(Tcl_DStringValue(&patterns), -1, &ds);
        nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
        nbytes += sizeof(WCHAR);         /* Terminating \0 */
        dlgFilterPtr[i].pszSpec = ckalloc(nbytes);
        memmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes);
        Tcl_DStringFree(&ds);
        Tcl_DStringFree(&patterns);
    }

    if (initialIndex == 0)
        initialIndex = 1;       /* If no default, show first entry */
    *initialIndexPtr = initialIndex;
    *dlgFilterPtrPtr = dlgFilterPtr;
    *countPtr = flist.numFilters;

    TkFreeFileFilters(&flist);
    return TCL_OK;
}

 
/*
 *----------------------------------------------------------------------
 *
 * Tk_ChooseDirectoryObjCmd --
 *
 *	This function implements the "tk_chooseDirectory" dialog box for the
 *	Windows platform. See the user documentation for details on what it
 *	does. Uses the newer SHBrowseForFolder explorer type interface.
 *
 * Results:
................................................................................
Tk_ChooseDirectoryObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    TCHAR path[MAX_PATH];
    int oldMode, result;
    LPCITEMIDLIST pidl;		/* Returned by browser */
    BROWSEINFO bInfo;		/* Used by browser */
    ChooseDir cdCBData;	    /* Structure to pass back and forth */
    LPMALLOC pMalloc;		/* Used by shell */

    HWND hWnd;

    TCHAR saveDir[MAX_PATH];
    Tcl_DString titleString;	/* Title */

    Tcl_DString tempString;	/* temporary */
    Tcl_Obj *objPtr;
    OFNOpts ofnOpts;
    const char *utfDir;

    result = ParseOFNOptions(clientData, interp, objc, objv,
                 OFN_DIR_CHOOSE, &ofnOpts);

    if (result != TCL_OK)
        return result;




    /* Use new dialogs if available */
    if (VistaFileDialogsAvailable() && ! ofnOpts.forceXPStyle) {
        result = GetFileNameVista(interp, &ofnOpts, OFN_DIR_CHOOSE);
        CleanupOFNOptions(&ofnOpts);

        return result;
    }

    /* Older dialogs */

    path[0] = '\0';
    ZeroMemory(&cdCBData, sizeof(ChooseDir));
    cdCBData.interp = interp;
    cdCBData.mustExist = ofnOpts.mustExist;


    utfDir = Tcl_DStringValue(&ofnOpts.utfDirString);





    if (utfDir[0] != '\0') {
	const TCHAR *uniStr;






















        Tcl_WinUtfToTChar(Tcl_DStringValue(&ofnOpts.utfDirString), -1,
                          &tempString);
        uniStr = (TCHAR *) Tcl_DStringValue(&tempString);


        /* Convert possible relative path to full path to keep dialog happy. */



        GetFullPathName(uniStr, MAX_PATH, saveDir, NULL);
        _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH);







    }










    /* XXX - rest of this (original) code has no error checks at all. */



    /*
     * Get ready to call the browser
     */

    Tk_MakeWindowExist(ofnOpts.tkwin);
    hWnd = Tk_GetHWND(Tk_WindowId(ofnOpts.tkwin));

    /*
     * Setup the parameters used by SHBrowseForFolder
     */

    bInfo.hwndOwner = hWnd;
    bInfo.pszDisplayName = path;
    bInfo.pidlRoot = NULL;
    if (_tcslen(cdCBData.initDir) == 0) {
	GetCurrentDirectory(MAX_PATH, cdCBData.initDir);
    }
    bInfo.lParam = (LPARAM) &cdCBData;

    if (ofnOpts.titleObj != NULL) {
	Tcl_WinUtfToTChar(Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
	bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString);
    } else {
	bInfo.lpszTitle = TEXT("Please choose a directory, then select OK.");
    }

    /*
     * Set flags to add edit box, status text line and use the new ui. Allow
................................................................................
     * user a chance to change their mind on an invalid folder if mustexist is
     * 0.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
    GetCurrentDirectory(MAX_PATH, saveDir);
    if (SHGetMalloc(&pMalloc) == NOERROR) {
        /*
         * XXX - MSDN says CoInitialize must have been called before
         * SHBrowseForFolder can be used but don't see that called anywhere.
         */
	pidl = SHBrowseForFolder(&bInfo);

	/*
	 * This is a fix for Windows 2000, which seems to modify the folder
	 * name buffer even when the dialog is canceled (in this case the
	 * buffer contains garbage). See [Bug #3002230]
	 */
................................................................................
	Tcl_DString ds;

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		ConvertExternalFilename(path, &ds), -1));
	Tcl_DStringFree(&ds);
    }

    CleanupOFNOptions(&ofnOpts);






    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * ChooseDirectoryValidateProc --
 *

Changes to jni/sdl2tk/win/tkWinInit.c.

153
154
155
156
157
158
159



















































160
161
162
163
164
165
166
167
    } else {
	titleString[len - 1] = L'\0';
	MessageBoxW(NULL, msgString, titleString,
		MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
		| MB_SETFOREGROUND | MB_TOPMOST);
    }
}



















































 
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    } else {
	titleString[len - 1] = L'\0';
	MessageBoxW(NULL, msgString, titleString,
		MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
		| MB_SETFOREGROUND | MB_TOPMOST);
    }
}
 
/*
 * ----------------------------------------------------------------------
 *
 * Win32ErrorObj --
 *
 *	Returns a string object containing text from a COM or Win32 error code
 *
 * Results:
 *	A Tcl_Obj containing the Win32 error message.
 *
 * Side effects:
 *	Removed the error message from the COM threads error object.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Obj*
TkWin32ErrorObj(
    HRESULT hrError)
{
    LPTSTR lpBuffer = NULL, p = NULL;
    TCHAR  sBuffer[30];
    Tcl_Obj* errPtr = NULL;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
	    | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError,
	    LANG_NEUTRAL, (LPTSTR)&lpBuffer, 0, NULL);

    if (lpBuffer == NULL) {
	lpBuffer = sBuffer;
	wsprintf(sBuffer, TEXT("Error Code: %08lX"), hrError);
    }

    if ((p = _tcsrchr(lpBuffer, TEXT('\r'))) != NULL) {
	*p = TEXT('\0');
    }

#ifdef _UNICODE
    errPtr = Tcl_NewUnicodeObj(lpBuffer, (int)wcslen(lpBuffer));
#else
    errPtr = Tcl_NewStringObj(lpBuffer, (int)strlen(lpBuffer));
#endif /* _UNICODE */

    if (lpBuffer != sBuffer) {
	LocalFree((HLOCAL)lpBuffer);
    }

    return errPtr;
}

 
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to jni/sdl2tk/win/tkWinInt.h.

195
196
197
198
199
200
201






202
203
204
205
206
207
208
MODULE_SCOPE void		TkpWinToplevelDeiconify(TkWindow *winPtr);
MODULE_SCOPE long		TkpWinToplevelIsControlledByWm(TkWindow *winPtr);
MODULE_SCOPE long		TkpWinToplevelMove(TkWindow *winPtr, int x, int y);
MODULE_SCOPE long		TkpWinToplevelOverrideRedirect(TkWindow *winPtr,
			    int reqValue);
MODULE_SCOPE void		TkpWinToplevelDetachWindow(TkWindow *winPtr);
MODULE_SCOPE int		TkpWmGetState(TkWindow *winPtr);







/*
 * The following functions are not present in old versions of Windows
 * API headers but are used in the Tk source to ensure 64bit
 * compatibility.
 */








>
>
>
>
>
>







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
MODULE_SCOPE void		TkpWinToplevelDeiconify(TkWindow *winPtr);
MODULE_SCOPE long		TkpWinToplevelIsControlledByWm(TkWindow *winPtr);
MODULE_SCOPE long		TkpWinToplevelMove(TkWindow *winPtr, int x, int y);
MODULE_SCOPE long		TkpWinToplevelOverrideRedirect(TkWindow *winPtr,
			    int reqValue);
MODULE_SCOPE void		TkpWinToplevelDetachWindow(TkWindow *winPtr);
MODULE_SCOPE int		TkpWmGetState(TkWindow *winPtr);

/*
 * Common routines used in Windows implementation
 */
MODULE_SCOPE Tcl_Obj *	        TkWin32ErrorObj(HRESULT hrError);


/*
 * The following functions are not present in old versions of Windows
 * API headers but are used in the Tk source to ensure 64bit
 * compatibility.
 */

Changes to jni/sdl2tk/win/tkWinSend.c.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
...
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
...
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
			    RegisteredInterp *riPtr);
#endif /* TK_SEND_ENABLED_ON_WINDOWS */
static int		FindInterpreterObject(Tcl_Interp *interp,
			    const char *name, LPDISPATCH *ppdisp);
static int		Send(LPDISPATCH pdispInterp, Tcl_Interp *interp,
			    int async, ClientData clientData, int objc,
			    Tcl_Obj *const objv[]);
static Tcl_Obj *	Win32ErrorObj(HRESULT hrError);
static void		SendTrace(const char *format, ...);
static Tcl_EventProc	SendEventProc;

#if defined(DEBUG) || defined(_DEBUG)
#define TRACE SendTrace
#else
#define TRACE 1 ? ((void)0) : SendTrace
................................................................................
	/*
	 * Expire the list if set.
	 */

	if (objList != NULL) {
	    Tcl_DecrRefCount(objList);
	}
	Tcl_SetObjResult(interp, Win32ErrorObj(hr));
	result = TCL_ERROR;
    }

    if (result == TCL_OK) {
	Tcl_SetObjResult(interp, objList);
    }

................................................................................
		pmk->lpVtbl->Release(pmk);
	    }
	    pBindCtx->lpVtbl->Release(pBindCtx);
	}
	pROT->lpVtbl->Release(pROT);
    }
    if (FAILED(hr) && result == TCL_OK) {
	Tcl_SetObjResult(interp, Win32ErrorObj(hr));
	result = TCL_ERROR;
    }
    return result;
}
 
/*
 *--------------------------------------------------------------
................................................................................
    SysFreeString(ei.bstrDescription);
    SysFreeString(ei.bstrSource);
    SysFreeString(ei.bstrHelpFile);
    VariantClear(&vCmd);

    return (SUCCEEDED(hr) ? TCL_OK : TCL_ERROR);
}
 
/*
 * ----------------------------------------------------------------------
 *
 * Win32ErrorObj --
 *
 *	Returns a string object containing text from a COM or Win32 error code
 *
 * Results:
 *	A Tcl_Obj containing the Win32 error message.
 *
 * Side effects:
 *	Removed the error message from the COM threads error object.
 *
 * ----------------------------------------------------------------------
 */

static Tcl_Obj*
Win32ErrorObj(
    HRESULT hrError)
{
    LPTSTR lpBuffer = NULL, p = NULL;
    TCHAR  sBuffer[30];
    Tcl_Obj* errPtr = NULL;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
	    | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError,
	    LANG_NEUTRAL, (LPTSTR)&lpBuffer, 0, NULL);

    if (lpBuffer == NULL) {
	lpBuffer = sBuffer;
	wsprintf(sBuffer, TEXT("Error Code: %08lX"), hrError);
    }

    if ((p = _tcsrchr(lpBuffer, TEXT('\r'))) != NULL) {
	*p = TEXT('\0');
    }

#ifdef _UNICODE
    errPtr = Tcl_NewUnicodeObj(lpBuffer, (int)wcslen(lpBuffer));
#else
    errPtr = Tcl_NewStringObj(lpBuffer, (int)strlen(lpBuffer));
#endif /* _UNICODE */

    if (lpBuffer != sBuffer) {
	LocalFree((HLOCAL)lpBuffer);
    }

    return errPtr;
}
 
/*
 * ----------------------------------------------------------------------
 *
 * TkWinSend_SetExcepInfo --
 *
 *	Convert the error information from a Tcl interpreter into a COM







<







 







|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







73
74
75
76
77
78
79

80
81
82
83
84
85
86
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
800
801
802
803
804
805
806


















































807
808
809
810
811
812
813
			    RegisteredInterp *riPtr);
#endif /* TK_SEND_ENABLED_ON_WINDOWS */
static int		FindInterpreterObject(Tcl_Interp *interp,
			    const char *name, LPDISPATCH *ppdisp);
static int		Send(LPDISPATCH pdispInterp, Tcl_Interp *interp,
			    int async, ClientData clientData, int objc,
			    Tcl_Obj *const objv[]);

static void		SendTrace(const char *format, ...);
static Tcl_EventProc	SendEventProc;

#if defined(DEBUG) || defined(_DEBUG)
#define TRACE SendTrace
#else
#define TRACE 1 ? ((void)0) : SendTrace
................................................................................
	/*
	 * Expire the list if set.
	 */

	if (objList != NULL) {
	    Tcl_DecrRefCount(objList);
	}
	Tcl_SetObjResult(interp, TkWin32ErrorObj(hr));
	result = TCL_ERROR;
    }

    if (result == TCL_OK) {
	Tcl_SetObjResult(interp, objList);
    }

................................................................................
		pmk->lpVtbl->Release(pmk);
	    }
	    pBindCtx->lpVtbl->Release(pBindCtx);
	}
	pROT->lpVtbl->Release(pROT);
    }
    if (FAILED(hr) && result == TCL_OK) {
	Tcl_SetObjResult(interp, TkWin32ErrorObj(hr));
	result = TCL_ERROR;
    }
    return result;
}
 
/*
 *--------------------------------------------------------------
................................................................................
    SysFreeString(ei.bstrDescription);
    SysFreeString(ei.bstrSource);
    SysFreeString(ei.bstrHelpFile);
    VariantClear(&vCmd);

    return (SUCCEEDED(hr) ? TCL_OK : TCL_ERROR);
}


















































 
/*
 * ----------------------------------------------------------------------
 *
 * TkWinSend_SetExcepInfo --
 *
 *	Convert the error information from a Tcl interpreter into a COM

Changes to jni/sdl2tk/win/tkWinTest.c.

74
75
76
77
78
79
80




































81
82
83
84
85
86
87
...
240
241
242
243
244
245
246

247
248
249
250
251

252
253
254
255
256
257
258
...
298
299
300
301
302
303
304

305
306
307
308
309
310
311
...
314
315
316
317
318
319
320

321











322
323
324
325
326
327
328
329
330






331

332
333
334
335
336
337
338
339
340
341
342
343
344
...
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398



399




















400
401
402
403
404
405
406
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testgetwindowinfo", TestgetwindowinfoObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testwinlocale", TestwinlocaleObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    return TCL_OK;
}




































 
/*
 *----------------------------------------------------------------------
 *
 * AppendSystemError --
 *
 *	This routine formats a Windows system error message and places it into
................................................................................
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    HWND hwnd = 0;
    HWND child = 0;

    int id;
    char *rest;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;

    static const TkStateMap messageMap[] = {
	{WM_LBUTTONDOWN,	"WM_LBUTTONDOWN"},
	{WM_LBUTTONUP,		"WM_LBUTTONUP"},
	{WM_CHAR,		"WM_CHAR"},
	{WM_GETTEXT,		"WM_GETTEXT"},
	{WM_SETTEXT,		"WM_SETTEXT"},
	{WM_COMMAND,            "WM_COMMAND"},
................................................................................
	}
	if (child == NULL) {
	    Tcl_AppendResult(interp, "could not find a control matching \"",
		Tcl_GetString(objv[2]), "\"", NULL);
	    return TCL_ERROR;
	}
    }

    message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3]));
    wParam = 0;
    lParam = 0;

    if (objc > 4) {
	wParam = strtol(Tcl_GetString(objv[4]), NULL, 0);
    }
................................................................................
    }

    switch (message) {
    case WM_GETTEXT: {
	Tcl_DString ds;
	char buf[256];


	GetDlgItemTextA(hwnd, id, buf, 256);











	Tcl_ExternalToUtfDString(NULL, buf, -1, &ds);
	Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
	Tcl_DStringFree(&ds);
	break;
    }
    case WM_SETTEXT: {
	Tcl_DString ds;
	BOOL result;







	Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[4]), -1, &ds);

	result = SetDlgItemTextA(hwnd, id, Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
	if (result == 0) {
    	Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1));
    	AppendSystemError(interp, GetLastError());
		return TCL_ERROR;
	}
	break;
    }
    case WM_COMMAND: {
	char buf[TCL_INTEGER_SPACE];
	if (objc < 5) {
	    wParam = MAKEWPARAM(id, 0);
................................................................................
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    const TCHAR  *title = NULL, *class = NULL;
    Tcl_DString titleString, classString;
    HWND hwnd = NULL;
    int r = TCL_OK;


    Tcl_DStringInit(&classString);
    Tcl_DStringInit(&titleString);

    if (objc < 2 || objc > 3) {
        Tcl_WrongNumArgs(interp, 1, objv, "title ?class?");
        return TCL_ERROR;
    }

    title = Tcl_WinUtfToTChar(Tcl_GetString(objv[1]), -1, &titleString);
    if (objc == 3) {
        class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString);
    }




    hwnd  = FindWindow(class, title);





















    if (hwnd == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1));
	AppendSystemError(interp, GetLastError());
	r = TCL_ERROR;
    } else {
        Tcl_SetObjResult(interp, Tcl_NewLongObj(PTR2INT(hwnd)));







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>





>







 







>







 







>

>
>
>
>
>
>
>
>
>
>
>







<

>
>
>
>
>
>

>
|


|
|
|







 







>













<
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testgetwindowinfo", TestgetwindowinfoObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testwinlocale", TestwinlocaleObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    return TCL_OK;
}
 
struct TestFindControlState {
    int  id;
    HWND control;
};    

/* Callback for window enumeration - used for TestFindControl */
BOOL CALLBACK TestFindControlCallback(
    HWND hwnd,
    LPARAM lParam
)
{
    struct TestFindControlState *fcsPtr = (struct TestFindControlState *)lParam;
    fcsPtr->control = GetDlgItem(hwnd, fcsPtr->id);
    /* If we have found the control, return FALSE to stop the enumeration */
    return fcsPtr->control == NULL ? TRUE : FALSE;
}

/*
 * Finds the descendent control window with the specified ID and returns
 * its HWND.
 */
HWND TestFindControl(HWND root, int id)
{
    struct TestFindControlState fcs;

    fcs.control = GetDlgItem(root, id);
    if (fcs.control == NULL) {
        /* Control is not a direct child. Look in descendents */
        fcs.id = id;
        fcs.control = NULL;
        EnumChildWindows(root, TestFindControlCallback, (LPARAM) &fcs);
    }
    return fcs.control;
}

 
/*
 *----------------------------------------------------------------------
 *
 * AppendSystemError --
 *
 *	This routine formats a Windows system error message and places it into
................................................................................
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    HWND hwnd = 0;
    HWND child = 0;
    HWND control;
    int id;
    char *rest;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
    LRESULT result;
    static const TkStateMap messageMap[] = {
	{WM_LBUTTONDOWN,	"WM_LBUTTONDOWN"},
	{WM_LBUTTONUP,		"WM_LBUTTONUP"},
	{WM_CHAR,		"WM_CHAR"},
	{WM_GETTEXT,		"WM_GETTEXT"},
	{WM_SETTEXT,		"WM_SETTEXT"},
	{WM_COMMAND,            "WM_COMMAND"},
................................................................................
	}
	if (child == NULL) {
	    Tcl_AppendResult(interp, "could not find a control matching \"",
		Tcl_GetString(objv[2]), "\"", NULL);
	    return TCL_ERROR;
	}
    }

    message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3]));
    wParam = 0;
    lParam = 0;

    if (objc > 4) {
	wParam = strtol(Tcl_GetString(objv[4]), NULL, 0);
    }
................................................................................
    }

    switch (message) {
    case WM_GETTEXT: {
	Tcl_DString ds;
	char buf[256];

#if 0
	GetDlgItemTextA(hwnd, id, buf, 256);
#else
        control = TestFindControl(hwnd, id);
        if (control == NULL) {
            Tcl_SetObjResult(interp,
                             Tcl_ObjPrintf("Could not find control with id %d", id));
            return TCL_ERROR;
        }
        buf[0] = 0;
        SendMessageA(control, WM_GETTEXT, (WPARAM)sizeof(buf),
                     (LPARAM) buf);
#endif
	Tcl_ExternalToUtfDString(NULL, buf, -1, &ds);
	Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
	Tcl_DStringFree(&ds);
	break;
    }
    case WM_SETTEXT: {
	Tcl_DString ds;


        control = TestFindControl(hwnd, id);
        if (control == NULL) {
            Tcl_SetObjResult(interp,
                             Tcl_ObjPrintf("Could not find control with id %d", id));
            return TCL_ERROR;
        }
	Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[4]), -1, &ds);
        result = SendMessageA(control, WM_SETTEXT, 0,
                                  (LPARAM) Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
	if (result == 0) {
            Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1));
            AppendSystemError(interp, GetLastError());
            return TCL_ERROR;
	}
	break;
    }
    case WM_COMMAND: {
	char buf[TCL_INTEGER_SPACE];
	if (objc < 5) {
	    wParam = MAKEWPARAM(id, 0);
................................................................................
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    const TCHAR  *title = NULL, *class = NULL;
    Tcl_DString titleString, classString;
    HWND hwnd = NULL;
    int r = TCL_OK;
    DWORD myPid;

    Tcl_DStringInit(&classString);
    Tcl_DStringInit(&titleString);

    if (objc < 2 || objc > 3) {
        Tcl_WrongNumArgs(interp, 1, objv, "title ?class?");
        return TCL_ERROR;
    }

    title = Tcl_WinUtfToTChar(Tcl_GetString(objv[1]), -1, &titleString);
    if (objc == 3) {
        class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString);
    }

    if (title[0] == 0)
        title = NULL;
#if 0
    hwnd  = FindWindow(class, title);
#else
    /* We want find a window the belongs to us and not some other process */
    hwnd = NULL;
    myPid = GetCurrentProcessId();
    while (1) {
        DWORD pid, tid;
        hwnd = FindWindowEx(NULL, hwnd, class, title);
        if (hwnd == NULL)
            break;
        tid = GetWindowThreadProcessId(hwnd, &pid);
        if (tid == 0) {
            /* Window has gone */
            hwnd = NULL;
            break;
        }
        if (pid == myPid)
            break;              /* Found it */
    }

#endif

    if (hwnd == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1));
	AppendSystemError(interp, GetLastError());
	r = TCL_ERROR;
    } else {
        Tcl_SetObjResult(interp, Tcl_NewLongObj(PTR2INT(hwnd)));

Changes to jni/sdl2tk/win/wish.exe.manifest.in.

16
17
18
19
20
21
22


23
24
25
26
27
28
29
			uiAccess="false"
		    />
	    </requestedPrivileges>
	</security>
    </trustInfo>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
	<application>


	    <!-- Windows 8.1 -->
	    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
	    <!-- Windows 8 -->
	    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
	    <!-- Windows 7 -->
	    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
	    <!-- Windows Vista -->







>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
			uiAccess="false"
		    />
	    </requestedPrivileges>
	</security>
    </trustInfo>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
	<application>
	    <!-- Windows 10 -->
	    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
	    <!-- Windows 8.1 -->
	    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
	    <!-- Windows 8 -->
	    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
	    <!-- Windows 7 -->
	    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
	    <!-- Windows Vista -->