Tk Source Code

Check-in [c512b82f]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:merge core-8-6-branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | canvas_image | tip-489
Files: files | file ages | folders
SHA3-256: c512b82f38164a23a27a94d449e1b1294612568d72088ec44aa29b164b9a2269
User & Date: fvogel 2017-11-11 12:50:12
Context
2017-11-27
20:27
Coding of the 'canvas image' command completed. check-in: 14b05087 user: scotty tags: canvas_image, tip-489
2017-11-11
12:50
merge core-8-6-branch check-in: c512b82f user: fvogel tags: canvas_image, tip-489
12:44
Add 'canvas image' command. Patch from Scott Pitcher. check-in: 543e8169 user: fvogel tags: canvas_image, tip-489
09:03
Fix [2fec274fe3]: OS X - menu-2.8[0134] triggers CFURLCopyResourcePropertyForKey failed check-in: 92068c2e user: fvogel tags: core-8-6-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to .fossil-settings/ignore-glob.

15
16
17
18
19
20
21
22
23

24

*/config.log
*/config.status
*/tkConfig.sh
*/wish*
*/tktest*
*/versions.vc
doc/man.macros
win/Debug_VC*
win/Release_VC*

unix/tk.pc







|
|
>

>
15
16
17
18
19
20
21
22
23
24
25
26
*/config.log
*/config.status
*/tkConfig.sh
*/wish*
*/tktest*
*/versions.vc
doc/man.macros
win/Debug*
win/Release*
win/nmhlp-out.txt
unix/tk.pc
html/*

Changes to doc/bind.n.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
...
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
...
602
603
604
605
606
607
608
609


610
611
612
613
614






615
616
617
618
619
620
621
.SH SYNOPSIS
\fBbind\fI tag\fR ?\fIsequence\fR? ?\fB+\fR??\fIscript\fR?
.BE
.SH "INTRODUCTION"
.PP
The \fBbind\fR command associates Tcl scripts with X events.
If all three arguments are specified, \fBbind\fR will
arrange for \fIscript\fR (a Tcl script) to be evaluated whenever

the event(s) given by \fIsequence\fR occur in the window(s)
identified by \fItag\fR.
If \fIscript\fR is prefixed with a
.QW + ,
then it is appended to
any existing binding for \fIsequence\fR;  otherwise \fIscript\fR replaces
any existing binding.
If \fIscript\fR is an empty string then the current binding for
\fIsequence\fR is destroyed, leaving \fIsequence\fR unbound.
................................................................................
to print out the keysym name for a particular key.
If a keysym \fIdetail\fR is given, then the
\fItype\fR field may be omitted;  it will default to \fBKeyPress\fR.
For example, \fB<Control\-comma>\fR is equivalent to
\fB<Control\-KeyPress\-comma>\fR.
.SH "BINDING SCRIPTS AND SUBSTITUTIONS"
.PP
The \fIscript\fR argument to \fBbind\fR is a Tcl script,

which will be executed whenever the given event sequence occurs.
\fICommand\fR will be executed in the same interpreter that the
\fBbind\fR command was executed in, and it will run at global
level (only global variables will be accessible).
If \fIscript\fR contains
any \fB%\fR characters, then the script will not be
executed directly.  Instead, a new script will be
................................................................................
an \fBall\fR binding.
The \fBbindtags\fR command may be used to change this order for
a particular window or to associate additional binding tags with
the window.
.PP
The \fBcontinue\fR and \fBbreak\fR commands may be used inside a
binding script to control the processing of matching scripts.
If \fBcontinue\fR is invoked, then the current binding script


is terminated but Tk will continue processing binding scripts
associated with other \fItag\fR's.
If the \fBbreak\fR command is invoked within a binding script,
then that script terminates and no other scripts will be invoked
for the event.






.PP
If more than one binding matches a particular event and they
have the same \fItag\fR, then the most specific binding
is chosen and its script is evaluated.
The following tests are applied, in order, to determine which of
several matching sequences is more specific:
.RS






|
>
|
|







 







|
>







 







|
>
>
|
|



>
>
>
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
...
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
.SH SYNOPSIS
\fBbind\fI tag\fR ?\fIsequence\fR? ?\fB+\fR??\fIscript\fR?
.BE
.SH "INTRODUCTION"
.PP
The \fBbind\fR command associates Tcl scripts with X events.
If all three arguments are specified, \fBbind\fR will
arrange for \fIscript\fR (a Tcl script called the
.QW "binding script")
to be evaluated whenever the event(s) given by \fIsequence\fR
occur in the window(s) identified by \fItag\fR.
If \fIscript\fR is prefixed with a
.QW + ,
then it is appended to
any existing binding for \fIsequence\fR;  otherwise \fIscript\fR replaces
any existing binding.
If \fIscript\fR is an empty string then the current binding for
\fIsequence\fR is destroyed, leaving \fIsequence\fR unbound.
................................................................................
to print out the keysym name for a particular key.
If a keysym \fIdetail\fR is given, then the
\fItype\fR field may be omitted;  it will default to \fBKeyPress\fR.
For example, \fB<Control\-comma>\fR is equivalent to
\fB<Control\-KeyPress\-comma>\fR.
.SH "BINDING SCRIPTS AND SUBSTITUTIONS"
.PP
The \fIscript\fR argument to \fBbind\fR is a Tcl script, called the
.QW "binding script",
which will be executed whenever the given event sequence occurs.
\fICommand\fR will be executed in the same interpreter that the
\fBbind\fR command was executed in, and it will run at global
level (only global variables will be accessible).
If \fIscript\fR contains
any \fB%\fR characters, then the script will not be
executed directly.  Instead, a new script will be
................................................................................
an \fBall\fR binding.
The \fBbindtags\fR command may be used to change this order for
a particular window or to associate additional binding tags with
the window.
.PP
The \fBcontinue\fR and \fBbreak\fR commands may be used inside a
binding script to control the processing of matching scripts.
If \fBcontinue\fR is invoked within a binding script, then this
binding script, including all other
.QW +
appended scripts, is terminated but Tk will continue processing
binding scripts associated with other \fItag\fR's.
If the \fBbreak\fR command is invoked within a binding script,
then that script terminates and no other scripts will be invoked
for the event.
.PP
Within a script called from the binding script, \fBreturn\fR
\fB-code ok\fR may be used to continue processing (including
.QW +
appended scripts), or \fBreturn\fR \fB-code break\fR may be used to
stop processing all other binding scripts.
.PP
If more than one binding matches a particular event and they
have the same \fItag\fR, then the most specific binding
is chosen and its script is evaluated.
The following tests are applied, in order, to determine which of
several matching sequences is more specific:
.RS

Changes to doc/text.n.

533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
option is only used when wrapping is enabled. If a text line wraps, the right
margin for each line on the display is determined by the first non-elided
character of that display line.
.TP
\fB\-rmargincolor \fIcolor\fR
.
\fIColor\fR specifies the background color to use in regions that do not
contain characters because they are indented by \fB\-rmargin1\fR. It may
have any of the forms accepted by \fBTk_GetColor\fR. If \fIcolor\fR has not
been specified, or if it is specified as an empty string, then the color
used is specified by the \fB-background\fR tag option (or, if this is also
unspecified, by the \fB-background\fR widget option).
.TP
\fB\-selectbackground \fIcolor\fR
\fIColor\fR specifies the background color to use when displaying selected






|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
option is only used when wrapping is enabled. If a text line wraps, the right
margin for each line on the display is determined by the first non-elided
character of that display line.
.TP
\fB\-rmargincolor \fIcolor\fR
.
\fIColor\fR specifies the background color to use in regions that do not
contain characters because they are indented by \fB\-rmargin\fR. It may
have any of the forms accepted by \fBTk_GetColor\fR. If \fIcolor\fR has not
been specified, or if it is specified as an empty string, then the color
used is specified by the \fB-background\fR tag option (or, if this is also
unspecified, by the \fB-background\fR widget option).
.TP
\fB\-selectbackground \fIcolor\fR
\fIColor\fR specifies the background color to use when displaying selected

Changes to doc/wm.n.

484
485
486
487
488
489
490
491







492
493
494
495
496
497
498
vice versa.
.PP
On X, the images are arranged into the _NET_WM_ICON X property, which
most modern window managers support.  A \fBwm iconbitmap\fR may exist
simultaneously.  It is recommended to use not more than 2 icons, placing
the larger icon first.
.PP
On Macintosh, this currently does nothing.







.RE
.TP
\fBwm iconposition \fIwindow\fR ?\fIx y\fR?
.
If \fIx\fR and \fIy\fR are specified, they are passed to the window
manager as a hint about where to position the icon for \fIwindow\fR.
In this case an empty string is returned.  If \fIx\fR and \fIy\fR are






|
>
>
>
>
>
>
>







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
vice versa.
.PP
On X, the images are arranged into the _NET_WM_ICON X property, which
most modern window managers support.  A \fBwm iconbitmap\fR may exist
simultaneously.  It is recommended to use not more than 2 icons, placing
the larger icon first.
.PP
On Macintosh, the first image called is loaded into an OSX-native icon
format, and becomes the application icon in dialogs, the Dock, and
other contexts. At present images loaded from PNG format lose their
alpha channel, but GIF format preserves its alpha/transparency. At the
script level the command will accept only the first image passed in the
parameters as support for multiple sizes/resolutions on macOS is outside Tk's
scope. Developers should use the largest icon they can support
(preferably 512 pixels) to ensure smooth rendering on the Mac. 
.RE
.TP
\fBwm iconposition \fIwindow\fR ?\fIx y\fR?
.
If \fIx\fR and \fIy\fR are specified, they are passed to the window
manager as a hint about where to position the icon for \fIwindow\fR.
In this case an empty string is returned.  If \fIx\fR and \fIy\fR are

Changes to generic/tkFont.c.

3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
	    continue;
	}

	cx[0] = cx[3] = chunkPtr->x;
	cy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent;
	cx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth;
	cy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent;
	if (	!PointInQuadrilateral(cx, cy, rx[0], ry[0]) ||
		!PointInQuadrilateral(cx, cy, rx[1], ry[1]) ||
		!PointInQuadrilateral(cx, cy, rx[2], ry[2]) ||
		!PointInQuadrilateral(cx, cy, rx[3], ry[3])) {
	    goto notReverseInside;
	}
    }
    return 0;

    /*
     * If we're overlapping now, we must be partially in and out of at least
     * one chunk. If that is the case, there must be one line segment of the
     * rectangle that is touching or crossing a line segment of a chunk.
     */

  notReverseInside:
    chunkPtr = layoutPtr->chunks;

    for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
	int j;

	if (chunkPtr->start[0] == '\n') {
	    /*






|
|
|
|
|
|

<







<







3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165
3166
3167

3168
3169
3170
3171
3172
3173
3174
	    continue;
	}

	cx[0] = cx[3] = chunkPtr->x;
	cy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent;
	cx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth;
	cy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent;
	if (	PointInQuadrilateral(cx, cy, rx[0], ry[0]) &&
		PointInQuadrilateral(cx, cy, rx[1], ry[1]) &&
		PointInQuadrilateral(cx, cy, rx[2], ry[2]) &&
		PointInQuadrilateral(cx, cy, rx[3], ry[3])) {
            return 0;
        }
    }


    /*
     * If we're overlapping now, we must be partially in and out of at least
     * one chunk. If that is the case, there must be one line segment of the
     * rectangle that is touching or crossing a line segment of a chunk.
     */


    chunkPtr = layoutPtr->chunks;

    for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
	int j;

	if (chunkPtr->start[0] == '\n') {
	    /*

Changes to generic/tkImgPhoto.c.

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
	    } else {
		height = (height - options.subsampleY - 1)
			/ -options.subsampleY;
	    }
	    options.toY2 = options.toY + height * options.zoomY;
	}

	/*














	 * Set the destination image size if the -shrink option was specified.



	 */

	if (options.options & OPT_SHRINK) {
	    if (ImgPhotoSetSize(masterPtr, options.toX2,
		    options.toY2) != TCL_OK) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
		return TCL_ERROR;
	    }
	}

	/*


	 * Copy the image data over using Tk_PhotoPutZoomedBlock.
	 */

	block.pixelPtr += options.fromX * block.pixelSize
		+ options.fromY * block.pitch;
	block.width = options.fromX2 - options.fromX;
	block.height = options.fromY2 - options.fromY;
	return Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr,
		&block, options.toX, options.toY, options.toX2 - options.toX,
		options.toY2 - options.toY, options.zoomX, options.zoomY,
		options.subsampleX, options.subsampleY,
		options.compositingRule);

    case PHOTO_DATA: {
	char *data;

	/*
	 * photo data command - first parse and check any options given.
	 */







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

>
>
>











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







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
	    } else {
		height = (height - options.subsampleY - 1)
			/ -options.subsampleY;
	    }
	    options.toY2 = options.toY + height * options.zoomY;
	}

	/*
	 * Copy the image data over using Tk_PhotoPutZoomedBlock.
	 */

	block.pixelPtr += options.fromX * block.pixelSize
		+ options.fromY * block.pitch;
	block.width = options.fromX2 - options.fromX;
	block.height = options.fromY2 - options.fromY;
	result = Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr,
		&block, options.toX, options.toY, options.toX2 - options.toX,
		options.toY2 - options.toY, options.zoomX, options.zoomY,
		options.subsampleX, options.subsampleY,
		options.compositingRule);

	/*
	 * Set the destination image size if the -shrink option was specified.
	 * This has to be done _after_ copying the data. Otherwise, if source
	 * and destination are the same image, block.pixelPtr would point to
	 * an invalid memory block (bug [5239fd749b]).
	 */

	if (options.options & OPT_SHRINK) {
	    if (ImgPhotoSetSize(masterPtr, options.toX2,
		    options.toY2) != TCL_OK) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
		return TCL_ERROR;
	    }
	}


	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
		masterPtr->width, masterPtr->height);
	return result;












    case PHOTO_DATA: {
	char *data;

	/*
	 * photo data command - first parse and check any options given.
	 */

Changes to generic/tkRectOval.c.

755
756
757
758
759
760
761
762
763
764















































765
766















































767
768
769
770
771
772
773
     * will die if it isn't.
     */

    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0],rectOvalPtr->bbox[1],
	    &x1, &y1);
    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3],
	    &x2, &y2);
    if (x2 <= x1) {
	x2 = x1+1;
    }















































    if (y2 <= y1) {
	y2 = y1+1;















































    }

    /*
     * Display filled part first (if wanted), then outline. If we're
     * stippling, then modify the stipple offset in the GC. Be sure to reset
     * the offset when done, since the GC is supposed to be read-only.
     */






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







755
756
757
758
759
760
761
762

763
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
795
796
797
798
799
800
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
865
     * will die if it isn't.
     */

    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0],rectOvalPtr->bbox[1],
	    &x1, &y1);
    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3],
	    &x2, &y2);
    if (x2 == x1) {


        /*
         * The width of the bounding box corresponds to less than one pixel
         * on screen. Adjustment is needed to avoid drawing attempts with zero
         * width items (which would draw nothing). The bounding box spans
         * either 1 or 2 pixels. Select which pixel will be drawn.
         */

        short ix1 = (short) (rectOvalPtr->bbox[0]);
        short ix2 = (short) (rectOvalPtr->bbox[2]);

        if (ix1 == ix2) {

            /*
             * x1 and x2 are "within the same pixel". Use this pixel.
             * Note: the degenerated case (bbox[0]==bbox[2]) of a completely
             * flat box results in arbitrary selection of the pixel at the
             * right (with positive coordinate) or left (with negative
             * coordinate) of the box. There is no "best choice" here.
             */

            if (ix1 > 0) {
                x2 += 1;
            } else {
                x1 -= 1;
            }
        } else {

            /*
             * (x1,x2) span two pixels. Select the one with the larger
             * covered "area".
             */

            if (ix1 > 0) {
                if ((rectOvalPtr->bbox[2] - ix2) > (ix2 - rectOvalPtr->bbox[0])) {
                    x2 += 1;
                } else {
                    x1 -= 1;
                }
            } else {
                if ((rectOvalPtr->bbox[2] - ix1) > (ix1 - rectOvalPtr->bbox[0])) {
                    x2 += 1;
                } else {
                    x1 -= 1;
                }
            }
        }
    }
    if (y2 == y1) {


        /*
         * The height of the bounding box corresponds to less than one pixel
         * on screen. Adjustment is needed to avoid drawing attempts with zero
         * height items (which would draw nothing). The bounding box spans
         * either 1 or 2 pixels. Select which pixel will be drawn.
         */

        short iy1 = (short) (rectOvalPtr->bbox[1]);
        short iy2 = (short) (rectOvalPtr->bbox[3]);

        if (iy1 == iy2) {

            /*
             * y1 and y2 are "within the same pixel". Use this pixel.
             * Note: the degenerated case (bbox[1]==bbox[3]) of a completely
             * flat box results in arbitrary selection of the pixel below
             * (with positive coordinate) or above (with negative coordinate)
             * the box. There is no "best choice" here.
             */

            if (iy1 > 0) {
                y2 += 1;
            } else {
                y1 -= 1;
            }
        } else {

            /*
             * (y1,y2) span two pixels. Select the one with the larger
             * covered "area".
             */

            if (iy1 > 0) {
                if ((rectOvalPtr->bbox[3] - iy2) > (iy2 - rectOvalPtr->bbox[1])) {
                    y2 += 1;
                } else {
                    y1 -= 1;
                }
            } else {
                if ((rectOvalPtr->bbox[3] - iy1) > (iy1 - rectOvalPtr->bbox[1])) {
                    y2 += 1;
                } else {
                    y1 -= 1;
                }
            }
        }
    }

    /*
     * Display filled part first (if wanted), then outline. If we're
     * stippling, then modify the stipple offset in the GC. Be sure to reset
     * the offset when done, since the GC is supposed to be read-only.
     */

Changes to generic/tkScale.c.

17
18
19
20
21
22
23




24
25
26
27
28
29
30
...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
932
933
934
935
936
937
938

939


940
941

942


943
944
945
946
947
948
949
....
1310
1311
1312
1313
1314
1315
1316

1317


1318
1319
1320
1321
1322
1323
1324
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "default.h"
#include "tkInt.h"
#include "tkScale.h"





/*
 * The following table defines the legal values for the -orient option. It is
 * used together with the "enum orient" declaration in tkScale.h.
 */

static const char *const orientStrings[] = {
    "horizontal", "vertical", NULL
................................................................................
		TCL_GLOBAL_ONLY);
	if ((valuePtr == NULL) || (Tcl_GetDoubleFromObj(NULL,
		valuePtr, &varValue) != TCL_OK)) {
	    ScaleSetVariable(scalePtr);
	} else {
	    char varString[TCL_DOUBLE_SPACE], scaleString[TCL_DOUBLE_SPACE];

	    sprintf(varString, scalePtr->format, varValue);
	    sprintf(scaleString, scalePtr->format, scalePtr->value);
	    if (strcmp(varString, scaleString)) {
		ScaleSetVariable(scalePtr);
	    }
	}
	Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),
		NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		ScaleVarProc, scalePtr);
    }
................................................................................

    /*
     * Vertical scale: compute the amount of space needed to display the
     * scales value by formatting strings for the two end points; use
     * whichever length is longer.
     */


    sprintf(valueString, scalePtr->format, scalePtr->fromValue);


    valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);


    sprintf(valueString, scalePtr->format, scalePtr->toValue);


    tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
    if (valuePixels < tmp) {
	valuePixels = tmp;
    }

    /*
     * Assign x-locations to the elements of the scale, working from left to
................................................................................
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;
    }
}
 






>
>
>
>







 







|
|
|







 







>
|
>
>


>
|
>
>







 







>
|
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
...
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
....
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "default.h"
#include "tkInt.h"
#include "tkScale.h"

#if defined(_WIN32)
#define snprintf _snprintf
#endif

/*
 * The following table defines the legal values for the -orient option. It is
 * used together with the "enum orient" declaration in tkScale.h.
 */

static const char *const orientStrings[] = {
    "horizontal", "vertical", NULL
................................................................................
		TCL_GLOBAL_ONLY);
	if ((valuePtr == NULL) || (Tcl_GetDoubleFromObj(NULL,
		valuePtr, &varValue) != TCL_OK)) {
	    ScaleSetVariable(scalePtr);
	} else {
	    char varString[TCL_DOUBLE_SPACE], scaleString[TCL_DOUBLE_SPACE];

            Tcl_PrintDouble(NULL, varValue, varString);
            Tcl_PrintDouble(NULL, scalePtr->value, scaleString);
            if (strcmp(varString, scaleString)) {
		ScaleSetVariable(scalePtr);
	    }
	}
	Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),
		NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		ScaleVarProc, scalePtr);
    }
................................................................................

    /*
     * Vertical scale: compute the amount of space needed to display the
     * scales value by formatting strings for the two end points; use
     * whichever length is longer.
     */

    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format,
            scalePtr->fromValue) < 0) {
        valueString[TCL_DOUBLE_SPACE - 1] = '\0';
    }
    valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);

    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format,
            scalePtr->toValue) < 0) {
        valueString[TCL_DOUBLE_SPACE - 1] = '\0';
    }
    tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
    if (valuePixels < tmp) {
	valuePixels = tmp;
    }

    /*
     * Assign x-locations to the elements of the scale, working from left to
................................................................................
static void
ScaleSetVariable(
    register TkScale *scalePtr)	/* Info about widget. */
{
    if (scalePtr->varNamePtr != NULL) {
	char string[TCL_DOUBLE_SPACE];

        if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
                scalePtr->value) < 0) {
            string[TCL_DOUBLE_SPACE - 1] = '\0';
        }
	scalePtr->flags |= SETTING_VAR;
	Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,
		Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);
	scalePtr->flags &= ~SETTING_VAR;
    }
}
 

Changes to generic/tkTextDisp.c.

4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
....
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
....
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
....
4438
4439
4440
4441
4442
4443
4444



























4445
4446
4447
4448
4449


4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462


4463
4464
4465
4466
4467
4468
4469
....
4478
4479
4480
4481
4482
4483
4484






4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
     * If drawing is disabled, all we need to do is
     * clear the REDRAW_PENDING flag.
     */
    TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
    MacDrawable *macWin = winPtr->privatePtr;
    if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
	dInfoPtr->flags &= ~REDRAW_PENDING;
	return;
    }
#endif

    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
	/*
	 * The widget has been deleted.	 Don't do anything.
	 */

................................................................................

	    dlPtr->oldY = dlPtr->y;
	    if (dlPtr->nextPtr == dlPtr2) {
		break;
	    }
	    dlPtr = dlPtr->nextPtr;
	}

	/*
	 * Scan through the lines following the copied ones to see if we are
	 * going to overwrite them with the copy operation. If so, mark them
	 * for redisplay.
	 */

	for ( ; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {
................................................................................
	 * calling TextInvalidateRegion to mark the display blocks as stale.
	 */

	damageRgn = TkCreateRegion();
	if (TkScrollWindow(textPtr->tkwin, dInfoPtr->scrollGC, dInfoPtr->x,
		oldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY,
		damageRgn)) {
#ifndef MAC_OSX_TK
	    TextInvalidateRegion(textPtr, damageRgn);
#endif
	}
	numCopies++;
	TkDestroyRegion(damageRgn);
    }

    /*
     * Clear the REDRAW_PENDING flag here. This is actually pretty tricky. We
................................................................................
#ifndef TK_NO_DOUBLE_BUFFERING
		    Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */
		    return;
		}
		dlPtr->oldY = dlPtr->y;
		dlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID);



























	    } else if (dlPtr->chunkPtr != NULL && ((dlPtr->y < 0)
		    || (dlPtr->y + dlPtr->height > dInfoPtr->maxY))) {
		register TkTextDispChunk *chunkPtr;

		/*


		 * It's the first or last DLine which are also overlapping the
		 * top or bottom of the window, but we decided above it wasn't
		 * necessary to display them (we were able to update them by
		 * scrolling). This is fine, except that if the lines contain
		 * any embedded windows, we must still call the display proc
		 * on them because they might need to be unmapped or they
		 * might need to be moved to reflect their new position.
		 * Otherwise, everything else moves, but the embedded window
		 * doesn't!
		 *
		 * So, we loop through all the chunks, calling the display
		 * proc of embedded windows only.
		 */



		for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
			chunkPtr = chunkPtr->nextPtr) {
		    int x;
		    if (chunkPtr->displayProc != TkTextEmbWinDisplayProc) {
			continue;
		    }
................................................................................
			 * as being off-screen to the left (the displayProc
			 * may not be able to tell if something is off to the
			 * right).
			 */

			x = -chunkPtr->width;
		    }






		    TkTextEmbWinDisplayProc(textPtr, chunkPtr, x,
			    dlPtr->spaceAbove,
			    dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow,
			    dlPtr->baseline - dlPtr->spaceAbove, NULL,
			    (Drawable) None, dlPtr->y + dlPtr->spaceAbove);
		}

	    }
	}
#ifndef TK_NO_DOUBLE_BUFFERING
	Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */
    }







|
|







 







<







 







<

<







 







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


<
<
|
>
>













>
>







 







>
>
>
>
>
>






<







4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
....
4270
4271
4272
4273
4274
4275
4276

4277
4278
4279
4280
4281
4282
4283
....
4293
4294
4295
4296
4297
4298
4299

4300

4301
4302
4303
4304
4305
4306
4307
....
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470


4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
....
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522

4523
4524
4525
4526
4527
4528
4529
     * If drawing is disabled, all we need to do is
     * clear the REDRAW_PENDING flag.
     */
    TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
    MacDrawable *macWin = winPtr->privatePtr;
    if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
	dInfoPtr->flags &= ~REDRAW_PENDING;
    	return;
     }
#endif

    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
	/*
	 * The widget has been deleted.	 Don't do anything.
	 */

................................................................................

	    dlPtr->oldY = dlPtr->y;
	    if (dlPtr->nextPtr == dlPtr2) {
		break;
	    }
	    dlPtr = dlPtr->nextPtr;
	}

	/*
	 * Scan through the lines following the copied ones to see if we are
	 * going to overwrite them with the copy operation. If so, mark them
	 * for redisplay.
	 */

	for ( ; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {
................................................................................
	 * calling TextInvalidateRegion to mark the display blocks as stale.
	 */

	damageRgn = TkCreateRegion();
	if (TkScrollWindow(textPtr->tkwin, dInfoPtr->scrollGC, dInfoPtr->x,
		oldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY,
		damageRgn)) {

	    TextInvalidateRegion(textPtr, damageRgn);

	}
	numCopies++;
	TkDestroyRegion(damageRgn);
    }

    /*
     * Clear the REDRAW_PENDING flag here. This is actually pretty tricky. We
................................................................................
#ifndef TK_NO_DOUBLE_BUFFERING
		    Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */
		    return;
		}
		dlPtr->oldY = dlPtr->y;
		dlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID);
#ifdef MAC_OSX_TK
	    } else if (dlPtr->chunkPtr != NULL) {
		/*
		 * On macOS we need to redisplay all embedded windows which
		 * were moved by the call to TkScrollWindows above.  This is
		 * not necessary on Unix or Windows because XScrollWindow will
		 * have included the bounding rectangles of all of these
		 * windows in the damage region.  The macosx implementation of
		 * TkScrollWindow does not do this.  It simply generates a
		 * damage region which is the scroll source rectangle minus
		 * the scroll destination rectangle.  This is because there is
		 * no efficient process available for iterating through the
		 * subwindows which meet the scrolled area.  (On Unix this is
		 * handled by GraphicsExpose events generated by XCopyArea and
		 * on Windows by ScrollWindowEx.  On macOS the low level
		 * scrolling is accomplished by calling [view scrollRect:by:].
		 * This method does not provide any damage information and, in
		 * any case, could not be aware of Tk windows which were not
		 * based on NSView objects.
		 *
		 * On the other hand, this loop is already iterating through
		 * all embedded windows which could possibly have been moved
		 * by the scrolling.  So it is as efficient to redisplay them
		 * here as it would have been if they had been redisplayed by
		 * the call to TextInvalidateRegion above.
		 */
#else
	    } else if (dlPtr->chunkPtr != NULL && ((dlPtr->y < 0)
		    || (dlPtr->y + dlPtr->height > dInfoPtr->maxY))) {


		/* 
		 * On platforms other than the Mac:
		 *
		 * It's the first or last DLine which are also overlapping the
		 * top or bottom of the window, but we decided above it wasn't
		 * necessary to display them (we were able to update them by
		 * scrolling). This is fine, except that if the lines contain
		 * any embedded windows, we must still call the display proc
		 * on them because they might need to be unmapped or they
		 * might need to be moved to reflect their new position.
		 * Otherwise, everything else moves, but the embedded window
		 * doesn't!
		 *
		 * So, we loop through all the chunks, calling the display
		 * proc of embedded windows only.
		 */
#endif
		register TkTextDispChunk *chunkPtr;

		for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
			chunkPtr = chunkPtr->nextPtr) {
		    int x;
		    if (chunkPtr->displayProc != TkTextEmbWinDisplayProc) {
			continue;
		    }
................................................................................
			 * as being off-screen to the left (the displayProc
			 * may not be able to tell if something is off to the
			 * right).
			 */

			x = -chunkPtr->width;
		    }
		    if (tkTextDebug) {
			char string[TK_POS_CHARS];

			TkTextPrintIndex(textPtr, &dlPtr->index, string);
			LOG("tk_textEmbWinDisplay", string);
		    }
		    TkTextEmbWinDisplayProc(textPtr, chunkPtr, x,
			    dlPtr->spaceAbove,
			    dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow,
			    dlPtr->baseline - dlPtr->spaceAbove, NULL,
			    (Drawable) None, dlPtr->y + dlPtr->spaceAbove);
		}

	    }
	}
#ifndef TK_NO_DOUBLE_BUFFERING
	Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */
    }

Changes to library/demos/twind.tcl.

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
108
109
110
111
112
113
114

115
116
117
118
119
120
121
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
298
299
300
301
302
303
304

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

320
321
322
323
324
325
$t insert end "You can also create multiple text widgets each of which "
$t insert end "display the same underlying text. Click this button to "
$t window create end \
  -create {button %W.peer -text "Make A Peer" -command "textMakePeer %W" \
  -cursor top_left_arrow} -padx 3
$t insert end " widget.  Notice how peer widgets can have different "
$t insert end "font settings, and by default contain all the images "
$t insert end "of the 'parent', but many of the embedded windows, "
$t insert end "such as buttons will not be there.  The easiest way "
$t insert end "to ensure they are in all peers is to use '-create' "
$t insert end "embedded window creation scripts "
$t insert end "(the plot above and the 'Make A Peer' button are "
$t insert end "designed to show up in all peers).  A good use of "
$t insert end "peers is for "
$t window create end \
  -create {button %W.split -text "Split Windows" -command "textSplitWindow %W" \
  -cursor top_left_arrow} -padx 3
$t insert end " \n\n"

$t insert end "Users of previous versions of Tk will also be interested "
................................................................................
$t insert end "text widget (\"Default\" restores the color to "
$t insert end "its default).  If you click on the button labeled "
$t insert end "\"Short\", it changes to a longer string so that "
$t insert end "you can see how the text widget automatically "
$t insert end "changes the layout.  Click on the button again "
$t insert end "to restore the short string.\n"


button $t.default -text Default -command "embDefBg $t" \
	-cursor top_left_arrow
$t window create end -window $t.default -padx 3
global embToggle
set embToggle Short
checkbutton $t.toggle -textvariable embToggle -indicatoron 0 \
	-variable embToggle -onvalue "A much longer string" \
................................................................................
$t window create end -window $t.bigP
$t window create end -window $t.smallP

$t insert end "\n\nFinally, images fit comfortably in text widgets too:"

$t image create end -image \
    [image create photo -file [file join $tk_demoDirectory images ouster.png]]


proc textWindBigB w {
    $w configure -borderwidth 15
}

proc textWindBigH w {
    $w configure -highlightthickness 15
................................................................................
    set n 1
    while {[winfo exists .peer$n]} { incr n }
    set w [toplevel .peer$n]
    wm title $w "Text Peer #$n"
    frame $w.f -highlightthickness 1 -borderwidth 1 -relief sunken
    set t [$parent peer create $w.f.text -yscrollcommand "$w.scroll set" \
	       -borderwidth 0 -highlightthickness 0]

    pack $t -expand  yes -fill both
    ttk::scrollbar $w.scroll -command "$t yview"
    pack $w.scroll -side right -fill y
    pack $w.f -expand yes -fill both
}

proc textSplitWindow {textW} {
................................................................................
	if {[winfo exists .twind.peer]} {
	    destroy .twind.peer
	} else {
	    set parent [winfo parent $textW]
	    set w [winfo parent $parent]
	    set t [$textW peer create $w.peer \
	      -yscrollcommand "$w.scroll set"]

	    $w.pane add $t
	}
    } else {
        return
    }
}






|
|
|
|
|
|







 







>







 







<







 







>







 







>






79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
...
160
161
162
163
164
165
166

167
168
169
170
171
172
173
...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
$t insert end "You can also create multiple text widgets each of which "
$t insert end "display the same underlying text. Click this button to "
$t window create end \
  -create {button %W.peer -text "Make A Peer" -command "textMakePeer %W" \
  -cursor top_left_arrow} -padx 3
$t insert end " widget.  Notice how peer widgets can have different "
$t insert end "font settings, and by default contain all the images "
$t insert end "of the 'parent', but that the embedded windows, "
$t insert end "such as buttons may not appear in the peer.  To ensure "
$t insert end "that embedded windows appear in all peers you can set the "
$t insert end "'-create' option to a script or a string containing %W.  "
$t insert end "(The plot above and the 'Make A Peer' button are "
$t insert end "designed to show up in all peers.)  A good use of "
$t insert end "peers is for "
$t window create end \
  -create {button %W.split -text "Split Windows" -command "textSplitWindow %W" \
  -cursor top_left_arrow} -padx 3
$t insert end " \n\n"

$t insert end "Users of previous versions of Tk will also be interested "
................................................................................
$t insert end "text widget (\"Default\" restores the color to "
$t insert end "its default).  If you click on the button labeled "
$t insert end "\"Short\", it changes to a longer string so that "
$t insert end "you can see how the text widget automatically "
$t insert end "changes the layout.  Click on the button again "
$t insert end "to restore the short string.\n"

$t insert end "\nNOTE: these buttons will not appear in peers!\n" "peer_warning"
button $t.default -text Default -command "embDefBg $t" \
	-cursor top_left_arrow
$t window create end -window $t.default -padx 3
global embToggle
set embToggle Short
checkbutton $t.toggle -textvariable embToggle -indicatoron 0 \
	-variable embToggle -onvalue "A much longer string" \
................................................................................
$t window create end -window $t.bigP
$t window create end -window $t.smallP

$t insert end "\n\nFinally, images fit comfortably in text widgets too:"

$t image create end -image \
    [image create photo -file [file join $tk_demoDirectory images ouster.png]]


proc textWindBigB w {
    $w configure -borderwidth 15
}

proc textWindBigH w {
    $w configure -highlightthickness 15
................................................................................
    set n 1
    while {[winfo exists .peer$n]} { incr n }
    set w [toplevel .peer$n]
    wm title $w "Text Peer #$n"
    frame $w.f -highlightthickness 1 -borderwidth 1 -relief sunken
    set t [$parent peer create $w.f.text -yscrollcommand "$w.scroll set" \
	       -borderwidth 0 -highlightthickness 0]
    $t tag configure peer_warning -font boldFont
    pack $t -expand  yes -fill both
    ttk::scrollbar $w.scroll -command "$t yview"
    pack $w.scroll -side right -fill y
    pack $w.f -expand yes -fill both
}

proc textSplitWindow {textW} {
................................................................................
	if {[winfo exists .twind.peer]} {
	    destroy .twind.peer
	} else {
	    set parent [winfo parent $textW]
	    set w [winfo parent $parent]
	    set t [$textW peer create $w.peer \
	      -yscrollcommand "$w.scroll set"]
	    $t tag configure peer_warning -font boldFont
	    $w.pane add $t
	}
    } else {
        return
    }
}

Changes to library/fontchooser.tcl.

61
62
63
64
65
66
67



68
69
70
71
72
73
74
proc ::tk::fontchooser::Show {} {
    variable S
    if {![winfo exists $S(W)]} {
        Create
        wm transient $S(W) [winfo toplevel $S(-parent)]
        tk::PlaceWindow $S(W) widget $S(-parent)
    }



    wm deiconify $S(W)
}

proc ::tk::fontchooser::Hide {} {
    variable S
    wm withdraw $S(W)
}






>
>
>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
proc ::tk::fontchooser::Show {} {
    variable S
    if {![winfo exists $S(W)]} {
        Create
        wm transient $S(W) [winfo toplevel $S(-parent)]
        tk::PlaceWindow $S(W) widget $S(-parent)
    }
    set S(fonts) [lsort -dictionary [font families]]
    set S(fonts,lcase) {}
    foreach font $S(fonts) { lappend S(fonts,lcase) [string tolower $font]}
    wm deiconify $S(W)
}

proc ::tk::fontchooser::Hide {} {
    variable S
    wm withdraw $S(W)
}

Changes to library/text.tcl.

764
765
766
767
768
769
770



771
772
773
774
775
776
777
	if {[$w compare $new < insert]} {
	    $w tag add sel $new insert
	} else {
	    $w tag add sel insert $new
	}
	$w mark set $anchorname insert
    } else {



	if {[$w compare $new < $anchorname]} {
	    set first $new
	    set last $anchorname
	} else {
	    set first $anchorname
	    set last $new
	}






>
>
>







764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
	if {[$w compare $new < insert]} {
	    $w tag add sel $new insert
	} else {
	    $w tag add sel insert $new
	}
	$w mark set $anchorname insert
    } else {
        if {[catch {$w index $anchorname}]} {
            $w mark set $anchorname insert
        }
	if {[$w compare $new < $anchorname]} {
	    set first $new
	    set last $anchorname
	} else {
	    set first $anchorname
	    set last $new
	}

Changes to library/tk.tcl.

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
    }
    return $result
}

# ::tk::AmpMenuArgs --
#	Processes arguments for a menu entry, turning -label option into
#	-label and -underline options, returned by ::tk::UnderlineAmpersand.

#
proc ::tk::AmpMenuArgs {widget add type args} {
    set options {}
    foreach {opt val} $args {
	if {$opt eq "-label"} {
	    lassign [UnderlineAmpersand $val] newlabel under
	    lappend options -label $newlabel -underline $under
	} else {
	    lappend options $opt $val
	}
    }
    $widget add $type {*}$options
}

# ::tk::FindAltKeyTarget --
#	Search recursively through the hierarchy of visible widgets to find
#	button or label which has $char as underlined character.
#
proc ::tk::FindAltKeyTarget {path char} {






>

|









|







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
    }
    return $result
}

# ::tk::AmpMenuArgs --
#	Processes arguments for a menu entry, turning -label option into
#	-label and -underline options, returned by ::tk::UnderlineAmpersand.
#      The cmd argument is supposed to be either "add" or "entryconfigure"
#
proc ::tk::AmpMenuArgs {widget cmd type args} {
    set options {}
    foreach {opt val} $args {
	if {$opt eq "-label"} {
	    lassign [UnderlineAmpersand $val] newlabel under
	    lappend options -label $newlabel -underline $under
	} else {
	    lappend options $opt $val
	}
    }
    $widget $cmd $type {*}$options
}

# ::tk::FindAltKeyTarget --
#	Search recursively through the hierarchy of visible widgets to find
#	button or label which has $char as underlined character.
#
proc ::tk::FindAltKeyTarget {path char} {

Changes to macosx/README.

1
2
3
4
5
6
7
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
41
42
43
44
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
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
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
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














































































































Tcl/Tk Mac OS X README
----------------------

This is the README file for the Mac OS X/Darwin version of Tcl/Tk.

1. Where to go for support
--------------------------

- The tcl-mac mailing list on sourceforge is the best place to ask questions
specific to Tcl & Tk on Mac OS X:
	http://lists.sourceforge.net/lists/listinfo/tcl-mac
(this page also has a link to searchable archives of the list, please check them
before asking on the list, many questions have already been answered).

- For general Tcl/Tk questions, the newsgroup comp.lang.tcl is your best bet:
	http://groups.google.com/group/comp.lang.tcl/

- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on Mac OS X, see
	http://wiki.tcl.tk/_/ref?N=3753
	http://wiki.tcl.tk/_/ref?N=8361

- Please report bugs with Tk on Mac OS X to the tracker:
	http://core.tcl.tk/tk/reportlist

2. Using Tcl/Tk on Mac OS X
---------------------------

- There are two versions of Tk available on Mac OS X: TkAqua using the native
aqua widgets and look&feel, and TkX11 using the traditional unix X11 wigets.
TkX11 requires an X11 server to be installed, such as Apple's X11 (which is
available as an optional or default install on recent Mac OS X).
TkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].

- At a minimum, Mac OS X 10.3 is required to run Tcl and TkX11.
TkAqua requires Mac OS X 10.5 or later (starting with the Cocoa-based Tk 8.5.7).

- Unless weak-linking is used, Tcl/Tk built on Mac OS X 10.x will not run on
10.y with y < x; on the other hand Tcl/Tk built on 10.y will always run on 10.x
with y <= x (but without any of the fixes and optimizations that would be
available in a binary built on 10.x).
Weak-linking is available on OS X 10.2 or later, it additionally allows Tcl/Tk
built on 10.x to run on any 10.y with x > y >= z (for a chosen z >= 2).

- Wish checks the Resources/Scripts directory in its application bundle for a
................................................................................
$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
This allows building extensions as frameworks with all script files contained in
the Resources/Scripts directory of the framework.

- [load]able binary extensions can linked as either ordinary shared libraries
(.dylib) or as MachO bundles (since 8.4.10/8.5a3); bundles have the advantage
that they are [load]ed more efficiently from a tcl VFS (no temporary copy to the
native filesystem required), and prior to Mac OS X 10.5, only bundles can be
[unload]ed.

- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
standard documentation location in the Tcl/Tk frameworks:
	Tcl.framework/Resources/Documentation/Reference/Tcl
	Tk.framework/Resources/Documentation/Reference/Tk
No nroff manpages are installed by default by the GNUmakefile.
................................................................................
application's Info.plist (or displaying an alert if no Help Book is set). This
action can be customized by defining a procedure named [tk::mac::ShowHelp], if
present, this procedure is invoked instead by the standard Help menu item.
Support for the Window menu and [tk::mac::ShowHelp] was added with the
Cocoa-based Tk 8.5.7.

- The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to
get and set Mac OS X-specific toplevel window class and attributes. Note that
the window class and many attributes have to be set before the window is first
mapped for the change to have any effect.
The command has the following syntax:
	tk::unsupported::MacWindowStyle style window ?class? ?attributes?
The 2 argument form returns a list of the current class and attributes for the
given window. The 3 argument form sets the class for the given window using the
default attributes for that class. The 4 argument form sets the class and the
................................................................................
magenta	#ff00ff
orange	#ff8000
purple 	#800080
brown	#996633
clear	systemTransparent

- The Cocoa-based TkAqua can be distinguished from the older Carbon-based
version via the [winfo server .] command, example output on Mac OS X 10.5.7:
    Cocoa-based:	CG409.3 Apple AppKit GC 949.46 Mac OS X 1057
    Carbon-based:	QD10R30 Apple 1057

- If you want to use Remote Debugging with Xcode, you need to set the
environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout.  Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.


3. Building Tcl/Tk on Mac OS X
------------------------------

- At least Mac OS X 10.3 is required to build Tcl and TkX11, and Mac OS X 10.5
is required to build TkAqua.
Apple's Xcode Developer Tools need to be installed (only the most recent version
matching your OS release is supported), the Xcode installer is available on Mac
OS X install media or may be present in /Applications/Installers on Macs that
came with OS X preinstalled. The most recent version can always be downloaded
from the ADC website http://connect.apple.com (free ADC membership required).

- Tcl/Tk are most easily built as Mac OS X frameworks via GNUmakefile in
tcl/macosx and tk/macosx (see below for details), but can also be built with the
standard unix configure and make buildsystem in tcl/unix resp. tk/unix as on any
other unix platform (indeed, the GNUmakefiles are just wrappers around the unix
buildsystem).
The Mac OS X specific configure flags are --enable-aqua, --enable-framework and
--disable-corefoundation (which disables CF and notably reverts to the standard
select based notifier). Note that --enable-aqua is incompatible with
--disable-corefoundation (for both Tcl and Tk configure).

- It is also possible to build with the Xcode IDE via the projects in
tk/macosx, take care to use the project matching your DevTools and OS version:
	Tk.xcode: 		    for Xcode 3.1 on 10.5
................................................................................
directories are named differently, e.g. '../../tcl8.6' and '../../tk8.6', you
need to manually change the TCL_SRCROOT and TK_SRCROOT settings by editing your
${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a
text editor.

- To build universal binaries outside of the Xcode IDE, set CFLAGS as follows:
	export CFLAGS="-arch i386 -arch x86_64 -arch ppc"
This requires Mac OS X 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is
omitted, but _not_ Xcode 2.1) and will work on any architecture (on PowerPC
Tiger you need to add "-isysroot /Developer/SDKs/MacOSX10.4u.sdk").
Note that configure requires CFLAGS to contain a least one architecture that can
be run on the build machine (i.e. ppc on G3/G4, ppc or ppc64 on G5, ppc or i386
on Core and ppc, i386 or x86_64 on Core2/Xeon).
Universal builds of Tcl TEA extensions are also possible with CFLAGS set as
above, they will be [load]able by universal as well as thin binaries of Tcl.
................................................................................
make overrides to the tk/macosx GNUmakefile, e.g.
	make -C tk${ver}/macosx \
	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
	sudo make -C tk${ver}/macosx install \
	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.

4. About the event loop in Tk for Mac OSX
-----------------------------------------




The main program in a typical OSX application looks like this (see *)



    void NSApplicationMain(int argc, char *argv[]) {
        [NSApplication sharedApplication];
        [NSBundle loadNibNamed:@"myMain" owner:NSApp];
        [NSApp run];
    }




The run method implements the event loop for the application.  There
are three key steps in the run method.  First it calls
[NSApp finishLaunching], which creates the bouncing application icon
and does other mysterious things. Second it creates an
NSAutoreleasePool.  Third, it starts an event loop which drains the
NSAutoreleasePool every time the queue is empty, and replaces the
drained pool with a new one.  This third step is essential to
preventing memory leaks, since the internal methods of Appkit objects
all assume that an autorelease pool is in scope and will be drained
when the event processing cycle ends.

Mac OSX Tk does not call the [NSApp run] method at all.  Instead it
uses the event loop built in to Tk.  So we must take care to replicate
the important features of the method ourselves.  Here is how this
works in outline.


































We add a private NSAUtoreleasePool* property to our subclass of
NSApplication.  (The subclass is called TKApplication but can be
referenced with the global variable NSApp).  The TkpInit
function calls [NSApp _setup] which initializes this property by
creating an NSAutoreleasePool. A bit later on, TkpInit calls
[NSAPP _setupEventLoop] which in turn calls the
[NSApp finishLaunching] method.

Each time that Tcl processes an event in its queue, it calls a
platform specific function which, in the case of Mac OSX, is named
TkMacOSXEventsCheckProc.  In the unix implementations of Tk, including
the Mac OSX version, this function collects events from an "event
source", and transfers them to the Tcl event queue.  In Mac OSX the
event source is the NSApplication event queue.  Each NSEvent is
converted to a Tcl event which is added to the Tcl event queue.  The
NSEvent is also passed to [NSApp sendevent], which sends the event on
to the application's NSWindows, which send it to their NSViews, etc.
Since the CheckProc function gets called for every Tk event, it is an
appropriate place to drain the main NSAutoreleasePool and replace it
with a new pool.  This is done by calling the method
[NSApp _resetAutoreleasePool], where _resetAutoreleasePool is a method
which we define for the subclass TKApplication.










One minor caveat is that there are several steps of the Tk

initialization which precede the call to TkpInit.  Notably, the font
package is initialized first.  Since there is no NSAUtoreleasePool in
scope prior to calling TkpInit, the functions called in these
preliminary stages need to create and drain their own
NSAutoreleasePools whenever they call methods of Appkit objects
(e.g. NSFont).

* https://developer.apple.com/library/mac/documentation/Cocoa/\
Reference/ApplicationKit/Classes/NSApplication_Class














































































































|


|





|







|



|


|


|


|


|
|

|







 







|







 







|







 







|
|








|


|







|




|







 







|







 







|
|
|
>
>
>
|
>
>






>
>
>

|
|
|
|







|
|
|
<
>
>

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

<
<
<
<
<
<
<
<
<


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

<
>
|
|
|
|



<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
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
41
42
43
44
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
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
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
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
Tcl/Tk macOS README
----------------------

This is the README file for the macOS/Darwin version of Tcl/Tk.

1. Where to go for support
--------------------------

- The tcl-mac mailing list on sourceforge is the best place to ask questions
specific to Tcl & Tk on macOS:
	http://lists.sourceforge.net/lists/listinfo/tcl-mac
(this page also has a link to searchable archives of the list, please check them
before asking on the list, many questions have already been answered).

- For general Tcl/Tk questions, the newsgroup comp.lang.tcl is your best bet:
	http://groups.google.com/group/comp.lang.tcl/

- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on macOS, see
	http://wiki.tcl.tk/_/ref?N=3753
	http://wiki.tcl.tk/_/ref?N=8361

- Please report bugs with Tk on macOS to the tracker:
	http://core.tcl.tk/tk/reportlist

2. Using Tcl/Tk on macOS
---------------------------

- There are two versions of Tk available on macOS: TkAqua using the native
aqua widgets and look&feel, and TkX11 using the traditional unix X11 wigets.
TkX11 requires an X11 server to be installed, such as Apple's X11 (which is
available as an optional or default install on recent macOS).
TkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].

- At a minimum, macOS 10.3 is required to run Tcl and TkX11.
TkAqua requires macOS 10.5 or later (starting with the Cocoa-based Tk 8.5.7).

- Unless weak-linking is used, Tcl/Tk built on macOS 10.x will not run on
10.y with y < x; on the other hand Tcl/Tk built on 10.y will always run on 10.x
with y <= x (but without any of the fixes and optimizations that would be
available in a binary built on 10.x).
Weak-linking is available on OS X 10.2 or later, it additionally allows Tcl/Tk
built on 10.x to run on any 10.y with x > y >= z (for a chosen z >= 2).

- Wish checks the Resources/Scripts directory in its application bundle for a
................................................................................
$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
This allows building extensions as frameworks with all script files contained in
the Resources/Scripts directory of the framework.

- [load]able binary extensions can linked as either ordinary shared libraries
(.dylib) or as MachO bundles (since 8.4.10/8.5a3); bundles have the advantage
that they are [load]ed more efficiently from a tcl VFS (no temporary copy to the
native filesystem required), and prior to macOS 10.5, only bundles can be
[unload]ed.

- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
standard documentation location in the Tcl/Tk frameworks:
	Tcl.framework/Resources/Documentation/Reference/Tcl
	Tk.framework/Resources/Documentation/Reference/Tk
No nroff manpages are installed by default by the GNUmakefile.
................................................................................
application's Info.plist (or displaying an alert if no Help Book is set). This
action can be customized by defining a procedure named [tk::mac::ShowHelp], if
present, this procedure is invoked instead by the standard Help menu item.
Support for the Window menu and [tk::mac::ShowHelp] was added with the
Cocoa-based Tk 8.5.7.

- The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to
get and set macOS-specific toplevel window class and attributes. Note that
the window class and many attributes have to be set before the window is first
mapped for the change to have any effect.
The command has the following syntax:
	tk::unsupported::MacWindowStyle style window ?class? ?attributes?
The 2 argument form returns a list of the current class and attributes for the
given window. The 3 argument form sets the class for the given window using the
default attributes for that class. The 4 argument form sets the class and the
................................................................................
magenta	#ff00ff
orange	#ff8000
purple 	#800080
brown	#996633
clear	systemTransparent

- The Cocoa-based TkAqua can be distinguished from the older Carbon-based
version via the [winfo server .] command, example output on macOS 10.5.7:
    Cocoa-based:	CG409.3 Apple AppKit GC 949.46 macOS 1057
    Carbon-based:	QD10R30 Apple 1057

- If you want to use Remote Debugging with Xcode, you need to set the
environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout.  Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.


3. Building Tcl/Tk on macOS
------------------------------

- At least macOS 10.3 is required to build Tcl and TkX11, and macOS 10.5
is required to build TkAqua.
Apple's Xcode Developer Tools need to be installed (only the most recent version
matching your OS release is supported), the Xcode installer is available on Mac
OS X install media or may be present in /Applications/Installers on Macs that
came with OS X preinstalled. The most recent version can always be downloaded
from the ADC website http://connect.apple.com (free ADC membership required).

- Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in
tcl/macosx and tk/macosx (see below for details), but can also be built with the
standard unix configure and make buildsystem in tcl/unix resp. tk/unix as on any
other unix platform (indeed, the GNUmakefiles are just wrappers around the unix
buildsystem).
The macOS specific configure flags are --enable-aqua, --enable-framework and
--disable-corefoundation (which disables CF and notably reverts to the standard
select based notifier). Note that --enable-aqua is incompatible with
--disable-corefoundation (for both Tcl and Tk configure).

- It is also possible to build with the Xcode IDE via the projects in
tk/macosx, take care to use the project matching your DevTools and OS version:
	Tk.xcode: 		    for Xcode 3.1 on 10.5
................................................................................
directories are named differently, e.g. '../../tcl8.6' and '../../tk8.6', you
need to manually change the TCL_SRCROOT and TK_SRCROOT settings by editing your
${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a
text editor.

- To build universal binaries outside of the Xcode IDE, set CFLAGS as follows:
	export CFLAGS="-arch i386 -arch x86_64 -arch ppc"
This requires macOS 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is
omitted, but _not_ Xcode 2.1) and will work on any architecture (on PowerPC
Tiger you need to add "-isysroot /Developer/SDKs/MacOSX10.4u.sdk").
Note that configure requires CFLAGS to contain a least one architecture that can
be run on the build machine (i.e. ppc on G3/G4, ppc or ppc64 on G5, ppc or i386
on Core and ppc, i386 or x86_64 on Core2/Xeon).
Universal builds of Tcl TEA extensions are also possible with CFLAGS set as
above, they will be [load]able by universal as well as thin binaries of Tcl.
................................................................................
make overrides to the tk/macosx GNUmakefile, e.g.
	make -C tk${ver}/macosx \
	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
	sudo make -C tk${ver}/macosx install \
	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.

4. Details regarding the macOS port of Tk.
-------------------------------------------
 
4.1 About the event loop
~~~~~~~~~~~~~~~~~~~~~~~~

The main program in a typical OSX application looks like this (see
https://developer.apple.com/library/mac/documentation/Cocoa/\
Reference/ApplicationKit/Classes/NSApplication_Class)

    void NSApplicationMain(int argc, char *argv[]) {
        [NSApplication sharedApplication];
        [NSBundle loadNibNamed:@"myMain" owner:NSApp];
        [NSApp run];
    }
Here NSApp is a standard global variable, initialized by the OS, which
points to an object in a subclass of NSApplication (called
TKApplication in the case of the macOS port of Tk).

The [NSApp run] method implements the event loop for a typical Mac
application.  There are three key steps in the run method.  First it
calls [NSApp finishLaunching], which creates the bouncing application
icon and does other mysterious things. Second it creates an
NSAutoreleasePool.  Third, it starts an event loop which drains the
NSAutoreleasePool every time the queue is empty, and replaces the
drained pool with a new one.  This third step is essential to
preventing memory leaks, since the internal methods of Appkit objects
all assume that an autorelease pool is in scope and will be drained
when the event processing cycle ends.

The macOS Tk application does not call the [NSApp run] method at
all.  Instead it uses the event loop built in to Tk.  So the
application must take care to replicate the important features of the

method ourselves.  The way that autorelease pools are handled is
discussed in 4.2 below.  Here we discuss the event handling itself.

The Tcl event loop simply consists of repeated calls to TclDoOneEvent.
Each call to TclDoOneEvent begins by collecting all pending events from
an "event source", converting them to Tcl events and adding them
to the Tcl event queue. For macOS, the event source is the NSApp
object, which maintains an event queue even though its run method
will never be called to process them.  The NSApp provides methods for
inspecting the queue and removing events from it as well as the
[NSApp sendevent] which sends an event to all of the application's
NSWindows which can then send it to subwindows, etc.

The event collection process consists of first calling a platform
specific SetupProc and then a platform specific CheckProc.  In
the macOS port, these are named TkMacOSXEventsSetupProc and
TkMacOSXEventsCheckProc.

It is important to understand that the Apple window manager does not
have the concept of an expose event.  Their replacement for an expose
event is to have the window manager call the [NSView drawRect] method
in any situation where an expose event for that NSView would be
generated in X11.  The [NSView drawRect] method is a no-op which is
expected to be overridden by any application.  In the case of Tcl, the
replacement [NSView drawRect] method creates a Tcl expose event
for each dirty rectangle of the NSView, and then adds the expose
event to the Tcl queue.


4.2 Autorelease pools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In order to carry out the job of managing autorelease pools, which
would normally be handled by the [NSApp run] method, a private
NSAUtoreleasePool* property is added to the TkApplication subclass of


NSApplication. The TkpInit function calls [NSApp _setup] which
initializes this property by creating an NSAutoreleasePool. A bit
later on, TkpInit calls [NSAPP _setupEventLoop] which in turn calls
the [NSApp finishLaunching] method.










Since the CheckProc function gets called for every Tk event, it is an
appropriate place to drain the main NSAutoreleasePool and replace it
with a new pool.  This is done by calling the method [NSApp
_resetAutoreleasePool], where _resetAutoreleasePool is a method which
we define for the subclass.  Unfortunately, by itself this is not
sufficient for safe memory managememt because, as was made painfully
evident with the release of OS X 10.13, it is possible for calls to
TclDoOneEvent, and hence to CheckProc, to be nested.  Draining the
autorelease pool in a nested call leads to crashes as objects in use
by the outer call can get freed by the inner call and then reused later.
One particular situation where this happens is when a modal dialogue
gets posted by a Tk Application.  To address this, the NSApp object
also implements a semaphore to prevent draining the autorelease pool
in nested calls to CheckProc.


One additional minor caveat for developers is that there are several
steps of the Tk initialization which precede the call to TkpInit.
Notably, the font package is initialized first.  Since there is no
NSAUtoreleasePool in scope prior to calling TkpInit, the functions
called in these preliminary stages need to create and drain their own
NSAutoreleasePools whenever they call methods of Appkit objects
(e.g. NSFont).



4.3 Clipping regions and "ghost windows"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Another unusual aspect of the macOS port is its use of clipping
regions.  It was part of Daniel Steffen's original design that the
TkWindowPrivate struct maintains three HIShapeRef regions, named
visRgn, aboveVisRgn and drawRgn.  These regions are used as clipping
masks whenever drawing into an NSView.  The visRgn is the bounding box
of the window with a rectangle removed for each subwindow and for each
sibling window at a higher stacking level.  The drawRgn is the
intersection of the visRgn with the clipping rectangle of the
window. (Normally, the clipping rectangle is the same as the bounding
rectangle, but drawing can be clipped to a smaller rectangle by
calling TkpClipDrawableToRect.) The aboveVisRgn is the intersection of
the window's bounding rectangle with the bounding rectangle of the
parent window.  Much of the code in tkMacOSXSubindows.c is devoted to
rebuilding these clipping regions whenever something changes in the
layout of the windows.  This turns out to be a tricky thing to do and
it is extremely prone to errors which can be difficult to trace.

It is not entirely clear what the original reason for using these
clipping regions was.  But one benefit is that if they are correctly
maintained then it allows windows to be drawn in any order.  You do
not have to draw them in the order of the window hierarchy.  Each
window can draw its entire rectangle through its own mask and never
have to worry about drawing in the wrong place.  It is likely that
the need for using clipping regions arose because, as Apple explicitly
states in the documentation for [NSView subviews],

    "The order of the subviews may be considered as being
    back-to-front, but this does not imply invalidation and drawing
    behavior."

In the early versions of the macOS port, buttons were implemented as
subviews of class TkButton.  This probably exacerbated the likelihood
that Tk windows would need to be drawn in arbitrary order.

The most obvious side effect caused by not maintaining the clipping
regions is the appearance of so-called "ghost windows".  A common
situation where these may arise is when a window containing buttons
is being scrolled.  A user may see two images of the same button on
the screen, one in the pre-scroll location and one in the post-scroll
location.

To see how these 'ghost windows' can arise, think about what happens if
the clipping regions are not maintained correctly.  A window might
have a rectangle missing from its clipping region because that
rectangle is the bounding rectangle for a subwindow, say a button.
The parent should not draw in the missing rectangle since doing so
would trash the button.  The button is responsible for drawing
there. Now imagine that the button gets moved, say by a scroll, but
the missing rectangle in the parent's clipping region does not get
moved correctly, or it gets moved later on, after the parent has
redrawn itself.  The parent would still not be allowed to draw in the
old rectangle, so the user would continue to see the image of the
button in its old location, as well as another image in the new
location.  This is a prototypical example of a "ghost window".
Anytime you see a "ghost window", you should suspect problems with the
updates to the clipping region visRgn.  It is natural to look for
timing issues, race conditions, or other "event loop problems".  But
in fact, the whole design of the code is to make those timing issues
irrelevant.  As long as the clipping regions are correctly maintained
the timing does not matter.  And if they are not correctly maintained
then you will see "ghost windows".

It is worth including a detailed description of one specific place
where the failure to correctly maintain clipping regions caused "ghost
window" artifacts that plagued the macOS port for years.  These
occurred when scrolling a Text widget which contained embedded
subwindows.  It involved some specific differences between the
low-level behavior of Apple's window manager versus those of the other
platforms, and the fix ultimately required changes in the generic Tk
implementation (documented in the comments in the DisplayText
function).

The Text widget attempts to improve perfomance when scrolling by
minimizing the number of text lines which need to be redisplayed.  It
does this by calling the platform-specific TkScrollWindow function
which uses a low-level routine to map one rectangle of the window to
another.  The TkScrollWindow function returns a damage region which is
then used by the Text widget's DisplayText function to determine which
text lines need to be redrawn.  On the unix and win platforms, this
damage region includes bounding rectangles for all embedded windows
inside the Text widget.  The way that this works is system dependent.
On unix, the low level scrolling is done by XCopyRegion, which
generates a GraphicsExpose event for each embedded window.  These
GraphicsExposed events are processsed within TkScrollWindow, using a
special handler which adds the bounding rectangle of each subwindow to
the damage region.  On the win platform the damage region is built by
the low level function ScrollWindowEx, and it also includes bounding
rectangles for all embedded windows.  This is possible because on X11
and Windows every Tk widget is also known to the window manager as a
window.  The situation is different on macOS.  The underlying object
for a top level window on macOS is the NSView.  However, Apple
explicitly warns in its documentation that performance degradation
occurs when an NSView has more than about 100 subviews.  A Text widget
with thousands of lines of text could easily contain more than 100
embedded windows.  In fact, while the original Cocoa port of Tk did
use the NSButton object, which is derived from NSView, as the basis
for its Tk Buttons, that was changed in order to improve performance.
Moreover, the low level routine used for scrolling on macOS, namely
[NSView scrollrect:by], does not provide any damage information.  So
TkScrollWindow needs to work differently on macOS.  Since it would be
inefficient to iterate through all embedded windows in a Text widget,
looking for those which meet the scrolling area, the damage region
constructed by TkScrollWindow contains only the difference between the
source and destination rectangles for the scrolling.  The embedded
windows are redrawn within the DisplayText function by some
conditional code which is only used for macOS.

Changes to macosx/Tk.xcode/project.pbxproj.

1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
....
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
		F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
		F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = "<group>"; };
		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
................................................................................
		};
		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,
				F96D447308F272BA004A47F5 /* coffbase.txt */,
				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.in */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,






<







 







<







1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
....
3811
3812
3813
3814
3815
3816
3817

3818
3819
3820
3821
3822
3823
3824
		F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };

		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
................................................................................
		};
		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,

				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.in */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,

Changes to macosx/Tk.xcodeproj/project.pbxproj.

1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
....
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
		F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
		F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = "<group>"; };
		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
................................................................................
		};
		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,
				F96D447308F272BA004A47F5 /* coffbase.txt */,
				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.in */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,






<







 







<







1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
....
3811
3812
3813
3814
3815
3816
3817

3818
3819
3820
3821
3822
3823
3824
		F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };

		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
................................................................................
		};
		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,

				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.in */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,

Changes to macosx/tkMacOSXBitmap.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"

/*
 * This structure holds information about native bitmaps.
 */

typedef struct {
    const char *name;		/* Name of icon. */
    OSType iconType;		/* OSType of icon. */
................................................................................
	if (image) {
	    [image setSize:size];
	}
    } else {
	string = [NSString stringWithUTF8String:name];
	image = [NSImage imageNamed:string];
	if (!image) {
	    NSURL *url = [NSURL URLWithString:string];
	    if (url) {
		image = [[[NSImage alloc] initWithContentsOfURL:url]
			autorelease];
	    }
	}
	if (image) {
	    size = [image size];






|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
/*
 * This structure holds information about native bitmaps.
 */

typedef struct {
    const char *name;		/* Name of icon. */
    OSType iconType;		/* OSType of icon. */
................................................................................
	if (image) {
	    [image setSize:size];
	}
    } else {
	string = [NSString stringWithUTF8String:name];
	image = [NSImage imageNamed:string];
	if (!image) {
	    NSURL *url = [NSURL fileURLWithPath:string];
	    if (url) {
		image = [[[NSImage alloc] initWithContentsOfURL:url]
			autorelease];
	    }
	}
	if (image) {
	    size = [image size];

Changes to macosx/tkMacOSXColor.c.

262
263
264
265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
	    break;
	    }
	case TRANSPARENT_PIXEL:
	    rgba[3]	= 0.0;
	    break;
	}

        // this attempts to find something roughly fitting for any display
//	*c = CGColorCreateGenericRGB(rgba[0], rgba[1], rgba[2], rgba[3]);

        // may be off for non-main display but in most cases better than prev
	static CGColorSpaceRef deviceRGBSpace = NULL;
	if (!deviceRGBSpace) {
	    deviceRGBSpace = CGDisplayCopyColorSpace(CGMainDisplayID());

	}
	*c = CGColorCreate(deviceRGBSpace, rgba );
    }
    return err;
}
 
/*






<
<
<
<


<
>







262
263
264
265
266
267
268




269
270

271
272
273
274
275
276
277
278
	    break;
	    }
	case TRANSPARENT_PIXEL:
	    rgba[3]	= 0.0;
	    break;
	}





	static CGColorSpaceRef deviceRGBSpace = NULL;
	if (!deviceRGBSpace) {

	    deviceRGBSpace = CGColorSpaceCreateDeviceRGB();
	}
	*c = CGColorCreate(deviceRGBSpace, rgba );
    }
    return err;
}
 
/*

Added macosx/tkMacOSXConstants.h.






























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
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
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
/*
 * tkMacOSXConstants.h --
 *
 *	Macros which map the names of NS constants used in the Tk code to
 *      the new name that Apple came up with for subsequent versions of the
 *      operating system.  (Each new OS release seems to come with a new
 *      naming convention for the same old constants.) 
 *
 * Copyright (c) 2017 Marc Culler
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TKMACCONSTANTS
#define _TKMACCONSTANTS

/*
 * Let's raise a glass for the project manager who improves our lives by
 * generating deprecation warnings about pointless changes of the names
 * of constants.
 */

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
#define NSOKButton NSModalResponseOK
#endif

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
#define NSAppKitDefined NSEventTypeAppKitDefined
#define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated
#define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated
#define NSWindowExposedEventType NSEventSubtypeWindowExposed
#define NSScreenChangedEventType NSEventSubtypeScreenChanged
#define NSWindowMovedEventType NSEventSubtypeWindowMoved
#define NSKeyUp NSEventTypeKeyUp
#define NSKeyDown NSEventTypeKeyDown
#define NSFlagsChanged NSEventTypeFlagsChanged
#define NSLeftMouseDown NSEventTypeLeftMouseDown
#define NSLeftMouseUp NSEventTypeLeftMouseUp
#define NSRightMouseDown NSEventTypeRightMouseDown
#define NSRightMouseUp NSEventTypeRightMouseUp
#define NSLeftMouseDragged NSEventTypeLeftMouseDragged
#define NSRightMouseDragged NSEventTypeRightMouseDragged
#define NSMouseMoved NSEventTypeMouseMoved
#define NSMouseEntered NSEventTypeMouseEntered
#define NSMouseExited NSEventTypeMouseExited
#define NSScrollWheel NSEventTypeScrollWheel
#define NSOtherMouseDown NSEventTypeOtherMouseDown
#define NSOtherMouseUp NSEventTypeOtherMouseUp
#define NSOtherMouseDragged NSEventTypeOtherMouseDragged
#define NSTabletPoint NSEventTypeTabletPoint
#define NSTabletProximity NSEventTypeTabletProximity
#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
#define NSCommandKeyMask NSEventModifierFlagCommand
#define NSShiftKeyMask NSEventModifierFlagShift
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock 
#define NSAlternateKeyMask NSEventModifierFlagOption
#define NSControlKeyMask NSEventModifierFlagControl
#define NSNumericPadKeyMask NSEventModifierFlagNumericPad
#define NSFunctionKeyMask NSEventModifierFlagFunction
#define NSCursorUpdate NSEventTypeCursorUpdate
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
#define NSCompositeCopy NSCompositingOperationCopy
#define NSWarningAlertStyle NSAlertStyleWarning
#define NSInformationalAlertStyle NSAlertStyleInformational
#define NSCriticalAlertStyle NSAlertStyleCritical
#define NSCenterTextAlignment NSTextAlignmentCenter
#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
#define NSCommandKeyMask NSEventModifierFlagCommand
#define NSShiftKeyMask NSEventModifierFlagShift
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
#define NSAlternateKeyMask NSEventModifierFlagOption
#define NSControlKeyMask NSEventModifierFlagControl
#define NSNumericPadKeyMask NSEventModifierFlagNumericPad
#define NSFunctionKeyMask NSEventModifierFlagFunction
#define NSKeyUp NSEventTypeKeyUp
#define NSKeyDown NSEventTypeKeyDown
#define NSFlagsChanged NSEventTypeFlagsChanged
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
#define NSShiftKeyMask NSEventModifierFlagShift
#define NSAnyEventMask NSEventMaskAny
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
#define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow
#define NSHUDWindowMask NSWindowStyleMaskHUDWindow
#define NSTitledWindowMask NSWindowStyleMaskTitled
#define NSClosableWindowMask NSWindowStyleMaskClosable
#define NSResizableWindowMask NSWindowStyleMaskResizable
#define NSUnifiedTitleAndToolbarWindowMask NSWindowStyleMaskUnifiedTitleAndToolbar
#define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable
#define NSBorderlessWindowMask NSWindowStyleMaskBorderless
#endif

#endif

Changes to macosx/tkMacOSXDialog.c.

10
11
12
13
14
15
16

17
18
19
20
21
22
23
...
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
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
266
267
268
269
270
271
272

273



274
275
276
277
278
279
280
281

282



283
284
285
286
287
288
289
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
713
714
715
716
717
718
719

720



721
722
723
724
725
726
727
...
880
881
882
883
884
885
886

887
888

889
890
891
892
893
894
895
...
967
968
969
970
971
972
973

974



975
976
977
978
979
980
981
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkFileFilter.h"


#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
#define modalOK     NSOKButton
#define modalCancel NSCancelButton
#else
#define modalOK     NSModalResponseOK
#define modalCancel NSModalResponseCancel
................................................................................
    }
    if (filename) {
	url = [NSURL URLWithString:filename relativeToURL:url];
    }
    return url;
}
#endif
 
 
#pragma mark TKApplication(TKDialog)

@interface NSColorPanel(TKDialog)
- (void) _setUseModalAppearance: (BOOL) flag;
@end

................................................................................
@implementation TKApplication(TKDialog)

- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
	returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
{
    FilePanelCallbackInfo *callbackInfo = contextInfo;

    if (returnCode == NSFileHandlingPanelOKButton) {
	Tcl_Obj *resultObj;

	if (callbackInfo->multiple) {
	    resultObj = Tcl_NewListObj(0, NULL);
	    for (NSURL *url in [(NSOpenPanel*)panel URLs]) {
		Tcl_ListObjAppendElement(callbackInfo->interp, resultObj,
			Tcl_NewStringObj([[url path] UTF8String], -1));
................................................................................
		TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
			TCL_EVAL_GLOBAL);
		ckfree(tmpv);
	    }
	} else {
	    Tcl_SetObjResult(callbackInfo->interp, resultObj);
	}
    } else if (returnCode == NSFileHandlingPanelCancelButton) {
	Tcl_ResetResult(callbackInfo->interp);
    }
    if (panel == [NSApp modalWindow]) {
	[NSApp stopModalWithCode:returnCode];
    }
    if (callbackInfo->cmdObj) {
	Tcl_DecrRefCount(callbackInfo->cmdObj);
................................................................................
	ckfree(callbackInfo);
    }
}

- (void)selectFormat:(id)sender  {
    NSPopUpButton *button                 = (NSPopUpButton *)sender;
    filterInfo.fileTypeIndex      = [button indexOfSelectedItem];

    NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex];



    [openpanel setAllowedFileTypes:allowedtypes];
    filterInfo.userHasSelectedFilter = true;

}

- (void)saveFormat:(id)sender  {
    NSPopUpButton *button                 = (NSPopUpButton *)sender;
    filterInfo.fileTypeIndex      = [button indexOfSelectedItem];

    NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex];



    [savepanel setAllowedFileTypes:allowedtypes];
}

@end

#pragma mark -
 
................................................................................
    }
    if (initialColor) {
	[colorPanel setColor:initialColor];
    }
    returnCode = [NSApp runModalForWindow:colorPanel];
    if (returnCode == modalOK) {
	color = [[colorPanel color] colorUsingColorSpace:
		[NSColorSpace genericRGBColorSpace]];
	numberOfComponents = [color numberOfComponents];
    }
    if (color && numberOfComponents >= 3 && numberOfComponents <= 4) {
	CGFloat components[4];
	char colorstr[8];

	[color getComponents:components];
................................................................................
	filterInfo.doFileTypes && filterInfo.userHasSelectedFilter) {
	/*
	 * The -typevariable must be set to the selected file type, if the dialog was not cancelled
	 */
	#if 0
	NSLog(@"result: %i modal: %li", result, (long)modalReturnCode);
	#endif

	NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex];



	Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
		Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
    }


  end:
    return result;
................................................................................
	[popupButton setAction:@selector(saveFormat:)];

	[accessoryView addSubview:label];
	[accessoryView addSubview:popupButton];

	[savepanel setAccessoryView:accessoryView];


	[savepanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]];
	[savepanel setAllowsOtherFileTypes:NO];

    } else if (defaultType) {
	/* If no filetypes are given, defaultextension is an alternative way
	 * to specify the attached extension. Just propose this extension,
	 * but don't display an accessory view */
	NSMutableArray *AllowedFileTypes = [NSMutableArray array];
	[AllowedFileTypes addObject:defaultType];
	[savepanel setAllowedFileTypes:AllowedFileTypes];
................................................................................
    if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) {
	/*
	 * The -typevariable must be set to the selected file type, if the dialog was not cancelled
	 */
	#if 0
	NSLog(@"result: %i modal: %li", result, (long)modalReturnCode);
	#endif

	NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex];



	Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
		Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
    }


  end:
    return result;






>







 







<







 







|







 







|







 







>

>
>
>








>

>
>
>







 







|







 







>

>
>
>







 







>


>







 







>

>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
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
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
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
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
...
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
...
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
...
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkFileFilter.h"
#include "tkMacOSXConstants.h"

#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
#define modalOK     NSOKButton
#define modalCancel NSCancelButton
#else
#define modalOK     NSModalResponseOK
#define modalCancel NSModalResponseCancel
................................................................................
    }
    if (filename) {
	url = [NSURL URLWithString:filename relativeToURL:url];
    }
    return url;
}
#endif

 
#pragma mark TKApplication(TKDialog)

@interface NSColorPanel(TKDialog)
- (void) _setUseModalAppearance: (BOOL) flag;
@end

................................................................................
@implementation TKApplication(TKDialog)

- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
	returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
{
    FilePanelCallbackInfo *callbackInfo = contextInfo;

    if (returnCode == modalOK) {
	Tcl_Obj *resultObj;

	if (callbackInfo->multiple) {
	    resultObj = Tcl_NewListObj(0, NULL);
	    for (NSURL *url in [(NSOpenPanel*)panel URLs]) {
		Tcl_ListObjAppendElement(callbackInfo->interp, resultObj,
			Tcl_NewStringObj([[url path] UTF8String], -1));
................................................................................
		TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
			TCL_EVAL_GLOBAL);
		ckfree(tmpv);
	    }
	} else {
	    Tcl_SetObjResult(callbackInfo->interp, resultObj);
	}
    } else if (returnCode == modalCancel) {
	Tcl_ResetResult(callbackInfo->interp);
    }
    if (panel == [NSApp modalWindow]) {
	[NSApp stopModalWithCode:returnCode];
    }
    if (callbackInfo->cmdObj) {
	Tcl_DecrRefCount(callbackInfo->cmdObj);
................................................................................
	ckfree(callbackInfo);
    }
}

- (void)selectFormat:(id)sender  {
    NSPopUpButton *button                 = (NSPopUpButton *)sender;
    filterInfo.fileTypeIndex      = [button indexOfSelectedItem];
#ifdef __clang__
    NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex];
#else
    NSMutableArray *allowedtypes = nil;
#endif
    [openpanel setAllowedFileTypes:allowedtypes];
    filterInfo.userHasSelectedFilter = true;

}

- (void)saveFormat:(id)sender  {
    NSPopUpButton *button                 = (NSPopUpButton *)sender;
    filterInfo.fileTypeIndex      = [button indexOfSelectedItem];
#ifdef __clang__
    NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex];
#else
    NSMutableArray *allowedtypes = nil;
#endif
    [savepanel setAllowedFileTypes:allowedtypes];
}

@end

#pragma mark -
 
................................................................................
    }
    if (initialColor) {
	[colorPanel setColor:initialColor];
    }
    returnCode = [NSApp runModalForWindow:colorPanel];
    if (returnCode == modalOK) {
	color = [[colorPanel color] colorUsingColorSpace:
		[NSColorSpace deviceRGBColorSpace]];
	numberOfComponents = [color numberOfComponents];
    }
    if (color && numberOfComponents >= 3 && numberOfComponents <= 4) {
	CGFloat components[4];
	char colorstr[8];

	[color getComponents:components];
................................................................................
	filterInfo.doFileTypes && filterInfo.userHasSelectedFilter) {
	/*
	 * The -typevariable must be set to the selected file type, if the dialog was not cancelled
	 */
	#if 0
	NSLog(@"result: %i modal: %li", result, (long)modalReturnCode);
	#endif
	#ifdef __clang__
	NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex];
	#else
	NSString * selectedFilter = [NSString string];
	#endif
	Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
		Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
    }


  end:
    return result;
................................................................................
	[popupButton setAction:@selector(saveFormat:)];

	[accessoryView addSubview:label];
	[accessoryView addSubview:popupButton];

	[savepanel setAccessoryView:accessoryView];

	#ifdef __clang__
	[savepanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]];
	[savepanel setAllowsOtherFileTypes:NO];
	#endif
    } else if (defaultType) {
	/* If no filetypes are given, defaultextension is an alternative way
	 * to specify the attached extension. Just propose this extension,
	 * but don't display an accessory view */
	NSMutableArray *AllowedFileTypes = [NSMutableArray array];
	[AllowedFileTypes addObject:defaultType];
	[savepanel setAllowedFileTypes:AllowedFileTypes];
................................................................................
    if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) {
	/*
	 * The -typevariable must be set to the selected file type, if the dialog was not cancelled
	 */
	#if 0
	NSLog(@"result: %i modal: %li", result, (long)modalReturnCode);
	#endif
	#ifdef __clang__
	NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex];
	#else
	NSString * selectedFilter = [NSString string];
	#endif
	Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
		Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
    }


  end:
    return result;

Changes to macosx/tkMacOSXDraw.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159


160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
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
...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
...
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
...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
...
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
....
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
....
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
....
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
....
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "xbytes.h"
#include "tkButton.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_DRAWING
#define TK_MAC_DEBUG_IMAGE_DRAWING
#endif
................................................................................
static int useThemedFrame = 0;

/*
 * Prototypes for functions used only in this file.
 */

static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);
static CGImageRef CreateCGImageWithXImage(XImage *ximage);
static CGContextRef GetCGContextForDrawable(Drawable d);
static void DrawCGImage(Drawable d, GC gc, CGContextRef context, CGImageRef image,
	unsigned long imageForeground, unsigned long imageBackground,
	CGRect imageBounds, CGRect srcBounds, CGRect dstBounds);

 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInitCGDrawing --
 *
 *	Initializes link vars that control CG drawing.
................................................................................
    }
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * BitmapRepFromDrawableRect
 *
 *	Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
 *
 * Results:
 *	Returns an autoreleased NSBitmapRep representing the image of the given
 *      rectangle of the given drawable.

 *
 *      NOTE: The x,y coordinates should be relative to a coordinate system with
 *      origin at the top left, as used by XImage and CGImage, not bottom
 *      left as used by NSView.
 *
 * Side effects:
 *     None
 *
 *----------------------------------------------------------------------
 */
NSBitmapImageRep*
BitmapRepFromDrawableRect(
        Drawable drawable,
	int x,
	int y,
	unsigned int width,
	unsigned int height)
{
    MacDrawable *mac_drawable = (MacDrawable *) drawable;
    CGContextRef cg_context=NULL;
    CGImageRef cg_image=NULL, sub_cg_image=NULL;
    NSBitmapImageRep *bitmap_rep=NULL;
    NSView *view=NULL;
    if ( mac_drawable->flags & TK_IS_PIXMAP ) {
	/*
	   This means that the MacDrawable is functioning as a Tk Pixmap, so its view
	   field is NULL.
	*/
	cg_context = GetCGContextForDrawable(drawable);
	CGRect image_rect = CGRectMake(x, y, width, height);
	cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
	sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
	if ( sub_cg_image ) {
	    /*This can be dealloc'ed prematurely if set for autorelease, causing crashes.*/
	    bitmap_rep = [NSBitmapImageRep alloc];
	    [bitmap_rep initWithCGImage:sub_cg_image];
	}
	if ( cg_image ) {
	    CGImageRelease(cg_image);
	}
    } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
	/* convert top-left coordinates to NSView coordinates */


	int view_height = [view bounds].size.height;
	NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
				      view_height - height - y - mac_drawable->yOff,
				      width,height);

	if ( [view lockFocusIfCanDraw] ) {
	    /*This can be dealloc'ed prematurely if set for autorelease, causing crashes.*/
	    bitmap_rep = [NSBitmapImageRep alloc];
	    bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect];
	    [view unlockFocus];
	} else {
	    TkMacOSXDbgMsg("Could not lock focus on view.");
	}

................................................................................
	/*TkMacOSXDbgMsg("Failed to setup drawing context.");*/
    }

    if ( dc.context ) {
	if (srcDraw->flags & TK_IS_PIXMAP) {
	    img = TkMacOSXCreateCGImageWithDrawable(src);
	}else if (TkMacOSXDrawableWindow(src)) {
	    bitmap_rep =  BitmapRepFromDrawableRect(src, src_x, src_y, width, height);
	    if ( bitmap_rep ) {
		img = [bitmap_rep CGImage];
	    }
	} else {
	    TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
	}

	if (img) {
	    DrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background,
			CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
			CGRectMake(src_x, src_y, width, height),
			CGRectMake(dest_x, dest_y, width, height));
	    CFRelease(img);


	} else {
................................................................................
		    CGContextFillRect(context, rect);
		    CGContextRestoreGState(context);
		    CGImageRelease(img);
		    CGImageRelease(mask);
		    CGImageRelease(submask);
		    CGImageRelease(subimage);
		} else {
		    DrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground,
				CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
				CGRectMake(src_x, src_y, width, height),
				CGRectMake(dest_x, dest_y, width, height));
		    CGImageRelease(img);
		}
	    } else { /* no image */
		TkMacOSXDbgMsg("Invalid source drawable");
................................................................................
	    TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context.");
	}
	TkMacOSXRestoreDrawingContext(&dc);
    } else { /* source drawable is a window, not a Pixmap */
	XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y);
    }
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkPutImage --
 *
 *	Copies a subimage from an in-memory image to a rectangle of
 *	of the specified drawable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws the image on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

int
TkPutImage(
    unsigned long *colors,	/* Unused on Macintosh. */
    int ncolors,			/* Unused on Macintosh. */
    Display* display,		/* Display. */
    Drawable d,			/* Drawable to place image on. */
    GC gc,				/* GC to use. */
    XImage* image,		/* Image to place. */
    int src_x,			/* Source X & Y. */
    int src_y,
    int dest_x,			/* Destination X & Y. */
    int dest_y,
    unsigned int width,	/* Same width & height for both */
    unsigned int height)	/* distination and source. */
{
    TkMacOSXDrawingContext dc;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGImageRef img = CreateCGImageWithXImage(image);

	if (img) {
	    /* If the XImage has big pixels, rescale the source dimensions.*/
	    int pp = image->pixelpower;
	    DrawCGImage(d, gc, dc.context, img, gc->foreground, gc->background,
		    CGRectMake(0, 0, image->width<<pp, image->height<<pp),
		    CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp),
		    CGRectMake(dest_x, dest_y, width, height));
	    CFRelease(img);
	} else {
	    TkMacOSXDbgMsg("Invalid source drawable");
	}
    } else {
	TkMacOSXDbgMsg("Invalid destination drawable");
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}
 
/*
 *----------------------------------------------------------------------
 *
 * CreateCGImageWithXImage --
 *
 *	Create CGImage from XImage, copying the image data.
 *
 * Results:
 *	CGImage, release after use.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void ReleaseData(void *info, const void *data, size_t size) {
    ckfree(info);
}

CGImageRef
CreateCGImageWithXImage(
    XImage *image)
{
    CGImageRef img = NULL;
    size_t bitsPerComponent, bitsPerPixel;
    size_t len = image->bytes_per_line * image->height;
    const CGFloat *decode = NULL;
    CGBitmapInfo bitmapInfo;
    CGDataProviderRef provider = NULL;
    char *data = NULL;
    CGDataProviderReleaseDataCallback releaseData = ReleaseData;

    if (image->bits_per_pixel == 1) {
	/*
	 * BW image
	 */

	/* Reverses the sense of the bits */
	static const CGFloat decodeWB[2] = {1, 0};
	decode = decodeWB;

	bitsPerComponent = 1;
	bitsPerPixel = 1;
	if (image->bitmap_bit_order != MSBFirst) {
	    char *srcPtr = image->data + image->xoffset;
	    char *endPtr = srcPtr + len;
	    char *destPtr = (data = ckalloc(len));

	    while (srcPtr < endPtr) {
		*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
	    }
	} else {
	    data = memcpy(ckalloc(len), image->data + image->xoffset, len);
	}
	if (data) {
	    provider = CGDataProviderCreateWithData(data, data, len, releaseData);
	}
	if (provider) {
	    img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
				    bitsPerPixel, image->bytes_per_line, 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);
	if (data) {
	    provider = CGDataProviderCreateWithData(data, data, len, releaseData);
	}
	if (provider) {
	    img = CGImageCreate(image->width, image->height, bitsPerComponent,
		    bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
		    provider, decode, 0, kCGRenderingIntentDefault);
	    CFRelease(provider);
	}
	if (colorspace) {
	    CFRelease(colorspace);
	}
    } else {
	TkMacOSXDbgMsg("Unsupported image type");
    }
    return img;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXCreateCGImageWithDrawable --
 *
 *	Create a CGImage from the given Drawable.
................................................................................
 */

CGImageRef
TkMacOSXCreateCGImageWithDrawable(
    Drawable drawable)
{
    CGImageRef img = NULL;
    CGContextRef context = GetCGContextForDrawable(drawable);

    if (context) {
	img = CGBitmapContextCreateImage(context);
    }
    return img;
}
 
................................................................................

    return [nsImage autorelease];
}
 
/*
 *----------------------------------------------------------------------
 *
 * GetCGContextForDrawable --
 *
 *	Get CGContext for given Drawable, creating one if necessary.
 *
 * Results:
 *	CGContext.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

CGContextRef
GetCGContextForDrawable(
    Drawable d)
{
    MacDrawable *macDraw = (MacDrawable *) d;

    if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) {
	const size_t bitsPerComponent = 8;
	size_t bitsPerPixel, bytesPerRow, len;
	CGColorSpaceRef colorspace = NULL;
	CGBitmapInfo bitmapInfo =
#ifdef __LITTLE_ENDIAN__
................................................................................
	char *data;
	CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height);

	if (macDraw->flags & TK_IS_BW_PIXMAP) {
	    bitsPerPixel = 8;
	    bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
	} else {
	    colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
	    bitsPerPixel = 32;
	    bitmapInfo |= kCGImageAlphaPremultipliedFirst;
	}
	bytesPerRow = ((size_t) macDraw->size.width * bitsPerPixel + 127) >> 3
		& ~15;
	len = macDraw->size.height * bytesPerRow;
	data = ckalloc(len);
................................................................................

    return (macDraw ? macDraw->context : NULL);
}
 
/*
 *----------------------------------------------------------------------
 *
 * DrawCGImage --
 *
 *	Draw CG image into drawable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
DrawCGImage(
    Drawable d,
    GC gc,
    CGContextRef context,
    CGImageRef image,
    unsigned long imageForeground,
    unsigned long imageBackground,
    CGRect imageBounds,
................................................................................
 *
 * TkScrollWindow --
 *
 *	Scroll a rectangle of the specified window and accumulate
 *	a damage region.
 *
 * Results:
 *	Returns 0 if the scroll genereated no additional damage.
 *	Otherwise, sets the region that needs to be repainted after
 *	scrolling and returns 1.
 *
 * Side effects:
 *	Scrolls the bits in the window.
 *
 *----------------------------------------------------------------------
................................................................................
    HIShapeRef dmgRgn = NULL, extraRgn = NULL;
    NSRect bounds, visRect, scrollSrc, scrollDst;
    int result = 0;

    if ( view ) {
  	/*  Get the scroll area in NSView coordinates (origin at bottom left). */
  	bounds = [view bounds];
 	scrollSrc = NSMakeRect(
			       macDraw->xOff + x,
			       bounds.size.height - height - (macDraw->yOff + y),
			       width, height);
 	scrollDst = NSOffsetRect(scrollSrc, dx, -dy);

  	/* Limit scrolling to the window content area. */
 	visRect = [view visibleRect];
 	scrollSrc = NSIntersectionRect(scrollSrc, visRect);
 	scrollDst = NSIntersectionRect(scrollDst, visRect);
 	if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {

  	    /*
  	     * Mark the difference between source and destination as damaged.
	     * This region is described in NSView coordinates (y=0 at the bottom)
	     * and converted to Tk coordinates later.
  	     */

	    srcRect = CGRectMake(x, y, width, height);
................................................................................

	    /* Compute the damage. */
  	    dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
 	    extraRgn = HIShapeCreateWithRect(&dstRect);
 	    ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
	    result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;

	    /* Convert to Tk coordinates. */
	    TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
	    if (extraRgn) {
		CFRelease(extraRgn);
	    }

 	    /* Scroll the rectangle. */
 	    [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];

	    /* Shift the Tk children which meet the source rectangle. */
	    TkWindow *winPtr = (TkWindow *)tkwin;
	    TkWindow *childPtr;
	    CGRect childBounds;
	    for (childPtr = winPtr->childList; childPtr != NULL; childPtr = childPtr->nextPtr) {
		if (Tk_IsMapped(childPtr) && !Tk_IsTopLevel(childPtr)) {
		    TkMacOSXWinCGBounds(childPtr, &childBounds);
		    if (CGRectIntersectsRect(srcRect, childBounds)) {
			MacDrawable *macChild = childPtr->privatePtr;
			if (macChild) {
			    macChild->yOff += dy;
			    macChild->xOff += dx;
			    childPtr->changes.y = macChild->yOff;
			    childPtr->changes.x = macChild->xOff;
			}
		    }
		}
	    }

	    /* Queue up Expose events for the damage region. */
	    int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
	    [view generateExposeEvents:dmgRgn childrenOnly:1];
	    Tcl_SetServiceMode(oldMode);
  	}
    } else {
	dmgRgn = HIShapeCreateEmpty();
	TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
    }

    if (dmgRgn) {
................................................................................
	ClipToGC(d, gc, &dc.clipRgn);
	dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0;
    }
    if (dontDraw) {
	goto end;
    }
    if (useCG) {
	dc.context = GetCGContextForDrawable(d);
    }
    if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) {
	isWin = (TkMacOSXDrawableWindow(d) != nil);
    }
    if (dc.context) {
	dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
    } else if (isWin) {






<







 







<
<
<
<
<
<







 







|




|
|
>











|













|
|

|




<







|
>
>


|
|


<







 







|








|







 







|







 







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







 







|







 







|













|
|

|







 







|







 







|













|







 







|







 







|
<









<







 







|







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







 







|







12
13
14
15
16
17
18

19
20
21
22
23
24
25
..
40
41
42
43
44
45
46






47
48
49
50
51
52
53
..
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
...
346
347
348
349
350
351
352
























































































































































353
354
355
356
357
358
359
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
...
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
...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
...
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
....
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
....
1354
1355
1356
1357
1358
1359
1360
1361

1362
1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
....
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
























1394
1395
1396
1397
1398
1399
1400
....
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"

#include "tkButton.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_DRAWING
#define TK_MAC_DEBUG_IMAGE_DRAWING
#endif
................................................................................
static int useThemedFrame = 0;

/*
 * Prototypes for functions used only in this file.
 */

static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);






 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInitCGDrawing --
 *
 *	Initializes link vars that control CG drawing.
................................................................................
    }
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXBitmapRepFromDrawableRect
 *
 *	Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
 *
 * Results:
 *	Returns an NSBitmapRep representing the image of the given
 *      rectangle of the given drawable.  This object is retained.
 *      The caller is responsible for releasing it.
 *
 *      NOTE: The x,y coordinates should be relative to a coordinate system with
 *      origin at the top left, as used by XImage and CGImage, not bottom
 *      left as used by NSView.
 *
 * Side effects:
 *     None
 *
 *----------------------------------------------------------------------
 */
NSBitmapImageRep*
TkMacOSXBitmapRepFromDrawableRect(
        Drawable drawable,
	int x,
	int y,
	unsigned int width,
	unsigned int height)
{
    MacDrawable *mac_drawable = (MacDrawable *) drawable;
    CGContextRef cg_context=NULL;
    CGImageRef cg_image=NULL, sub_cg_image=NULL;
    NSBitmapImageRep *bitmap_rep=NULL;
    NSView *view=NULL;
    if ( mac_drawable->flags & TK_IS_PIXMAP ) {
	/*
	 * This means that the MacDrawable is functioning as a
	 * Tk Pixmap, so its view field is NULL.
	*/
	cg_context = TkMacOSXGetCGContextForDrawable(drawable);
	CGRect image_rect = CGRectMake(x, y, width, height);
	cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
	sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
	if ( sub_cg_image ) {

	    bitmap_rep = [NSBitmapImageRep alloc];
	    [bitmap_rep initWithCGImage:sub_cg_image];
	}
	if ( cg_image ) {
	    CGImageRelease(cg_image);
	}
    } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
	/*
	 * Convert Tk top-left to NSView bottom-left coordinates.
	 */
	int view_height = [view bounds].size.height;
	NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
			       view_height - height - y - mac_drawable->yOff,
			       width, height);

	if ( [view lockFocusIfCanDraw] ) {

	    bitmap_rep = [NSBitmapImageRep alloc];
	    bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect];
	    [view unlockFocus];
	} else {
	    TkMacOSXDbgMsg("Could not lock focus on view.");
	}

................................................................................
	/*TkMacOSXDbgMsg("Failed to setup drawing context.");*/
    }

    if ( dc.context ) {
	if (srcDraw->flags & TK_IS_PIXMAP) {
	    img = TkMacOSXCreateCGImageWithDrawable(src);
	}else if (TkMacOSXDrawableWindow(src)) {
	    bitmap_rep =  TkMacOSXBitmapRepFromDrawableRect(src, src_x, src_y, width, height);
	    if ( bitmap_rep ) {
		img = [bitmap_rep CGImage];
	    }
	} else {
	    TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
	}

	if (img) {
	    TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background,
			CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
			CGRectMake(src_x, src_y, width, height),
			CGRectMake(dest_x, dest_y, width, height));
	    CFRelease(img);


	} else {
................................................................................
		    CGContextFillRect(context, rect);
		    CGContextRestoreGState(context);
		    CGImageRelease(img);
		    CGImageRelease(mask);
		    CGImageRelease(submask);
		    CGImageRelease(subimage);
		} else {
		    TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground,
				CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
				CGRectMake(src_x, src_y, width, height),
				CGRectMake(dest_x, dest_y, width, height));
		    CGImageRelease(img);
		}
	    } else { /* no image */
		TkMacOSXDbgMsg("Invalid source drawable");
................................................................................
	    TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context.");
	}
	TkMacOSXRestoreDrawingContext(&dc);
    } else { /* source drawable is a window, not a Pixmap */
	XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y);
    }
}
























































































































































 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXCreateCGImageWithDrawable --
 *
 *	Create a CGImage from the given Drawable.
................................................................................
 */

CGImageRef
TkMacOSXCreateCGImageWithDrawable(
    Drawable drawable)
{
    CGImageRef img = NULL;
    CGContextRef context = TkMacOSXGetCGContextForDrawable(drawable);

    if (context) {
	img = CGBitmapContextCreateImage(context);
    }
    return img;
}
 
................................................................................

    return [nsImage autorelease];
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetCGContextForDrawable --
 *
 *	Get CGContext for given Drawable, creating one if necessary.
 *
 * Results:
 *	CGContext.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

CGContextRef
TkMacOSXGetCGContextForDrawable(
    Drawable drawable)
{
    MacDrawable *macDraw = (MacDrawable *) drawable;

    if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) {
	const size_t bitsPerComponent = 8;
	size_t bitsPerPixel, bytesPerRow, len;
	CGColorSpaceRef colorspace = NULL;
	CGBitmapInfo bitmapInfo =
#ifdef __LITTLE_ENDIAN__
................................................................................
	char *data;
	CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height);

	if (macDraw->flags & TK_IS_BW_PIXMAP) {
	    bitsPerPixel = 8;
	    bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
	} else {
	    colorspace = CGColorSpaceCreateDeviceRGB();
	    bitsPerPixel = 32;
	    bitmapInfo |= kCGImageAlphaPremultipliedFirst;
	}
	bytesPerRow = ((size_t) macDraw->size.width * bitsPerPixel + 127) >> 3
		& ~15;
	len = macDraw->size.height * bytesPerRow;
	data = ckalloc(len);
................................................................................

    return (macDraw ? macDraw->context : NULL);
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXDrawCGImage --
 *
 *	Draw CG image into drawable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXDrawCGImage(
    Drawable d,
    GC gc,
    CGContextRef context,
    CGImageRef image,
    unsigned long imageForeground,
    unsigned long imageBackground,
    CGRect imageBounds,
................................................................................
 *
 * TkScrollWindow --
 *
 *	Scroll a rectangle of the specified window and accumulate
 *	a damage region.
 *
 * Results:
 *	Returns 0 if the scroll generated no additional damage.
 *	Otherwise, sets the region that needs to be repainted after
 *	scrolling and returns 1.
 *
 * Side effects:
 *	Scrolls the bits in the window.
 *
 *----------------------------------------------------------------------
................................................................................
    HIShapeRef dmgRgn = NULL, extraRgn = NULL;
    NSRect bounds, visRect, scrollSrc, scrollDst;
    int result = 0;

    if ( view ) {
  	/*  Get the scroll area in NSView coordinates (origin at bottom left). */
  	bounds = [view bounds];
 	scrollSrc = NSMakeRect(macDraw->xOff + x,

			       bounds.size.height - height - (macDraw->yOff + y),
			       width, height);
 	scrollDst = NSOffsetRect(scrollSrc, dx, -dy);

  	/* Limit scrolling to the window content area. */
 	visRect = [view visibleRect];
 	scrollSrc = NSIntersectionRect(scrollSrc, visRect);
 	scrollDst = NSIntersectionRect(scrollDst, visRect);
 	if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {

  	    /*
  	     * Mark the difference between source and destination as damaged.
	     * This region is described in NSView coordinates (y=0 at the bottom)
	     * and converted to Tk coordinates later.
  	     */

	    srcRect = CGRectMake(x, y, width, height);
................................................................................

	    /* Compute the damage. */
  	    dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
 	    extraRgn = HIShapeCreateWithRect(&dstRect);
 	    ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
	    result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;

	    /* Convert to Tk coordinates, offset by the window origin. */
	    TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
	    if (extraRgn) {
		CFRelease(extraRgn);
	    }

 	    /* Scroll the rectangle. */
 	    [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];
























  	}
    } else {
	dmgRgn = HIShapeCreateEmpty();
	TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
    }

    if (dmgRgn) {
................................................................................
	ClipToGC(d, gc, &dc.clipRgn);
	dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0;
    }
    if (dontDraw) {
	goto end;
    }
    if (useCG) {
	dc.context = TkMacOSXGetCGContextForDrawable(d);
    }
    if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) {
	isWin = (TkMacOSXDrawableWindow(d) != nil);
    }
    if (dc.context) {
	dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
    } else if (isWin) {

Changes to macosx/tkMacOSXEvent.c.

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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"


#pragma mark TKApplication(TKEvent)

enum {
    NSWindowWillMoveEventType = 20
};







>







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

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

#pragma mark TKApplication(TKEvent)

enum {
    NSWindowWillMoveEventType = 20
};

Changes to macosx/tkMacOSXHLEvents.c.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
 * Static functions used only in this file.
 */

static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
				 NSAppleEventDescriptor* replyEvent,
				 Tcl_Interp *interp,
				 char* procedure);
static int  MissedAnyParameters(const AppleEvent *theEvent);
static int  ReallyKillMe(Tcl_Event *eventPtr, int flags);

#pragma mark TKApplication(TKHLEvents)

@implementation TKApplication(TKHLEvents)
- (void) terminate: (id) sender
................................................................................
 */

static void
tkMacOSXProcessFiles(
    NSAppleEventDescriptor* event,
    NSAppleEventDescriptor* replyEvent,
    Tcl_Interp *interp,
    char* procedure)
{
    Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8");
    const AEDesc *fileSpecDesc = nil;
    AEDesc contents;
    char URLString[1 + URL_MAX_LENGTH];
    NSURL *fileURL;
    DescType type;






|







 







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
 * Static functions used only in this file.
 */

static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
				 NSAppleEventDescriptor* replyEvent,
				 Tcl_Interp *interp,
				 const char* procedure);
static int  MissedAnyParameters(const AppleEvent *theEvent);
static int  ReallyKillMe(Tcl_Event *eventPtr, int flags);

#pragma mark TKApplication(TKHLEvents)

@implementation TKApplication(TKHLEvents)
- (void) terminate: (id) sender
................................................................................
 */

static void
tkMacOSXProcessFiles(
    NSAppleEventDescriptor* event,
    NSAppleEventDescriptor* replyEvent,
    Tcl_Interp *interp,
    const char* procedure)
{
    Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8");
    const AEDesc *fileSpecDesc = nil;
    AEDesc contents;
    char URLString[1 + URL_MAX_LENGTH];
    NSURL *fileURL;
    DescType type;

Added macosx/tkMacOSXImage.c.






































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
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
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
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
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
/*
 * tkMacOSXImage.c --
 *
 *	The code in this file provides an interface for XImages,
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2005-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2017 Marc Culler.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "xbytes.h"

#pragma mark XImage handling

int
_XInitImageFuncPtrs(
    XImage *image)
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXCreateCGImageWithXImage --
 *
 *	Create CGImage from XImage, copying the image data.
 *
 * Results:
 *	CGImage, release after use.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void ReleaseData(void *info, const void *data, size_t size) {
    ckfree(info);
}

CGImageRef
TkMacOSXCreateCGImageWithXImage(
    XImage *image)
{
    CGImageRef img = NULL;
    size_t bitsPerComponent, bitsPerPixel;
    size_t len = image->bytes_per_line * image->height;
    const CGFloat *decode = NULL;
    CGBitmapInfo bitmapInfo;
    CGDataProviderRef provider = NULL;
    char *data = NULL;
    CGDataProviderReleaseDataCallback releaseData = ReleaseData;

    if (image->bits_per_pixel == 1) {
	/*
	 * BW image
	 */

	/* Reverses the sense of the bits */
	static const CGFloat decodeWB[2] = {1, 0};
	decode = decodeWB;

	bitsPerComponent = 1;
	bitsPerPixel = 1;
	if (image->bitmap_bit_order != MSBFirst) {
	    char *srcPtr = image->data + image->xoffset;
	    char *endPtr = srcPtr + len;
	    char *destPtr = (data = ckalloc(len));

	    while (srcPtr < endPtr) {
		*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
	    }
	} else {
	    data = memcpy(ckalloc(len), image->data + image->xoffset, len);
	}
	if (data) {
	    provider = CGDataProviderCreateWithData(data, data, len, releaseData);
	}
	if (provider) {
	    img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
				    bitsPerPixel, image->bytes_per_line, provider, decode, 0);
	}
    } else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
	/*
	 * Color image
	 */

	CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();

	bitsPerComponent = 8;
	bitsPerPixel = 32;
	bitmapInfo = (image->byte_order == MSBFirst ?
		kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) |
		kCGImageAlphaNoneSkipFirst;
	data = memcpy(ckalloc(len), image->data + image->xoffset, len);
	if (data) {
	    provider = CGDataProviderCreateWithData(data, data, len, releaseData);
	}
	if (provider) {
	    img = CGImageCreate(image->width, image->height, bitsPerComponent,
		    bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
		    provider, decode, 0, kCGRenderingIntentDefault);
	    CFRelease(provider);
	}
	if (colorspace) {
	    CFRelease(colorspace);
	}
    } else {
	TkMacOSXDbgMsg("Unsupported image type");
    }
    return img;
}
 

/*
 *----------------------------------------------------------------------
 *
 * XGetImage --
 *
 *	This function copies data from a pixmap or window into an XImage.
 *
 * Results:
 *	Returns a newly allocated XImage containing the data from the given
 *	rectangle of the given drawable, or NULL if the XImage could not be
 *	constructed.  NOTE: If we are copying from a window on a Retina
 *	display, the dimensions of the XImage will be 2*width x 2*height.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
struct pixel_fmt {int r; int g; int b; int a;};
static struct pixel_fmt bgra = {2, 1, 0, 3};
static struct pixel_fmt abgr = {3, 2, 1, 0};

XImage *
XGetImage(
    Display *display,
    Drawable drawable,
    int x,
    int y,
    unsigned int width,
    unsigned int height,
    unsigned long plane_mask,
    int format)
{
    NSBitmapImageRep* bitmap_rep = NULL;
    NSUInteger bitmap_fmt = 0;
    XImage* imagePtr = NULL;
    char* bitmap = NULL;
    char R, G, B, A;
    int depth = 32, offset = 0, bitmap_pad = 0;
    unsigned int bytes_per_row, size, row, n, m;
    unsigned int scalefactor=1, scaled_height=height, scaled_width=width;
    NSWindow *win = TkMacOSXDrawableWindow(drawable);
    static enum {unknown, no, yes} has_retina = unknown;

    if (win && has_retina == unknown) {
#ifdef __clang__
	has_retina = [win respondsToSelector:@selector(backingScaleFactor)]?
	    yes : no;
#else
	has_retina = no;
#endif
    }

    if (has_retina == yes) {
	/*
	 * We only allow scale factors 1 or 2, as Apple currently does.
	 */
#ifdef __clang__
	scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1;
#endif
	scaled_height *= scalefactor;
	scaled_width *= scalefactor;
    }

    if (format == ZPixmap) {
	if (width == 0 || height == 0) {
	    return NULL;
	}
	bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
		         x, y, width, height);
	if (!bitmap_rep) {
	    TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
	    return NULL;
	}
	bitmap_fmt = [bitmap_rep bitmapFormat];
	size = [bitmap_rep bytesPerPlane];
	bytes_per_row = [bitmap_rep bytesPerRow];
	bitmap = ckalloc(size);
	if (!bitmap                              ||
	    (bitmap_fmt != 0 && bitmap_fmt != 1) ||
	    [bitmap_rep samplesPerPixel] != 4    ||
	    [bitmap_rep isPlanar] != 0           ||
	    bytes_per_row != 4 * scaled_width    ||
	    size != bytes_per_row*scaled_height  ) {
	    TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
	    CFRelease(bitmap_rep);
	    return NULL;
	}
	memcpy(bitmap, (char *)[bitmap_rep bitmapData], size);
	CFRelease(bitmap_rep);
	
	/*
	 * When Apple extracts a bitmap from an NSView, it may be in
	 * either BGRA or ABGR format.  For an XImage we need RGBA.
	 */
	struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;

	for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) {
	    for (m=n; m<n+bytes_per_row; m+=4) {
		R = *(bitmap + m + pixel.r);
		G = *(bitmap + m + pixel.g);
		B = *(bitmap + m + pixel.b);
		A = *(bitmap + m + pixel.a);
		
		*(bitmap + m)     = R;
		*(bitmap + m + 1) = G;
		*(bitmap + m + 2) = B;
		*(bitmap + m + 3) = A;
	    }
	}
	imagePtr = XCreateImage(display, NULL, depth, format, offset,
				(char*)bitmap, scaled_width, scaled_height,
				bitmap_pad, bytes_per_row);
	if (scalefactor == 2) {
	    imagePtr->pixelpower = 1;
	}
    } else {
	/*
	 * There are some calls to XGetImage in the generic Tk
	 * code which pass an XYPixmap rather than a ZPixmap.
	 * XYPixmaps should be handled here.
	 */
	TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment.");
    }
    return imagePtr;
}
 
/*
 *----------------------------------------------------------------------
 *
 * DestroyImage --
 *
 *	Destroys storage associated with an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Deallocates the image.
 *
 *----------------------------------------------------------------------
 */

static int
DestroyImage(
    XImage *image)
{
    if (image) {
	if (image->data) {
	    ckfree(image->data);
	}
	ckfree(image);
    }
    return 0;
}
 
/*
 *----------------------------------------------------------------------
 *
 * ImageGetPixel --
 *
 *	Get a single pixel from an image.
 *
 * Results:
 *	Returns the 32 bit pixel value.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned long
ImageGetPixel(
    XImage *image,
    int x,
    int y)
{
    unsigned char r = 0, g = 0, b = 0;

    if (image && image->data) {
	unsigned char *srcPtr = ((unsigned char*) image->data)
		+ (y * image->bytes_per_line)
		+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);

	switch (image->bits_per_pixel) {
	    case 32: {
		r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
		g = (*((unsigned int*) srcPtr) >>  8) & 0xff;
		b = (*((unsigned int*) srcPtr)      ) & 0xff;
		/*if (image->byte_order == LSBFirst) {
		    r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
		} else {
		    r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
		}*/
		break;
	    }
	    case 16:
		r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
		g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
		b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
		break;
	    case 8:
		r = (*srcPtr << 2) & 0xc0;
		g = (*srcPtr << 4) & 0xc0;
		b = (*srcPtr << 6) & 0xc0;
		r |= r >> 2 | r >> 4 | r >> 6;
		g |= g >> 2 | g >> 4 | g >> 6;
		b |= b >> 2 | b >> 4 | b >> 6;
		break;
	    case 4: {
		unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
		r = (c & 0x04) ? 0xff : 0;
		g = (c & 0x02) ? 0xff : 0;
		b = (c & 0x01) ? 0xff : 0;
		break;
		}
	    case 1:
		r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
		break;
	}
    }
    return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
}
 
/*
 *----------------------------------------------------------------------
 *
 * ImagePutPixel --
 *
 *	Set a single pixel in an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ImagePutPixel(
    XImage *image,
    int x,
    int y,
    unsigned long pixel)
{
    if (image && image->data) {
	unsigned char r = ((pixel & image->red_mask)   >> 16) & 0xff;
	unsigned char g = ((pixel & image->green_mask) >>  8) & 0xff;
	unsigned char b = ((pixel & image->blue_mask)       ) & 0xff;
	unsigned char *dstPtr = ((unsigned char*) image->data)
		+ (y * image->bytes_per_line)
		+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);

	switch (image->bits_per_pixel) {
	    case 32:
		*((unsigned int*) dstPtr) = (0xff << 24) | (r << 16) |
			(g << 8) | b;
		/*if (image->byte_order == LSBFirst) {
		    dstPtr[3] = 0xff; dstPtr[2] = r; dstPtr[1] = g; dstPtr[0] = b;
		} else {
		    dstPtr[0] = 0xff; dstPtr[1] = r; dstPtr[2] = g; dstPtr[3] = b;
		}*/
		break;
	    case 16:
		*((unsigned short*) dstPtr) = ((r & 0xf8) << 7) |
			((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
		break;
	    case 8:
		*dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) |
			((b & 0xc0) >> 6);
		break;
	    case 4: {
		unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) |
			((b & 0x80) >> 7);
		*dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) :
			((*dstPtr & 0x0f) | ((c << 4) & 0xf0));
		break;
		}
	    case 1:
		*dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) :
			(*dstPtr & ~(0x80 >> (x % 8)));
		break;
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * XCreateImage --
 *
 *	Allocates storage for a new XImage.
 *
 * Results:
 *	Returns a newly allocated XImage.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

XImage *
XCreateImage(
    Display* display,
    Visual* visual,
    unsigned int depth,
    int format,
    int offset,
    char* data,
    unsigned int width,
    unsigned int height,
    int bitmap_pad,
    int bytes_per_line)
{
    XImage *ximage;
    display->request++;
    ximage = ckalloc(sizeof(XImage));

    ximage->height = height;
    ximage->width = width;
    ximage->depth = depth;
    ximage->xoffset = offset;
    ximage->format = format;
    ximage->data = data;
    ximage->obdata = NULL;
    /* The default pixelpower is 0.  This must be explicitly set to 1 in the
     * case of an XImage extracted from a Retina display.
     */
    ximage->pixelpower = 0;

    if (format == ZPixmap) {
	ximage->bits_per_pixel = 32;
	ximage->bitmap_unit = 32;
    } else {
	ximage->bits_per_pixel = 1;
	ximage->bitmap_unit = 8;
    }
    if (bitmap_pad) {
	ximage->bitmap_pad = bitmap_pad;
    } else {
	/* Use 16 byte alignment for best Quartz perfomance */
	ximage->bitmap_pad = 128;
    }
    if (bytes_per_line) {
	ximage->bytes_per_line = bytes_per_line;
    } else {
	ximage->bytes_per_line = ((width * ximage->bits_per_pixel +
		(ximage->bitmap_pad - 1)) >> 3) &
		~((ximage->bitmap_pad >> 3) - 1);
    }
#ifdef WORDS_BIGENDIAN
    ximage->byte_order = MSBFirst;
    ximage->bitmap_bit_order = MSBFirst;
#else
    ximage->byte_order = LSBFirst;
    ximage->bitmap_bit_order = LSBFirst;
#endif
    ximage->red_mask = 0x00FF0000;
    ximage->green_mask = 0x0000FF00;
    ximage->blue_mask = 0x000000FF;
    ximage->f.create_image = NULL;
    ximage->f.destroy_image = DestroyImage;
    ximage->f.get_pixel = ImageGetPixel;
    ximage->f.put_pixel = ImagePutPixel;
    ximage->f.sub_image = NULL;
    ximage->f.add_pixel = NULL;

    return ximage;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkPutImage --
 *
 *	Copies a subimage from an in-memory image to a rectangle of
 *	of the specified drawable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws the image on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

int
TkPutImage(
    unsigned long *colors,	/* Unused on Macintosh. */
    int ncolors,			/* Unused on Macintosh. */
    Display* display,		/* Display. */
    Drawable d,			/* Drawable to place image on. */
    GC gc,				/* GC to use. */
    XImage* image,		/* Image to place. */
    int src_x,			/* Source X & Y. */
    int src_y,
    int dest_x,			/* Destination X & Y. */
    int dest_y,
    unsigned int width,	/* Same width & height for both */
    unsigned int height)	/* distination and source. */
{
    TkMacOSXDrawingContext dc;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGImageRef img = TkMacOSXCreateCGImageWithXImage(image);

	if (img) {
	    /* If the XImage has big pixels, rescale the source dimensions.*/
	    int pp = image->pixelpower;
	    TkMacOSXDrawCGImage(d, gc, dc.context,
		    img, gc->foreground, gc->background,
		    CGRectMake(0, 0, image->width<<pp, image->height<<pp),
		    CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp),
		    CGRectMake(dest_x, dest_y, width, height));
	    CFRelease(img);
	} else {
	    TkMacOSXDbgMsg("Invalid source drawable");
	}
    } else {
	TkMacOSXDbgMsg("Invalid destination drawable");
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}
 
/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */

Changes to macosx/tkMacOSXInit.c.

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
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
@end

@interface TKApplication(TKMenus)
- (void) _setupMenus;
@end

@implementation TKApplication
@synthesize poolProtected = _poolProtected;
@end







@implementation TKApplication(TKInit)
- (void) _resetAutoreleasePool
{
    if(![self poolProtected]) {
	[_mainPool drain];
	_mainPool = [NSAutoreleasePool new];




    }
}








#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void) _postedNotification: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
#endif

................................................................................
    [pool drain];
}

- (void) _setup: (Tcl_Interp *) interp
{
    _eventInterp = interp;
    _mainPool = [NSAutoreleasePool new];
    [NSApp setPoolProtected:NO];
    _defaultMainMenu = nil;
    [self _setupMenus];
    [self setDelegate:self];
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    [[NSNotificationCenter defaultCenter] addObserver:self
	    selector:@selector(_postedNotification:) name:nil object:nil];
#endif






|


>
>
>
>
>
>



|


>
>
>
>


>
>
>
>
>
>
>
>







 







|







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
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@end

@interface TKApplication(TKMenus)
- (void) _setupMenus;
@end

@implementation TKApplication
@synthesize poolLock = _poolLock;
@end

/*
 * #define this to see a message on stderr whenever _resetAutoreleasePool is
 * called while the pool is locked.
 */
#undef DEBUG_LOCK

@implementation TKApplication(TKInit)
- (void) _resetAutoreleasePool
{
    if([self poolLock] == 0) {
	[_mainPool drain];
	_mainPool = [NSAutoreleasePool new];
    } else {
#ifdef DEBUG_LOCK
	fprintf(stderr, "Pool is locked with count %d!!!!\n", [self poolLock]);
#endif
    }
}
- (void) _lockAutoreleasePool
{
    [self setPoolLock:[self poolLock] + 1];
}
- (void) _unlockAutoreleasePool
{
    [self setPoolLock:[self poolLock] - 1];
}
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void) _postedNotification: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
#endif

................................................................................
    [pool drain];
}

- (void) _setup: (Tcl_Interp *) interp
{
    _eventInterp = interp;
    _mainPool = [NSAutoreleasePool new];
    [NSApp setPoolLock:0];
    _defaultMainMenu = nil;
    [self _setupMenus];
    [self setDelegate:self];
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    [[NSNotificationCenter defaultCenter] addObserver:self
	    selector:@selector(_postedNotification:) name:nil object:nil];
#endif

Changes to macosx/tkMacOSXKeyEvent.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"


/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_KEYBOARD
#endif
*/
#define NS_KEYLOG 0






>







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

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXConstants.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_KEYBOARD
#endif
*/
#define NS_KEYLOG 0

Changes to macosx/tkMacOSXKeyboard.c.

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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"

/*
 * A couple of simple definitions to make code a bit more self-explaining.
 *
 * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
 * tkMacOSXMouseEvent.c.
 */







|







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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXConstants.h"
/*
 * A couple of simple definitions to make code a bit more self-explaining.
 *
 * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
 * tkMacOSXMouseEvent.c.
 */

Changes to macosx/tkMacOSXMenu.c.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
#include "tkMacOSXPrivate.h"
#include "tkMenubutton.h"
#include "tkMenu.h"
#include "tkColor.h"
#include "tkFont.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXDebug.h"


/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_MENUS
#endif
*/







>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "tkMacOSXPrivate.h"
#include "tkMenubutton.h"
#include "tkMenu.h"
#include "tkColor.h"
#include "tkFont.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_MENUS
#endif
*/

Changes to macosx/tkMacOSXMenus.c.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMenu.h"


static void		GenerateEditEvent(const char *name);
static Tcl_Obj *	GetWidgetDemoPath(Tcl_Interp *interp);
 
#pragma mark TKApplication(TKMenus)

@implementation TKApplication(TKMenus)






>







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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMenu.h"
#include "tkMacOSXConstants.h"

static void		GenerateEditEvent(const char *name);
static Tcl_Obj *	GetWidgetDemoPath(Tcl_Interp *interp);
 
#pragma mark TKApplication(TKMenus)

@implementation TKApplication(TKMenus)

Changes to macosx/tkMacOSXMouseEvent.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"


typedef struct {
    unsigned int state;
    long delta;
    Window window;
    Point global;
    Point local;






>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

typedef struct {
    unsigned int state;
    long delta;
    Window window;
    Point global;
    Point local;

Changes to macosx/tkMacOSXNotify.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
212
213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
...
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
...
299
300
301
302
303
304
305


306
307
308
309
310
311
312
313
314
315
316
317
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"

#include <tclInt.h>
#include <pthread.h>
#import <objc/objc-auto.h>

/* This is not used for anything at the moment. */
typedef struct ThreadSpecificData {
    int initialized;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
................................................................................
	tsdPtr->initialized = 1;

	/*
	 * Install TkAqua event source in main event loop thread.
	 */

	if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
	    if (!pthread_main_np()) {
		/*
		 * Panic if main runloop is not on the main application thread.
		 */

		Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s",
		    "first [load] of TkAqua has to occur in the main thread!");
	    }
	    Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
				  TkMacOSXEventsCheckProc,
				  GetMainEventQueue());
	    TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
	    Tcl_SetServiceMode(TCL_SERVICE_ALL);
	    TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
	    TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);
	}
    }
}
................................................................................
TkMacOSXNotifyExitHandler(
    ClientData clientData)	/* Not used. */
{
    TSD_INIT();

    Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
			  TkMacOSXEventsCheckProc,
			  GetMainEventQueue());
    tsdPtr->initialized = 0;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXEventsSetupProc --
................................................................................

static void
TkMacOSXEventsSetupProc(
    ClientData clientData,
    int flags)
{
    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
    /* runloopMode will be nil if we are in the Tcl event loop. */
    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
	static const Tcl_Time zeroBlockTime = { 0, 0 };

	/* Call this with dequeue=NO -- just checking if the queue is empty. */
	NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
				       untilDate:[NSDate distantPast]
				       inMode:GetRunLoopMode(TkMacOSXGetModalSession())
				       dequeue:NO];
	if (currentEvent) {
	    if (currentEvent.type > 0) {
................................................................................
 */
static void
TkMacOSXEventsCheckProc(
    ClientData clientData,
    int flags)
{
    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
    /* runloopMode will be nil if we are in the Tcl event loop. */
    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
	NSEvent *currentEvent = nil;
	NSEvent *testEvent = nil;
	NSModalSession modalSession;








	do {
	    [NSApp _resetAutoreleasePool];
	    modalSession = TkMacOSXGetModalSession();
	    testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
					      untilDate:[NSDate distantPast]
						 inMode:GetRunLoopMode(modalSession)
						dequeue:NO];
	    /* We must not steal any events during LiveResize. */
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
	    if (testEvent && [[testEvent window] inLiveResize]) {
		break;
	    }
#else
	    if (testEvent && [[[testEvent window] contentView] inLiveResize]) {
		break;
	    }
#endif
	    currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
					      untilDate:[NSDate distantPast]
						 inMode:GetRunLoopMode(modalSession)
						dequeue:YES];
	    if (currentEvent) {
		/* Generate Xevents. */
		int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
................................................................................
		    }
		}
		[currentEvent release];
	    } else {
		break;
	    }
	} while (1);


    }
}

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






>

<







 







|









|







 







|







 







|


>







 







|




<
>
>
>
>
>
>
>

<

|




|



|



|







 







>
>












11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
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
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXConstants.h"
#include <tclInt.h>

#import <objc/objc-auto.h>

/* This is not used for anything at the moment. */
typedef struct ThreadSpecificData {
    int initialized;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
................................................................................
	tsdPtr->initialized = 1;

	/*
	 * Install TkAqua event source in main event loop thread.
	 */

	if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
	    if (![NSThread isMainThread]) {
		/*
		 * Panic if main runloop is not on the main application thread.
		 */

		Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s",
		    "first [load] of TkAqua has to occur in the main thread!");
	    }
	    Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
				  TkMacOSXEventsCheckProc,
				  NULL);
	    TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
	    Tcl_SetServiceMode(TCL_SERVICE_ALL);
	    TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
	    TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);
	}
    }
}
................................................................................
TkMacOSXNotifyExitHandler(
    ClientData clientData)	/* Not used. */
{
    TSD_INIT();

    Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
			  TkMacOSXEventsCheckProc,
			  NULL);
    tsdPtr->initialized = 0;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXEventsSetupProc --
................................................................................

static void
TkMacOSXEventsSetupProc(
    ClientData clientData,
    int flags)
{
    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
    /* runloopMode will be nil if we are in a Tcl event loop. */
    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
	static const Tcl_Time zeroBlockTime = { 0, 0 };
	[NSApp _resetAutoreleasePool];
	/* Call this with dequeue=NO -- just checking if the queue is empty. */
	NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
				       untilDate:[NSDate distantPast]
				       inMode:GetRunLoopMode(TkMacOSXGetModalSession())
				       dequeue:NO];
	if (currentEvent) {
	    if (currentEvent.type > 0) {
................................................................................
 */
static void
TkMacOSXEventsCheckProc(
    ClientData clientData,
    int flags)
{
    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
    /* runloopMode will be nil if we are in a Tcl event loop. */
    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
	NSEvent *currentEvent = nil;
	NSEvent *testEvent = nil;
	NSModalSession modalSession;

	/* It is possible for the SetupProc to be called before this function
	 * returns.  This happens, for example, when we process an event which
	 * opens a modal window.  To prevent premature release of our
	 * application-wide autorelease pool by a nested call to the SetupProc,
	 * we must lock it here.
	 */
	[NSApp _lockAutoreleasePool];
	do {

	    modalSession = TkMacOSXGetModalSession();
	    	    testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
					      untilDate:[NSDate distantPast]
						 inMode:GetRunLoopMode(modalSession)
						dequeue:NO];
	    /* We must not steal any events during LiveResize. */
        #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
	    if (testEvent && [[testEvent window] inLiveResize]) {
		break;
	    }
        #else
	    if (testEvent && [[[testEvent window] contentView] inLiveResize]) {
		break;
	    }
        #endif
	    currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
					      untilDate:[NSDate distantPast]
						 inMode:GetRunLoopMode(modalSession)
						dequeue:YES];
	    if (currentEvent) {
		/* Generate Xevents. */
		int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
................................................................................
		    }
		}
		[currentEvent release];
	    } else {
		break;
	    }
	} while (1);
	/* Now we can unlock the pool. */
	[NSApp _unlockAutoreleasePool];
    }
}

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

Changes to macosx/tkMacOSXPrivate.h.

205
206
207
208
209
210
211
212
213





214
215
216
217
218
219
220
...
224
225
226
227
228
229
230

231
232
233
234
235
236
237
...
274
275
276
277
278
279
280
281
282
283
284

285
286
287
288


289
290
291
292
293
294
295
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
			    int antiAlias);
MODULE_SCOPE int	TkMacOSXGenerateFocusEvent(TkWindow *winPtr,
			    int activeFlag);
MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
MODULE_SCOPE int	TkMacOSXIsWindowZoomed(TkWindow *winPtr);
MODULE_SCOPE int	TkGenerateButtonEventForXPointer(Window window);
MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
MODULE_SCOPE NSBitmapImageRep* BitmapRepFromDrawableRect(Drawable drawable,
			    int x, int y, unsigned int width, unsigned int height);





MODULE_SCOPE int	TkMacOSXSetupDrawingContext(Drawable d, GC gc,
			    int useCG, TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void	TkMacOSXRestoreDrawingContext(
			    TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void	TkMacOSXSetColorInContext(GC gc, unsigned long pixel,
			    CGContextRef context);
MODULE_SCOPE int	TkMacOSXMakeFullscreen(TkWindow *winPtr,
................................................................................
			    int active);
MODULE_SCOPE NSWindow*	TkMacOSXDrawableWindow(Drawable drawable);
MODULE_SCOPE NSView*	TkMacOSXDrawableView(MacDrawable *macWin);
MODULE_SCOPE void	TkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds);
MODULE_SCOPE HIShapeRef	TkMacOSXGetClipRgn(Drawable drawable);
MODULE_SCOPE void	TkMacOSXInvalidateViewRegion(NSView *view,
			    HIShapeRef rgn);

MODULE_SCOPE CGImageRef	TkMacOSXCreateCGImageWithDrawable(Drawable drawable);
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageWithTkImage(Display *display,
			    Tk_Image image, int width, int height);
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageWithBitmap(Display *display,
			    Pixmap bitmap, GC gc, int width, int height);
MODULE_SCOPE CGColorRef	TkMacOSXCreateCGColor(GC gc, unsigned long pixel);
MODULE_SCOPE NSColor*	TkMacOSXGetNSColor(GC gc, unsigned long pixel);
................................................................................
    TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
    NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
    NSArray *_defaultHelpMenuItems;
    NSWindow *_windowWithMouse;
    NSAutoreleasePool *_mainPool;
#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    BOOL _poolProtected;
#endif
}
@property BOOL poolProtected;

@end
@interface TKApplication(TKInit)
- (NSString *)tkFrameworkImagePath:(NSString*)image;
- (void)_resetAutoreleasePool;


@end
@interface TKApplication(TKEvent)
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
@end
@interface TKApplication(TKMouseEvent)
- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent;
@end
................................................................................
@interface TKContentView(TKKeyEvent)
- (void) deleteWorkingText;
@end

@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly;
- (void) viewDidEndLiveResize;
- (void) tkToolbarButton: (id) sender;
- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
- (BOOL) acceptsFirstResponder;
- (void) keyDown: (NSEvent *) theEvent;
@end






|

>
>
>
>
>







 







>







 







|


|
>




>
>







 







<







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
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
...
346
347
348
349
350
351
352

353
354
355
356
357
358
359
			    int antiAlias);
MODULE_SCOPE int	TkMacOSXGenerateFocusEvent(TkWindow *winPtr,
			    int activeFlag);
MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
MODULE_SCOPE int	TkMacOSXIsWindowZoomed(TkWindow *winPtr);
MODULE_SCOPE int	TkGenerateButtonEventForXPointer(Window window);
MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable,
			    int x, int y, unsigned int width, unsigned int height);
MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image);
MODULE_SCOPE void       TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context,
			    CGImageRef image, unsigned long imageForeground,
			    unsigned long imageBackground, CGRect imageBounds,
			    CGRect srcBounds, CGRect dstBounds);
MODULE_SCOPE int	TkMacOSXSetupDrawingContext(Drawable d, GC gc,
			    int useCG, TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void	TkMacOSXRestoreDrawingContext(
			    TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void	TkMacOSXSetColorInContext(GC gc, unsigned long pixel,
			    CGContextRef context);
MODULE_SCOPE int	TkMacOSXMakeFullscreen(TkWindow *winPtr,
................................................................................
			    int active);
MODULE_SCOPE NSWindow*	TkMacOSXDrawableWindow(Drawable drawable);
MODULE_SCOPE NSView*	TkMacOSXDrawableView(MacDrawable *macWin);
MODULE_SCOPE void	TkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds);
MODULE_SCOPE HIShapeRef	TkMacOSXGetClipRgn(Drawable drawable);
MODULE_SCOPE void	TkMacOSXInvalidateViewRegion(NSView *view,
			    HIShapeRef rgn);
MODULE_SCOPE CGContextRef TkMacOSXGetCGContextForDrawable(Drawable drawable);
MODULE_SCOPE CGImageRef	TkMacOSXCreateCGImageWithDrawable(Drawable drawable);
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageWithTkImage(Display *display,
			    Tk_Image image, int width, int height);
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageWithBitmap(Display *display,
			    Pixmap bitmap, GC gc, int width, int height);
MODULE_SCOPE CGColorRef	TkMacOSXCreateCGColor(GC gc, unsigned long pixel);
MODULE_SCOPE NSColor*	TkMacOSXGetNSColor(GC gc, unsigned long pixel);
................................................................................
    TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
    NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
    NSArray *_defaultHelpMenuItems;
    NSWindow *_windowWithMouse;
    NSAutoreleasePool *_mainPool;
#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    int _poolLock;
#endif
}
@property BOOL poolLock;

@end
@interface TKApplication(TKInit)
- (NSString *)tkFrameworkImagePath:(NSString*)image;
- (void)_resetAutoreleasePool;
- (void)_lockAutoreleasePool;
- (void)_unlockAutoreleasePool;
@end
@interface TKApplication(TKEvent)
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
@end
@interface TKApplication(TKMouseEvent)
- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent;
@end
................................................................................
@interface TKContentView(TKKeyEvent)
- (void) deleteWorkingText;
@end

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

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

Changes to macosx/tkMacOSXScale.c.

167
168
169
170
171
172
173

174


175
176
177
178
179
180
181
    /*
     * Invoke the scale's command if needed.
     */

    Tcl_Preserve((ClientData) scalePtr);
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
	Tcl_Preserve((ClientData) interp);

	sprintf(string, scalePtr->format, scalePtr->value);


	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {






>
|
>
>







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    /*
     * Invoke the scale's command if needed.
     */

    Tcl_Preserve((ClientData) scalePtr);
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
	Tcl_Preserve((ClientData) interp);
        if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
                scalePtr->value) < 0) {
            string[TCL_DOUBLE_SPACE - 1] = '\0';
        }
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {

Changes to macosx/tkMacOSXSubwindows.c.

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
...
274
275
276
277
278
279
280
281

282



283
284
285

286

287
288
289
290
291
292
293
...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
void
XUnmapWindow(
    Display *display,		/* Display. */
    Window window)		/* Window. */
{
    MacDrawable *macWin = (MacDrawable *) window;


    XEvent event;

    display->request++;
    macWin->winPtr->flags &= ~TK_MAPPED;
    if (Tk_IsTopLevel(macWin->winPtr)) {
	if (!Tk_IsEmbedded(macWin->winPtr) &&
		macWin->winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
	    NSWindow *win = TkMacOSXDrawableWindow(window);

	    if ([win isVisible]) {
		[[win parentWindow] removeChildWindow:win];
		[win orderOut:NSApp];
	    }
	}
	TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr);

	/*
	 * We only need to send the UnmapNotify event for toplevel windows.
	 */

	event.xany.serial = LastKnownRequestProcessed(display);
	event.xany.send_event = False;
................................................................................
	event.xunmap.type = UnmapNotify;
	event.xunmap.window = window;
	event.xunmap.event = window;
	event.xunmap.from_configure = false;
	Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
    } else {
	/*
	 * Generate damage for that area of the window.

	 */




	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
	TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);

    }

}
 
/*
 *----------------------------------------------------------------------
 *
 * XResizeWindow --
 *
................................................................................
	     * the stacking order. For an embedded toplevel, just clip to the
	     * container's visible clip region. Remember, we only allow one
	     * contained window in a frame, and don't support any other widgets
	     * in the frame either. This is not currently enforced, however.
	     */

	    if (!Tk_IsTopLevel(winPtr)) {
		TkMacOSXUpdateClipRgn(winPtr->parentPtr);
		if (winPtr->parentPtr) {
		    ChkErr(HIShapeIntersect,
			    winPtr->parentPtr->privatePtr->aboveVisRgn,
			    rgn, rgn);
		}
		win2Ptr = winPtr;
		while ((win2Ptr = win2Ptr->nextPtr)) {
		    if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {






>
>



<
|
|
|







|







 







|
>

>
>
>
|
<
|
>

>







 







|
|







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
...
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
...
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
void
XUnmapWindow(
    Display *display,		/* Display. */
    Window window)		/* Window. */
{
    MacDrawable *macWin = (MacDrawable *) window;
    TkWindow *winPtr = macWin->winPtr;
    TkWindow *parentPtr = winPtr->parentPtr;
    XEvent event;

    display->request++;

    if (Tk_IsTopLevel(winPtr)) {
	if (!Tk_IsEmbedded(winPtr) &&
		winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
	    NSWindow *win = TkMacOSXDrawableWindow(window);

	    if ([win isVisible]) {
		[[win parentWindow] removeChildWindow:win];
		[win orderOut:NSApp];
	    }
	}
	TkMacOSXInvalClipRgns((Tk_Window) winPtr);

	/*
	 * We only need to send the UnmapNotify event for toplevel windows.
	 */

	event.xany.serial = LastKnownRequestProcessed(display);
	event.xany.send_event = False;
................................................................................
	event.xunmap.type = UnmapNotify;
	event.xunmap.window = window;
	event.xunmap.event = window;
	event.xunmap.from_configure = false;
	Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
    } else {
	/*
	 * Rebuild the visRgn clip region for the parent so it will be allowed
	 * to draw in the space from which this subwindow was removed.
	 */
	if (parentPtr && parentPtr->privatePtr->visRgn) {
	    TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr),
					 parentPtr->privatePtr->visRgn);
	}

	TkMacOSXInvalClipRgns((Tk_Window) parentPtr);
	TkMacOSXUpdateClipRgn(parentPtr);
    }
    winPtr->flags &= ~TK_MAPPED;
}
 
/*
 *----------------------------------------------------------------------
 *
 * XResizeWindow --
 *
................................................................................
	     * the stacking order. For an embedded toplevel, just clip to the
	     * container's visible clip region. Remember, we only allow one
	     * contained window in a frame, and don't support any other widgets
	     * in the frame either. This is not currently enforced, however.
	     */

	    if (!Tk_IsTopLevel(winPtr)) {
		if (winPtr->parentPtr) {
		    TkMacOSXUpdateClipRgn(winPtr->parentPtr);
		    ChkErr(HIShapeIntersect,
			    winPtr->parentPtr->privatePtr->aboveVisRgn,
			    rgn, rgn);
		}
		win2Ptr = winPtr;
		while ((win2Ptr = win2Ptr->nextPtr)) {
		    if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {

Changes to macosx/tkMacOSXWindowEvent.c.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
...
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"


/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_EVENTS
#define TK_MAC_DEBUG_DRAWING
#endif
*/
................................................................................
    CFRelease(boundsRgn);

    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    event.xany.send_event = false;
    event.xany.window = Tk_WindowId(winPtr);
    event.xany.display = Tk_Display(winPtr);
    event.type = Expose;
    event.xexpose.x = damageBounds.origin.x;
    event.xexpose.y = damageBounds.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

    /*
................................................................................
	ClientData oldArg;
    	Tk_RestrictProc *oldProc;

	/* This can be called from outside the Tk event loop.
	 * Since it calls Tcl_DoOneEvent, we need to make sure we
	 * don't clobber the AutoreleasePool set up by the caller.
	 */
	[NSApp setPoolProtected:YES];

	/*
	 * Try to prevent flickers and flashes.
	 */
	[w disableFlushWindow];
	NSDisableScreenUpdates();

................................................................................
	HIRect bounds = NSRectToCGRect([self bounds]);
	HIShapeRef shape = HIShapeCreateWithRect(&bounds);
	[self generateExposeEvents: shape];
	while (Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT)) {}
	[w enableFlushWindow];
	[w flushWindowIfNeeded];
	NSEnableScreenUpdates();
	[NSApp setPoolProtected:NO];
    }
}

/*
 * As insurance against bugs that might cause layout glitches during a live
 * resize, we redraw the window one more time at the end of the resize
 * operation.
................................................................................
/* Core method of this class: generates expose events for redrawing.  If the
 * Tcl_ServiceMode is set to TCL_SERVICE_ALL then the expose events will be
 * immediately removed from the Tcl event loop and processed.  Typically, they
 * should be queued, however.
 */
- (void) generateExposeEvents: (HIShapeRef) shape
{
    [self generateExposeEvents:shape childrenOnly:0];
}

- (void) generateExposeEvents: (HIShapeRef) shape
		 childrenOnly: (int) childrenOnly
{
    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    unsigned long serial;
    CGRect updateBounds;
    int updatesNeeded;


    if (!winPtr) {
		return;
    }

    /* Generate Tk Expose events. */
    HIShapeGetBounds(shape, &updateBounds);






>







 







|
|



|







 







|







 







|







 







<
<
<
<
<
<
<



>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
...
911
912
913
914
915
916
917







918
919
920
921
922
923
924
925
926
927
928
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_EVENTS
#define TK_MAC_DEBUG_DRAWING
#endif
*/
................................................................................
    CFRelease(boundsRgn);

    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    event.xany.send_event = false;
    event.xany.window = Tk_WindowId(winPtr);
    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
    NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
	event.xexpose.y, event.xexpose.width, event.xexpose.height);
#endif

    /*
................................................................................
	ClientData oldArg;
    	Tk_RestrictProc *oldProc;

	/* This can be called from outside the Tk event loop.
	 * Since it calls Tcl_DoOneEvent, we need to make sure we
	 * don't clobber the AutoreleasePool set up by the caller.
	 */
	[NSApp _lockAutoreleasePool];

	/*
	 * Try to prevent flickers and flashes.
	 */
	[w disableFlushWindow];
	NSDisableScreenUpdates();

................................................................................
	HIRect bounds = NSRectToCGRect([self bounds]);
	HIShapeRef shape = HIShapeCreateWithRect(&bounds);
	[self generateExposeEvents: shape];
	while (Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT)) {}
	[w enableFlushWindow];
	[w flushWindowIfNeeded];
	NSEnableScreenUpdates();
	[NSApp _unlockAutoreleasePool];
    }
}

/*
 * As insurance against bugs that might cause layout glitches during a live
 * resize, we redraw the window one more time at the end of the resize
 * operation.
................................................................................
/* Core method of this class: generates expose events for redrawing.  If the
 * Tcl_ServiceMode is set to TCL_SERVICE_ALL then the expose events will be
 * immediately removed from the Tcl event loop and processed.  Typically, they
 * should be queued, however.
 */
- (void) generateExposeEvents: (HIShapeRef) shape
{







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

    if (!winPtr) {
		return;
    }

    /* Generate Tk Expose events. */
    HIShapeGetBounds(shape, &updateBounds);

Changes to macosx/tkMacOSXWm.c.

16
17
18
19
20
21
22

23
24
25
26
27
28
29
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
...
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
...
378
379
380
381
382
383
384

385














386
387
388
389
390
391
392
....
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324

2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344


2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358

2359
2360
2361
2362
2363
2364
2365
2366
2367



2368
2369



2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
....
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
....
5107
5108
5109
5110
5111
5112
5113

5114
5115
5116
5117
5118
5119
5120
....
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159

5160
5161
5162
5163
5164
5165
5166
5167
5168
....
5602
5603
5604
5605
5606
5607
5608

5609
5610
5611
5612
5613
5614
5615
....
6497
6498
6499
6500
6501
6502
6503

6504
6505
6506
6507
6508
6509
6510
....
6528
6529
6530
6531
6532
6533
6534

6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545

6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558

6559
6560
6561
6562
6563
6564
6565
 */

#include "tkMacOSXPrivate.h"
#include "tkScrollbar.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"


#define DEBUG_ZOMBIES 0

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_WINDOWS
#endif
................................................................................
 * Hash table for Mac Window -> TkWindow mapping.
 */

static Tcl_HashTable windowTable;
static int windowHashInit = false;



#pragma mark NSWindow(TKWm)

/*
 * Conversion of coordinates between window and screen.
 */

@implementation NSWindow(TKWm)
................................................................................
{
    return [self convertBaseToScreen:point];
}
- (NSPoint) convertPointFromScreen: (NSPoint)point
{
    return [self convertScreenToBase:point];
}
@end
#else
- (NSPoint) convertPointToScreen: (NSPoint) point
{
    NSRect pointrect;
    pointrect.origin = point;
    pointrect.size.width = 0;
    pointrect.size.height = 0;
................................................................................
{
    NSRect pointrect;
    pointrect.origin = point;
    pointrect.size.width = 0;
    pointrect.size.height = 0;
    return [self convertRectFromScreen:pointrect].origin;
}
@end

#endif

#pragma mark -


/*
 * Forward declarations for procedures defined in this file:
 */
................................................................................

@interface NSDrawerWindow : NSWindow
{
    id _i1, _i2;
}
@end


@implementation TKWindow














@end

@implementation TKWindow(TKWm)

- (BOOL) canBecomeKeyWindow
{
    TkWindow *winPtr = TkMacOSXGetTkWindow(self);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * WmIconphotoCmd --
 *
 *	This procedure is invoked to process the "wm iconphoto" Tcl command.
 *	See the user documentation for details on what it does. Not yet
 *	implemented for OS X.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.

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

static int
WmIconphotoCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_PhotoHandle photo;
    int i, width, height, isDefault = 0;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?-default? image1 ?image2 ...?");
	return TCL_ERROR;
    }


    if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
	isDefault = 1;
	if (objc == 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "window ?-default? image1 ?image2 ...?");
	    return TCL_ERROR;
	}
    }

    /*
     * Iterate over all images to retrieve their sizes, in order to allocate a
     * buffer large enough to hold all images.
     */


    for (i = 3 + isDefault; i < objc; i++) {
	photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
	if (photo == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't use \"%s\" as iconphoto: not a photo image",
		    Tcl_GetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "PHOTO", NULL);
	    return TCL_ERROR;
	}



	Tk_PhotoGetSize(photo, &width, &height);
    }




    /*
     * TODO: This requires implementation for OS X, but we silently return for
     * now.
     */

    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * WmIconpositionCmd --
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXIsWindowZoomed --
 *
 *	Ask Carbon if the given window is in the zoomed out state. Because
 *	dragging & growing a window can change the Carbon zoom state, we
 *	cannot rely on wmInfoPtr->hints.initial_state for this information.
 *
 * Results:
 *	True if window is zoomed out, false otherwise.
 *
 * Side effects:
 *	None.
................................................................................

MODULE_SCOPE int
TkMacOSXIsWindowZoomed(
    TkWindow *winPtr)
{
    return [TkMacOSXDrawableWindow(winPtr->window) isZoomed];
}

 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXZoomToplevel --
 *
 *	The function is invoked when the user clicks in the zoom region of a
................................................................................
	return false;
    }

    /*
     * Do nothing if already in desired zoom state.
     */

    if (![window isZoomed] == (zoomPart == inZoomIn)) {
	return false;
    }
    [window zoom:NSApp];

    wmPtr->hints.initial_state =
	    (zoomPart == inZoomIn ? NormalState : ZoomState);
    return true;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkUnsupported1Cmd --
................................................................................
    NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
	    styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
    if (!window) {
    	Tcl_Panic("couldn't allocate new Mac window");
    }
    TKContentView *contentView = [[TKContentView alloc]
				     initWithFrame:NSZeroRect];

    [window setContentView:contentView];
    [contentView release];
    [window setDelegate:NSApp];
    [window setAcceptsMouseMovedEvents:YES];
    [window setReleasedWhenClosed:NO];
    [window setAutodisplay:NO];
    if (styleMask & NSUtilityWindowMask) {
................................................................................
			" width/height is too small", winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "FULLSCREEN",
			"CONSTRAINT_FAILURE", NULL);
	    }
	    result = TCL_ERROR;
	    wmPtr->flags &= ~WM_FULLSCREEN;
	} else {

	    NSRect bounds = [window contentRectForFrameRect:[window frame]];
	    NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight);

	    if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) {
		wmPtr->configX = wmPtr->x;
		wmPtr->configY = wmPtr->y;
		wmPtr->configAttributes = wmPtr->attributes;
................................................................................
	 */

	prevMask = [window styleMask];
	prevPres = [NSApp presentationOptions];
	[window setStyleMask: NSBorderlessWindowMask];
	[NSApp setPresentationOptions: NSApplicationPresentationAutoHideDock
	                          | NSApplicationPresentationAutoHideMenuBar];

#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
    } else {
	wmPtr->flags &= ~WM_FULLSCREEN;

#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
	[NSApp setPresentationOptions: prevPres];
	[window setStyleMask: prevMask];
#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
    }

    if (wasFullscreen && !(wmPtr->flags & WM_FULLSCREEN)) {

	UInt64 oldAttributes = wmPtr->attributes;
	NSRect bounds = NSMakeRect(wmPtr->configX, tkMacOSXZeroScreenHeight -
		(wmPtr->configY + wmPtr->yInParent + wmPtr->configHeight),
		wmPtr->xInParent + wmPtr->configWidth,
		wmPtr->yInParent + wmPtr->configHeight);

	wmPtr->attributes |= wmPtr->configAttributes &
		kWindowResizableAttribute;
	ApplyWindowAttributeFlagChanges(winPtr, window, oldAttributes,
		wmPtr->flags, 1, 0);
	wmPtr->flags |= WM_SYNC_PENDING;
	[window setFrame:[window frameRectForContentRect:bounds] display:YES];
	wmPtr->flags &= ~WM_SYNC_PENDING;

    }
    return result;
}
 
/*
 *----------------------------------------------------------------------
 *






>







 







<







 







<







 







|
>
|







 







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







 







|
<






>



<








|




|


>
>




|




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







 







|
|







 







>







 







|


|
>
|
|







 







>







 







>







 







>











>













>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
194
195
196
197
198
199
200

201
202
203
204
205
206
207
...
210
211
212
213
214
215
216

217
218
219
220
221
222
223
...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
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
....
2325
2326
2327
2328
2329
2330
2331
2332

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342

2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369


2370
2371

2372
2373
2374
2375


2376


2377
2378
2379
2380
2381
2382
2383
2384
2385
2386


2387

2388
2389
2390
2391
2392
2393
2394
2395
....
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
....
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
....
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
....
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
....
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
....
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
 */

#include "tkMacOSXPrivate.h"
#include "tkScrollbar.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

#define DEBUG_ZOMBIES 0

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_WINDOWS
#endif
................................................................................
 * Hash table for Mac Window -> TkWindow mapping.
 */

static Tcl_HashTable windowTable;
static int windowHashInit = false;



#pragma mark NSWindow(TKWm)

/*
 * Conversion of coordinates between window and screen.
 */

@implementation NSWindow(TKWm)
................................................................................
{
    return [self convertBaseToScreen:point];
}
- (NSPoint) convertPointFromScreen: (NSPoint)point
{
    return [self convertScreenToBase:point];
}

#else
- (NSPoint) convertPointToScreen: (NSPoint) point
{
    NSRect pointrect;
    pointrect.origin = point;
    pointrect.size.width = 0;
    pointrect.size.height = 0;
................................................................................
{
    NSRect pointrect;
    pointrect.origin = point;
    pointrect.size.width = 0;
    pointrect.size.height = 0;
    return [self convertRectFromScreen:pointrect].origin;
}
#endif

@end

#pragma mark -


/*
 * Forward declarations for procedures defined in this file:
 */
................................................................................

@interface NSDrawerWindow : NSWindow
{
    id _i1, _i2;
}
@end


@implementation TKWindow: NSWindow
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_12
/*
 * Override automatic fullscreen button on >10.12 because system fullscreen API
 * confuses Tk window geometry.
 */
- (void)toggleFullScreen:(id)sender
{
    if ([self isZoomed]) {
	TkMacOSXZoomToplevel(self, inZoomIn);
    } else {
	TkMacOSXZoomToplevel(self, inZoomOut);
    }
}
#endif
@end

@implementation TKWindow(TKWm)

- (BOOL) canBecomeKeyWindow
{
    TkWindow *winPtr = TkMacOSXGetTkWindow(self);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * WmIconphotoCmd --
 *
 *	This procedure is invoked to process the "wm iconphoto" Tcl command.
 *	See the user documentation for details on what it does. 

 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *
 *----------------------------------------------------------------------
 */

static int
WmIconphotoCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
     Tk_Image tk_icon;
    int i, width, height, isDefault = 0;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2, objv,
			 "window ?-default? image1 ?image2 ...?");
	return TCL_ERROR;
    }

    /*Parse args.*/
    if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
	isDefault = 1;
	if (objc == 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
			     "window ?-default? image1 ?image2 ...?");
	    return TCL_ERROR;
	}
    }



    /*Get icon name. We only use the first icon name because macOS does not
      support multiple images in Tk photos.*/

    char *icon; 
    if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
	icon = Tcl_GetString(objv[4]);
    }	else {


	icon = Tcl_GetString(objv[3]);


    }

    /*Get image and convert to NSImage that can be displayed as icon.*/
    tk_icon = Tk_GetImage(interp, winPtr, icon, NULL, NULL);
    Tk_SizeOfImage(tk_icon, &width, &height);
	
    NSImage *newIcon;
    newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, width, height);
    [NSApp setApplicationIconImage: newIcon];
	   


    Tk_FreeImage(tk_icon);

    
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * WmIconpositionCmd --
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXIsWindowZoomed --
 *
 *	Ask Cocoa if the given window is in the zoomed out state. Because
 *	dragging & growing a window can change the Cocoa zoom state, we
 *	cannot rely on wmInfoPtr->hints.initial_state for this information.
 *
 * Results:
 *	True if window is zoomed out, false otherwise.
 *
 * Side effects:
 *	None.
................................................................................

MODULE_SCOPE int
TkMacOSXIsWindowZoomed(
    TkWindow *winPtr)
{
    return [TkMacOSXDrawableWindow(winPtr->window) isZoomed];
}

 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXZoomToplevel --
 *
 *	The function is invoked when the user clicks in the zoom region of a
................................................................................
	return false;
    }

    /*
     * Do nothing if already in desired zoom state.
     */

    if ((![window isZoomed] == (zoomPart == inZoomIn))) {
	return false;
    }
      [window zoom:NSApp];

     wmPtr->hints.initial_state =
    	    (zoomPart == inZoomIn ? NormalState : ZoomState);
    return true;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkUnsupported1Cmd --
................................................................................
    NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
	    styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
    if (!window) {
    	Tcl_Panic("couldn't allocate new Mac window");
    }
    TKContentView *contentView = [[TKContentView alloc]
				     initWithFrame:NSZeroRect];
    [window setColorSpace:[NSColorSpace deviceRGBColorSpace]];
    [window setContentView:contentView];
    [contentView release];
    [window setDelegate:NSApp];
    [window setAcceptsMouseMovedEvents:YES];
    [window setReleasedWhenClosed:NO];
    [window setAutodisplay:NO];
    if (styleMask & NSUtilityWindowMask) {
................................................................................
			" width/height is too small", winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "FULLSCREEN",
			"CONSTRAINT_FAILURE", NULL);
	    }
	    result = TCL_ERROR;
	    wmPtr->flags &= ~WM_FULLSCREEN;
	} else {
	    Tk_UnmapWindow((Tk_Window) winPtr);
	    NSRect bounds = [window contentRectForFrameRect:[window frame]];
	    NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight);

	    if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) {
		wmPtr->configX = wmPtr->x;
		wmPtr->configY = wmPtr->y;
		wmPtr->configAttributes = wmPtr->attributes;
................................................................................
	 */

	prevMask = [window styleMask];
	prevPres = [NSApp presentationOptions];
	[window setStyleMask: NSBorderlessWindowMask];
	[NSApp setPresentationOptions: NSApplicationPresentationAutoHideDock
	                          | NSApplicationPresentationAutoHideMenuBar];
	Tk_MapWindow((Tk_Window) winPtr);
#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
    } else {
	wmPtr->flags &= ~WM_FULLSCREEN;

#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
	[NSApp setPresentationOptions: prevPres];
	[window setStyleMask: prevMask];
#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
    }

    if (wasFullscreen && !(wmPtr->flags & WM_FULLSCREEN)) {
	Tk_UnmapWindow((Tk_Window) winPtr);
	UInt64 oldAttributes = wmPtr->attributes;
	NSRect bounds = NSMakeRect(wmPtr->configX, tkMacOSXZeroScreenHeight -
		(wmPtr->configY + wmPtr->yInParent + wmPtr->configHeight),
		wmPtr->xInParent + wmPtr->configWidth,
		wmPtr->yInParent + wmPtr->configHeight);

	wmPtr->attributes |= wmPtr->configAttributes &
		kWindowResizableAttribute;
	ApplyWindowAttributeFlagChanges(winPtr, window, oldAttributes,
		wmPtr->flags, 1, 0);
	wmPtr->flags |= WM_SYNC_PENDING;
	[window setFrame:[window frameRectForContentRect:bounds] display:YES];
	wmPtr->flags &= ~WM_SYNC_PENDING;
       Tk_MapWindow((Tk_Window) winPtr);
    }
    return result;
}
 
/*
 *----------------------------------------------------------------------
 *

Changes to macosx/tkMacOSXXStubs.c.

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
...
758
759
760
761
762
763
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
795
796
797
798
799
800
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
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
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
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
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
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
....
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
 * Forward declarations of procedures used in this file.
 */

static XID		MacXIdAlloc(Display *display);
static int		DefaultErrorHandler(Display *display,
			    XErrorEvent *err_evt);

/*
 * Other declarations
 */

static int		DestroyImage(XImage *image);
static unsigned long	ImageGetPixel(XImage *image, int x, int y);
static int		ImagePutPixel(XImage *image, int x, int y,
			    unsigned long pixel);
 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXDisplayChanged --
 *
 *	Called to set up initial screen info or when an event indicated
................................................................................
	snprintf(vendor, sizeof(vendor), "Apple AppKit %g",
		NSAppKitVersionNumber);
    }
    display->vendor = vendor;
    {
	int major, minor, patch;

#if MAC_OS_X_VERSION_MIN_REQUIRED < 10100
	Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
	Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
	Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
#else
	NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
	major = systemVersion.majorVersion;
	minor = systemVersion.minorVersion;
................................................................................
    Display * display,
    Atom atom)
{
    display->request++;
    return NULL;
}
 
int
_XInitImageFuncPtrs(
    XImage *image)
{
    return 0;
}

XErrorHandler
XSetErrorHandler(
    XErrorHandler handler)
{
    return DefaultErrorHandler;
}

................................................................................
	    ProtocolVersion(Tk_Display(tkwin)),
	    ProtocolRevision(Tk_Display(tkwin)));
    snprintf(buffer2, sizeof(buffer2), " Mac OS X %x",
	    VendorRelease(Tk_Display(tkwin)));
    Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)),
	    buffer2, NULL);
}
 
#pragma mark XImage handling

/*
 *----------------------------------------------------------------------
 *
 * XCreateImage --
 *
 *	Allocates storage for a new XImage.
 *
 * Results:
 *	Returns a newly allocated XImage.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

XImage *
XCreateImage(
    Display* display,
    Visual* visual,
    unsigned int depth,
    int format,
    int offset,
    char* data,
    unsigned int width,
    unsigned int height,
    int bitmap_pad,
    int bytes_per_line)
{
    XImage *ximage;
    display->request++;
    ximage = ckalloc(sizeof(XImage));

    ximage->height = height;
    ximage->width = width;
    ximage->depth = depth;
    ximage->xoffset = offset;
    ximage->format = format;
    ximage->data = data;
    ximage->obdata = NULL;
    /* The default pixelpower is 0.  This must be explicitly set to 1 in the
     * case of an XImage extracted from a Retina display.
     */
    ximage->pixelpower = 0;

    if (format == ZPixmap) {
	ximage->bits_per_pixel = 32;
	ximage->bitmap_unit = 32;
    } else {
	ximage->bits_per_pixel = 1;
	ximage->bitmap_unit = 8;
    }
    if (bitmap_pad) {
	ximage->bitmap_pad = bitmap_pad;
    } else {
	/* Use 16 byte alignment for best Quartz perfomance */
	ximage->bitmap_pad = 128;
    }
    if (bytes_per_line) {
	ximage->bytes_per_line = bytes_per_line;
    } else {
	ximage->bytes_per_line = ((width * ximage->bits_per_pixel +
		(ximage->bitmap_pad - 1)) >> 3) &
		~((ximage->bitmap_pad >> 3) - 1);
    }
#ifdef WORDS_BIGENDIAN
    ximage->byte_order = MSBFirst;
    ximage->bitmap_bit_order = MSBFirst;
#else
    ximage->byte_order = LSBFirst;
    ximage->bitmap_bit_order = LSBFirst;
#endif
    ximage->red_mask = 0x00FF0000;
    ximage->green_mask = 0x0000FF00;
    ximage->blue_mask = 0x000000FF;
    ximage->f.create_image = NULL;
    ximage->f.destroy_image = DestroyImage;
    ximage->f.get_pixel = ImageGetPixel;
    ximage->f.put_pixel = ImagePutPixel;
    ximage->f.sub_image = NULL;
    ximage->f.add_pixel = NULL;

    return ximage;
}
 
/*
 *----------------------------------------------------------------------
 *
 * XGetImage --
 *
 *	This function copies data from a pixmap or window into an XImage.
 *
 * Results:
 *	Returns a newly allocated XImage containing the data from the given
 *	rectangle of the given drawable, or NULL if the XImage could not be
 *	constructed.  NOTE: If we are copying from a window on a Retina
 *	display, the dimensions of the XImage will be 2*width x 2*height.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

XImage *
XGetImage(
    Display *display,
    Drawable d,
    int x,
    int y,
    unsigned int width,
    unsigned int height,
    unsigned long plane_mask,
    int format)
{
    NSBitmapImageRep *bitmap_rep;
    NSUInteger         bitmap_fmt;
    XImage *       imagePtr = NULL;
    char *           bitmap = NULL;
    char *           image_data=NULL;
    int	        depth = 32;
    int	        offset = 0;
    int	        bitmap_pad = 0;
    int	        bytes_per_row = 4*width;
    int                size;
    MacDrawable *macDraw = (MacDrawable *) d; // Where is this variable used? May it be removed?
    int scalefactor = 1;
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
    NSWindow *win = TkMacOSXDrawableWindow(d);
    /* This code assumes that backing scale factors are integers.  Currently
     * Retina displays use a scale factor of 2.0 and normal displays use 1.0.
     * We do not support any other values here.
     */
    if (win && [win respondsToSelector:@selector(backingScaleFactor)]) {
	scalefactor = ([win backingScaleFactor] == 2.0) ? 2 : 1;
    }
#endif
    int scaled_height = height * scalefactor;
    int scaled_width = width * scalefactor;

    if (format == ZPixmap) {
	if (width == 0 || height == 0) {
	    /* This happens all the time.
	    TkMacOSXDbgMsg("XGetImage: empty image requested");
	    */
	    return NULL;
	}

	bitmap_rep =  BitmapRepFromDrawableRect(d, x, y, width, height);
	bitmap_fmt = [bitmap_rep bitmapFormat];

	if ( bitmap_rep == Nil                        ||
	     (bitmap_fmt != 0 && bitmap_fmt != 1)     ||
	     [bitmap_rep samplesPerPixel] != 4 ||
	     [bitmap_rep isPlanar] != 0               ) {
	    TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
	    return NULL;
	}

	NSSize image_size = NSMakeSize(width, height);
	NSImage* ns_image = [[NSImage alloc]initWithSize:image_size];
	[ns_image addRepresentation:bitmap_rep];

	/* Assume premultiplied nonplanar data with 4 bytes per pixel.*/
	if ( [bitmap_rep isPlanar ] == 0 &&
	     [bitmap_rep samplesPerPixel] == 4 ) {
	    bytes_per_row = [bitmap_rep bytesPerRow];
	    assert(bytes_per_row == 4 * scaled_width);
	    assert([bitmap_rep bytesPerPlane] == bytes_per_row * scaled_height);
	    size = bytes_per_row*scaled_height;
	    image_data = (char*)[bitmap_rep bitmapData];
	    if ( image_data ) {
		int row, n, m;
		bitmap = ckalloc(size);
		/*
		  Oddly enough, the bitmap has the top row at the beginning,
		  and the pixels are in BGRA or ABGR format.
		*/
		if (bitmap_fmt == 0) {
		    /* BGRA */
		    for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) {
			for (m=n; m<n+bytes_per_row; m+=4) {
			    *(bitmap+m)   = *(image_data+m+2);
			    *(bitmap+m+1) = *(image_data+m+1);
			    *(bitmap+m+2) = *(image_data+m);
			    *(bitmap+m+3) = *(image_data+m+3);
			}
		    }
		} else {
		    /* ABGR */
		    for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) {
			for (m=n; m<n+bytes_per_row; m+=4) {
			    *(bitmap+m)   = *(image_data+m+3);
			    *(bitmap+m+1) = *(image_data+m+2);
			    *(bitmap+m+2) = *(image_data+m+1);
			    *(bitmap+m+3) = *(image_data+m);
			}
		    }
		}
	    }
	}
	if (bitmap) {
	    imagePtr = XCreateImage(display, NULL, depth, format, offset,
				    (char*)bitmap, scaled_width, scaled_height,
				    bitmap_pad, bytes_per_row);
	    if (scalefactor == 2) {
	    	imagePtr->pixelpower = 1;
	     }
	    [ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/
	    [ns_image release];
	}
    } else {
	TkMacOSXDbgMsg("Could not extract image from drawable.");
    }
    return imagePtr;
}
 
/*
 *----------------------------------------------------------------------
 *
 * DestroyImage --
 *
 *	Destroys storage associated with an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Deallocates the image.
 *
 *----------------------------------------------------------------------
 */

static int
DestroyImage(
    XImage *image)
{
    if (image) {
	if (image->data) {
	    ckfree(image->data);
	}
	ckfree(image);
    }
    return 0;
}
 
/*
 *----------------------------------------------------------------------
 *
 * ImageGetPixel --
 *
 *	Get a single pixel from an image.
 *
 * Results:
 *	Returns the 32 bit pixel value.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned long
ImageGetPixel(
    XImage *image,
    int x,
    int y)
{
    unsigned char r = 0, g = 0, b = 0;

    if (image && image->data) {
	unsigned char *srcPtr = ((unsigned char*) image->data)
		+ (y * image->bytes_per_line)
		+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);

	switch (image->bits_per_pixel) {
	    case 32: {
		r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
		g = (*((unsigned int*) srcPtr) >>  8) & 0xff;
		b = (*((unsigned int*) srcPtr)      ) & 0xff;
		/*if (image->byte_order == LSBFirst) {
		    r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
		} else {
		    r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
		}*/
		break;
	    }
	    case 16:
		r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
		g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
		b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
		break;
	    case 8:
		r = (*srcPtr << 2) & 0xc0;
		g = (*srcPtr << 4) & 0xc0;
		b = (*srcPtr << 6) & 0xc0;
		r |= r >> 2 | r >> 4 | r >> 6;
		g |= g >> 2 | g >> 4 | g >> 6;
		b |= b >> 2 | b >> 4 | b >> 6;
		break;
	    case 4: {
		unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
		r = (c & 0x04) ? 0xff : 0;
		g = (c & 0x02) ? 0xff : 0;
		b = (c & 0x01) ? 0xff : 0;
		break;
		}
	    case 1:
		r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
		break;
	}
    }
    return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
}
 
/*
 *----------------------------------------------------------------------
 *
 * ImagePutPixel --
 *
 *	Set a single pixel in an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ImagePutPixel(
    XImage *image,
    int x,
    int y,
    unsigned long pixel)
{
    if (image && image->data) {
	unsigned char r = ((pixel & image->red_mask)   >> 16) & 0xff;
	unsigned char g = ((pixel & image->green_mask) >>  8) & 0xff;
	unsigned char b = ((pixel & image->blue_mask)       ) & 0xff;
	unsigned char *dstPtr = ((unsigned char*) image->data)
		+ (y * image->bytes_per_line)
		+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);

	switch (image->bits_per_pixel) {
	    case 32:
		*((unsigned int*) dstPtr) = (0xff << 24) | (r << 16) |
			(g << 8) | b;
		/*if (image->byte_order == LSBFirst) {
		    dstPtr[3] = 0xff; dstPtr[2] = r; dstPtr[1] = g; dstPtr[0] = b;
		} else {
		    dstPtr[0] = 0xff; dstPtr[1] = r; dstPtr[2] = g; dstPtr[3] = b;
		}*/
		break;
	    case 16:
		*((unsigned short*) dstPtr) = ((r & 0xf8) << 7) |
			((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
		break;
	    case 8:
		*dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) |
			((b & 0xc0) >> 6);
		break;
	    case 4: {
		unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) |
			((b & 0x80) >> 7);
		*dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) :
			((*dstPtr & 0x0f) | ((c << 4) & 0xf0));
		break;
		}
	    case 1:
		*dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) :
			(*dstPtr & ~(0x80 >> (x % 8)));
		break;
	}
    }
    return 0;
}
 
/*
 *----------------------------------------------------------------------
 *
 * XChangeWindowAttributes, XSetWindowBackground,
 * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap,
 * XSetWindowBorderWidth, XSetWindowColormap
................................................................................
 *----------------------------------------------------------------------
 */

void
Tk_ResetUserInactiveTime(
    Display *dpy)
{
    IOGPoint loc;
    kern_return_t kr;
    NXEvent nullEvent = {NX_NULLEVENT, {0, 0}, 0, -1, 0};
    enum { kNULLEventPostThrottle = 10 };
    static io_connect_t io_connection = MACH_PORT_NULL;

    if (io_connection == MACH_PORT_NULL) {
	io_service_t service = IOServiceGetMatchingService(






<
<
<
<
<
<
<
<







 







|







 







<
<
<
<
<
<
<







 







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







 







|







49
50
51
52
53
54
55








56
57
58
59
60
61
62
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
371
372
373
374
375
376
377







378
379
380
381
382
383
384
...
743
744
745
746
747
748
749






























































































































































































































































































































































































750
751
752
753
754
755
756
...
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
 * Forward declarations of procedures used in this file.
 */

static XID		MacXIdAlloc(Display *display);
static int		DefaultErrorHandler(Display *display,
			    XErrorEvent *err_evt);









 
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXDisplayChanged --
 *
 *	Called to set up initial screen info or when an event indicated
................................................................................
	snprintf(vendor, sizeof(vendor), "Apple AppKit %g",
		NSAppKitVersionNumber);
    }
    display->vendor = vendor;
    {
	int major, minor, patch;

#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
	Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
	Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
	Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
#else
	NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
	major = systemVersion.majorVersion;
	minor = systemVersion.minorVersion;
................................................................................
    Display * display,
    Atom atom)
{
    display->request++;
    return NULL;
}
 







XErrorHandler
XSetErrorHandler(
    XErrorHandler handler)
{
    return DefaultErrorHandler;
}

................................................................................
	    ProtocolVersion(Tk_Display(tkwin)),
	    ProtocolRevision(Tk_Display(tkwin)));
    snprintf(buffer2, sizeof(buffer2), " Mac OS X %x",
	    VendorRelease(Tk_Display(tkwin)));
    Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)),
	    buffer2, NULL);
}






























































































































































































































































































































































































 
/*
 *----------------------------------------------------------------------
 *
 * XChangeWindowAttributes, XSetWindowBackground,
 * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap,
 * XSetWindowBorderWidth, XSetWindowColormap
................................................................................
 *----------------------------------------------------------------------
 */

void
Tk_ResetUserInactiveTime(
    Display *dpy)
{
    IOGPoint loc = {0, 0};
    kern_return_t kr;
    NXEvent nullEvent = {NX_NULLEVENT, {0, 0}, 0, -1, 0};
    enum { kNULLEventPostThrottle = 10 };
    static io_connect_t io_connection = MACH_PORT_NULL;

    if (io_connection == MACH_PORT_NULL) {
	io_service_t service = IOServiceGetMatchingService(

Changes to tests/font.test.

1952
1953
1954
1955
1956
1957
1958










1959
1960
1961
1962
1963
1964
1965
test font-31.6 {Tk_IntersectTextLayout procedure: ignore spaces at eol} -body {
    csetup "000\n000      000000000"
    .t.c itemconfig text -width [expr $ax*10]
    set x [.t.c find overlapping [expr $ax*5] $ay [expr $ax*5] $ay]
    .t.c itemconfig text -width 0
    return $x
} -result {}










destroy .t.c


test font-32.1 {Tk_TextLayoutToPostscript: ensure buffer doesn't overflow} -setup {
	destroy .t.c
	canvas .t.c -closeenough 0 
	.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"






>
>
>
>
>
>
>
>
>
>







1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
test font-31.6 {Tk_IntersectTextLayout procedure: ignore spaces at eol} -body {
    csetup "000\n000      000000000"
    .t.c itemconfig text -width [expr $ax*10]
    set x [.t.c find overlapping [expr $ax*5] $ay [expr $ax*5] $ay]
    .t.c itemconfig text -width 0
    return $x
} -result {}
test font-31.7 {TkIntersectAngledTextLayout procedure: bug [514ff64dd0]} -body {
    csetup "This is line one\nand line two\nand line three here"
    .t.c itemconfigure text -angle 90
    # Coordinates of the rectangle to check can be hardcoded:
    # The goal of this test is to check whether the overlap detection algorithm
    # works when the rectangle is entirely included in a chunk of the text layout.
    # The text has been rotated 90 degrees around it's upper left corner,
    # so it's enough to check with a small rectangle with small negative y coords.
    .t.c find overlapping 5 -7 7 -5
} -result {1}
destroy .t.c


test font-32.1 {Tk_TextLayoutToPostscript: ensure buffer doesn't overflow} -setup {
	destroy .t.c
	canvas .t.c -closeenough 0 
	.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"

Changes to tests/imgPhoto.test.

815
816
817
818
819
820
821












822
823
824
825
826
827
828
} -body {
    file copy -force $teapotPhotoFile -teapotPhotoFile
    image create photo photo1
    photo1 read -teapotPhotoFile
} -cleanup {
    image delete photo1
    file delete ./-teapotPhotoFile












} -result {}

test imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} -constraints {
    hasTeapotPhoto
} -setup {
    destroy .c
    pack [canvas .c]






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







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
} -body {
    file copy -force $teapotPhotoFile -teapotPhotoFile
    image create photo photo1
    photo1 read -teapotPhotoFile
} -cleanup {
    image delete photo1
    file delete ./-teapotPhotoFile
} -result {}
test imgPhoto-4.76 {ImgPhotoCmd procedure: copy to same image} -constraints {
    hasTeapotPhoto 
} -setup {
    imageCleanup
    image create photo photo1 -file $teapotPhotoFile
} -body {
    # non-regression test for bug [5239fd749b] - shall just not crash
    photo1 copy photo1 -to 0 0 2000 1000
    photo1 copy photo1 -subsample 2 2 -shrink
} -cleanup {
    imageCleanup
} -result {}

test imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} -constraints {
    hasTeapotPhoto
} -setup {
    destroy .c
    pack [canvas .c]

Changes to tests/menu.test.

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
....
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
....
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
....
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
....
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778












1779
1780
1781
1782












1783
1784
1785
1786
1787
1788
1789
....
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
....
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
....
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
....
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
....
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
....
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
....
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
....
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
# We need to test all of the options with all of the different types of
# menu entries. The following code sets up .m1 with 6 items. It then
# runs through the 2.31 - 2.228 tests below
# index 0 is tearoff, 1 command, 2 cascade, 3 separator, 4 checkbutton, 
# 5 radiobutton
deleteWindows
menu .m1
.m1 add command -label "command"
menu .m2
.m2 add command -label "test"
.m1 add cascade -label "cascade" -menu .m2
.m1 add separator
.m1 add checkbutton -label "checkbutton" -variable check -onvalue on -offvalue off
.m1 add radiobutton -label "radiobutton" -variable radio

if {[testConstraint hasEarthPhoto]} {
................................................................................
} -body {
    menu .m1
    .m1 delete foo
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.24 {MenuWidgetCmd procedure, "delete" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 delete 0 "foo"
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.25 {MenuWidgetCmd procedure, "delete" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 delete 0
................................................................................
} -body {
    menu .m1
    .m1 index foo
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.41 {MenuWidgetCmd procedure, "index" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "3"
    .m1 add command -label "another label"
    .m1 add command -label "end"
    .m1 add command -label "3a"
    .m1 add command -label "final entry"
    list [.m1 index "test"] [.m1 index "3"] [.m1 index "3a"] [.m1 index "end"]
................................................................................
    .m1 type 1
} -cleanup {
	destroy .m1
} -result {cascade}
test menu-3.62 {MenuWidgetCmd procedure, "type" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 type 0
} -cleanup {
	destroy .m1
} -result {tearoff}
test menu-3.63 {MenuWidgetCmd procedure, "unpost" option} -setup {
	destroy .m1
} -body {
................................................................................
	destroy .m1
} -body {
    menu .m1
    .m1 yposition
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 yposition index"}
test menu-3.66 {MenuWidgetCmd procedure, "yposition" option} -setup {
	destroy .m1
} -body {
    menu .m1












    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {1}












test menu-3.67 {MenuWidgetCmd procedure, bad option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 foo
} -cleanup {
	destroy .m1
................................................................................
} -cleanup {
	destroy .m1
} -result {0 {} 0 on 0 {}}
test menu-4.6 {TkInvokeMenu: radiobutton} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add radiobutton -label "1" -variable foo -value one
    .m1 add radiobutton -label "2" -variable foo -value two
    .m1 add radiobutton -label "3" -variable foo -value three
    list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
} -cleanup {
	destroy .m1
} -result {0 {} 0 one 0 {}}
test menu-4.7 {TkInvokeMenu: radiobutton} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add radiobutton -label "1" -variable foo -value one
    .m1 add radiobutton -label "2" -variable foo -value two
    .m1 add radiobutton -label "3" -variable foo -value three
    list [catch {.m1 invoke 2} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
} -cleanup {
	destroy .m1
} -result {0 {} 0 two 0 {}}
................................................................................
    list [catch {.m1 invoke 1} msg] $msg 
} -cleanup {
	destroy .m1
} -result {0 {}}
test menu-4.12 {TkInvokeMenu} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test" -command ".m1 delete 1"
    list [catch {.m1 invoke 1} msg] $msg [catch {.m1 type "test"} msg2] $msg2
} -cleanup {
	destroy .m1
} -result {0 {} 1 {bad menu entry index "test"}}

test menu-5.1 {DestroyMenuInstance} -setup {
................................................................................
    menu .m1
    .m1 add command -label "test"
    list [.m1 delete 1] [destroy .m1]
} -result {{} {}}
test menu-8.6 {DestroyMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "one"
    .m1 add command -label "two"
    list [.m1 delete 1] [.m1 entrycget 1 -label] [destroy .m1]
} -result {{} two {}}
test menu-8.7 {DestroyMenuEntry} -setup {
	deleteWindows
} -body {
................................................................................
    deleteWindows
} -result {}


test menu-13.1 {TkGetMenuIndex} -setup {
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "active"
    .m1 add command -label "test2"
    .m1 add command -label "test3"
    .m1 activate 2
    .m1 entrycget active -label
} -cleanup {
    deleteWindows
................................................................................
} -cleanup {
    deleteWindows
} -result {}
#test menu-13.7 - Need to add @test here.
test menu-13.7 {TkGetMenuIndex} -setup {
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "active"
    .m1 add command -label "test2"
    .m1 add command -label "test3"
    .m1 entrycget 1 -label
} -cleanup {
    deleteWindows
} -result {active}
................................................................................
} -body {
    menu .m1
    .m1 insert -1 command -label "test"
} -returnCodes error -result {bad menu entry index "-1"}
test menu-16.4 {MenuAddOrInsert} -setup {
	deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 insert 0 command -label "test2"
    .m1 entrycget 1 -label
} -cleanup {
	deleteWindows
} -result {test2}
test menu-16.5 {MenuAddOrInsert} -setup {
................................................................................
    .m1 clone .foo
} -cleanup {
	deleteWindows
} -result {}
test menu-20.10 {CloneMenu - tearoff fields} -setup {
	deleteWindows
} -body {
    menu .m1
    list [.m1 clone .m2 normal] [.m2 cget -tearoff]
} -cleanup {
	deleteWindows
} -result {{} 1}
test menu-20.11 {CloneMenu} -setup {
	deleteWindows
} -body {
................................................................................
    .m1 configure -tearoff 0
    .m1 index @5,5
} -cleanup {
	deleteWindows
} -result {0}
test menu-22.3 {GetIndexFromCoords: mapped window, y only} -setup {
	deleteWindows
} -constraints {unix} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    .m1 index @5
} -cleanup {
	deleteWindows
} -result {0}
test menu-22.4 {GetIndexFromCoords: mapped window x,y} -setup {
	deleteWindows
} -constraints {unix} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    update
    set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]
    .m1 index @$x,5
} -cleanup {
	deleteWindows
} -result {0}
test menu-22.5 {GetIndexFromCoords: mapped wide window} -setup {
	deleteWindows
} -constraints {unix} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    wm geometry .m1 200x100
    update






|

|







 







|







 







|







 







|







 







|


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




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







 







|











|







 







|







 







|







 







|







 







|







 







|







 







|







 







|











|













|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
....
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
....
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
....
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
....
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
....
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
....
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
....
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
....
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
....
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
....
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
....
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
....
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
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
# We need to test all of the options with all of the different types of
# menu entries. The following code sets up .m1 with 6 items. It then
# runs through the 2.31 - 2.228 tests below
# index 0 is tearoff, 1 command, 2 cascade, 3 separator, 4 checkbutton, 
# 5 radiobutton
deleteWindows
menu .m1 -tearoff 1
.m1 add command -label "command"
menu .m2 -tearoff 1
.m2 add command -label "test"
.m1 add cascade -label "cascade" -menu .m2
.m1 add separator
.m1 add checkbutton -label "checkbutton" -variable check -onvalue on -offvalue off
.m1 add radiobutton -label "radiobutton" -variable radio

if {[testConstraint hasEarthPhoto]} {
................................................................................
} -body {
    menu .m1
    .m1 delete foo
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.24 {MenuWidgetCmd procedure, "delete" option} -setup {
	destroy .m1
} -body {
    menu .m1 -tearoff 1
    .m1 delete 0 "foo"
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.25 {MenuWidgetCmd procedure, "delete" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 delete 0
................................................................................
} -body {
    menu .m1
    .m1 index foo
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.41 {MenuWidgetCmd procedure, "index" option} -setup {
	destroy .m1
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "test"
    .m1 add command -label "3"
    .m1 add command -label "another label"
    .m1 add command -label "end"
    .m1 add command -label "3a"
    .m1 add command -label "final entry"
    list [.m1 index "test"] [.m1 index "3"] [.m1 index "3a"] [.m1 index "end"]
................................................................................
    .m1 type 1
} -cleanup {
	destroy .m1
} -result {cascade}
test menu-3.62 {MenuWidgetCmd procedure, "type" option} -setup {
	destroy .m1
} -body {
    menu .m1 -tearoff 1
    .m1 type 0
} -cleanup {
	destroy .m1
} -result {tearoff}
test menu-3.63 {MenuWidgetCmd procedure, "unpost" option} -setup {
	destroy .m1
} -body {
................................................................................
	destroy .m1
} -body {
    menu .m1
    .m1 yposition
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 yposition index"}
test menu-3.66a {MenuWidgetCmd procedure, "yposition" option, no tearoff} -setup {
	destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {0}
test menu-3.66b {MenuWidgetCmd procedure, "yposition" option, with tearoff} -constraints {
    notAqua
} -setup {
	destroy .m1
} -body {
    # on Win or Linux, tearoff menus are supported
    # see menu-3.66c for aqua
    menu .m1 -tearoff 1
    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {1}
test menu-3.66c {MenuWidgetCmd procedure, "yposition" option, with tearoff} -constraints {
    aqua
} -setup {
	destroy .m1
} -body {
    # on OS X, tearoff menus are not supported
    # see menu-3.66b for win or linux
    menu .m1 -tearoff 1
    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {0}
test menu-3.67 {MenuWidgetCmd procedure, bad option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 foo
} -cleanup {
	destroy .m1
................................................................................
} -cleanup {
	destroy .m1
} -result {0 {} 0 on 0 {}}
test menu-4.6 {TkInvokeMenu: radiobutton} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1 -tearoff 1
    .m1 add radiobutton -label "1" -variable foo -value one
    .m1 add radiobutton -label "2" -variable foo -value two
    .m1 add radiobutton -label "3" -variable foo -value three
    list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
} -cleanup {
	destroy .m1
} -result {0 {} 0 one 0 {}}
test menu-4.7 {TkInvokeMenu: radiobutton} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1 -tearoff 1
    .m1 add radiobutton -label "1" -variable foo -value one
    .m1 add radiobutton -label "2" -variable foo -value two
    .m1 add radiobutton -label "3" -variable foo -value three
    list [catch {.m1 invoke 2} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3
} -cleanup {
	destroy .m1
} -result {0 {} 0 two 0 {}}
................................................................................
    list [catch {.m1 invoke 1} msg] $msg 
} -cleanup {
	destroy .m1
} -result {0 {}}
test menu-4.12 {TkInvokeMenu} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "test" -command ".m1 delete 1"
    list [catch {.m1 invoke 1} msg] $msg [catch {.m1 type "test"} msg2] $msg2
} -cleanup {
	destroy .m1
} -result {0 {} 1 {bad menu entry index "test"}}

test menu-5.1 {DestroyMenuInstance} -setup {
................................................................................
    menu .m1
    .m1 add command -label "test"
    list [.m1 delete 1] [destroy .m1]
} -result {{} {}}
test menu-8.6 {DestroyMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "one"
    .m1 add command -label "two"
    list [.m1 delete 1] [.m1 entrycget 1 -label] [destroy .m1]
} -result {{} two {}}
test menu-8.7 {DestroyMenuEntry} -setup {
	deleteWindows
} -body {
................................................................................
    deleteWindows
} -result {}


test menu-13.1 {TkGetMenuIndex} -setup {
    deleteWindows
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "active"
    .m1 add command -label "test2"
    .m1 add command -label "test3"
    .m1 activate 2
    .m1 entrycget active -label
} -cleanup {
    deleteWindows
................................................................................
} -cleanup {
    deleteWindows
} -result {}
#test menu-13.7 - Need to add @test here.
test menu-13.7 {TkGetMenuIndex} -setup {
    deleteWindows
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "active"
    .m1 add command -label "test2"
    .m1 add command -label "test3"
    .m1 entrycget 1 -label
} -cleanup {
    deleteWindows
} -result {active}
................................................................................
} -body {
    menu .m1
    .m1 insert -1 command -label "test"
} -returnCodes error -result {bad menu entry index "-1"}
test menu-16.4 {MenuAddOrInsert} -setup {
	deleteWindows
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "test"
    .m1 insert 0 command -label "test2"
    .m1 entrycget 1 -label
} -cleanup {
	deleteWindows
} -result {test2}
test menu-16.5 {MenuAddOrInsert} -setup {
................................................................................
    .m1 clone .foo
} -cleanup {
	deleteWindows
} -result {}
test menu-20.10 {CloneMenu - tearoff fields} -setup {
	deleteWindows
} -body {
    menu .m1 -tearoff 1
    list [.m1 clone .m2 normal] [.m2 cget -tearoff]
} -cleanup {
	deleteWindows
} -result {{} 1}
test menu-20.11 {CloneMenu} -setup {
	deleteWindows
} -body {
................................................................................
    .m1 configure -tearoff 0
    .m1 index @5,5
} -cleanup {
	deleteWindows
} -result {0}
test menu-22.3 {GetIndexFromCoords: mapped window, y only} -setup {
	deleteWindows
} -constraints {x11} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    .m1 index @5
} -cleanup {
	deleteWindows
} -result {0}
test menu-22.4 {GetIndexFromCoords: mapped window x,y} -setup {
	deleteWindows
} -constraints {x11} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    update
    set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]
    .m1 index @$x,5
} -cleanup {
	deleteWindows
} -result {0}
test menu-22.5 {GetIndexFromCoords: mapped wide window} -setup {
	deleteWindows
} -constraints {x11} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    wm geometry .m1 200x100
    update

Changes to tests/scale.test.

1499
1500
1501
1502
1503
1504
1505




















1506
1507
1508
1509
1510
1511
    pack .s
    .s set 10
    update  ; # -command callback shall fire
    set res [list [.s get] $commandedVar]
} -cleanup {
    destroy .s
} -result {10 10}





















option clear

# cleanup
cleanupTests
return






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






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
    pack .s
    .s set 10
    update  ; # -command callback shall fire
    set res [list [.s get] $commandedVar]
} -cleanup {
    destroy .s
} -result {10 10}

test scale-21.1 {Bug [55b95f578a] - Associating variable with bignum value with scale crashes it} -setup {
    catch {destroy .s}
} -body {
    pack [scale .s]
    set foo 5.79e99
    # non-regression test for bug [55b95f578a] - shall just not crash
    .s configure -variable foo
} -cleanup {
    destroy .s
} -result {}
test scale-21.2 {Bug [55b95f578a] again - Bignum value for -from/-to with scale crashes it} -setup {
    catch {destroy .s}
} -body {
    pack [scale .s]
    # non-regression test for bug [55b95f578a] - shall just not crash
    .s configure -from -6.8e99 -to 8.8e99
} -cleanup {
    destroy .s
} -result {}

option clear

# cleanup
cleanupTests
return

Changes to tests/text.test.

7302
7303
7304
7305
7306
7307
7308


7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319



7320
7321


7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332



7333
7334


7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345


























7346
7347
7348
7349
7350
7351
7352
7353
7354
    set result "ok"
} -cleanup {
    destroy .t
} -result {ok}


test text-36.1 "bug #1777362: event handling with hyphenated windows" -setup {


    proc bgerror {m} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t-1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    update
    set ::my_error
} -cleanup {
    destroy .t-1



} -result {}
test text-36.2 "bug #1777362: event handling with hyphenated windows" -setup {


    proc bgerror {m} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t+1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    update
    set ::my_error
} -cleanup {
    destroy $w



} -result {}
test text-36.3 "bug #1777362: event handling with hyphenated windows" -setup {


    proc bgerror {m} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t*1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    update
    set ::my_error
} -cleanup {
    destroy $w


























} -result {}
 
# cleanup
cleanupTests
return

# Local Variables:
# mode: tcl
# End:






>
>
|










>
>
>


>
>
|










>
>
>


>
>
|










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









7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
    set result "ok"
} -cleanup {
    destroy .t
} -result {ok}


test text-36.1 "bug #1777362: event handling with hyphenated windows" -setup {
    set save [interp bgerror {}]
    interp bgerror {} returnerror-36.1
    proc returnerror-36.1 {m opts} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t-1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    update
    set ::my_error
} -cleanup {
    destroy .t-1
    rename returnerror-36.1 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error w
} -result {}
test text-36.2 "bug #1777362: event handling with hyphenated windows" -setup {
    set save [interp bgerror {}]
    interp bgerror {} returnerror-36.2
    proc returnerror-36.2 {m opts} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t+1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    update
    set ::my_error
} -cleanup {
    destroy $w
    rename returnerror-36.2 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error w
} -result {}
test text-36.3 "bug #1777362: event handling with hyphenated windows" -setup {
    set save [interp bgerror {}]
    interp bgerror {} returnerror-36.3
    proc returnerror-36.3 {m opts} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t*1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    update
    set ::my_error
} -cleanup {
    destroy $w
    rename returnerror-36.3 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error w
} -result {}


test text-37.1 "bug #dd9667635d: text anchor not set" -setup {
    set save [interp bgerror {}]
    interp bgerror {} returnerror-37.1
    proc returnerror-37.1 {m opts} {set ::my_error $m}
    destroy .t
    set ::my_error {}
    pack [text .t]
} -body {
    .t insert end "Hello world!"
    .t tag add sel 1.0 end
    # this line shall not trigger error:
    #     bad text index "tk::anchorN"
    event generate .t <<SelectPrevLine>>
    update
    set ::my_error
} -cleanup {
    destroy .t
    rename returnerror-37.1 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error
} -result {}
 
# cleanup
cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/textDisp.test.

944
945
946
947
948
949
950






















951
952
953
954
955
956
957
    set scrollInfo unchanged
    .t insert end xxxxxxxxx\n
    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx
    update
    set scrollInfo
} [list 0.0 [expr {4.0/11}]]























# The following group of tests is marked non-portable because
# they result in a lot of extra redisplay under Ultrix.  I don't
# know why this is so.

.t configure -bd 2 -relief raised -wrap char
.t delete 1.0 end






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







944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
    set scrollInfo unchanged
    .t insert end xxxxxxxxx\n
    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx
    update
    set scrollInfo
} [list 0.0 [expr {4.0/11}]]
test textDisp-6.10 {DisplayText, redisplay embedded windows after scroll.} {aqua} {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1"
    foreach i {2 3 4} {
	.t insert end "\nLine $i"
    }
    .t insert end "\n"
    .t window create end -create {
	button %W.button_one -text "Button 1"}
    .t insert end "\nLine 6\n"
    .t window create end -create {
	button %W.button_two -text "Button 2"}
    .t insert end "\nLine 8\n"
    .t window create end -create {
	button %W.button_three -text "Button 3"}
    update
    .t delete 2.0 3.0
    update
    list $tk_textEmbWinDisplay
} {{4.0 6.0}}


# The following group of tests is marked non-portable because
# they result in a lot of extra redisplay under Ultrix.  I don't
# know why this is so.

.t configure -bd 2 -relief raised -wrap char
.t delete 1.0 end

Changes to unix/Makefile.in.

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
...
515
516
517
518
519
520
521

522
523
524
525
526
527
528
....
1268
1269
1270
1271
1272
1273
1274



1275
1276
1277
1278
1279
1280
1281
	tkUnixFocus.o  $(FONT_OBJS) tkUnixInit.o tkUnixKey.o tkUnixMenu.o \
	tkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \
	tkUnixSend.o tkUnixWm.o tkUnixXId.o

AQUA_OBJS = tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \
	tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \
	tkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \
	tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXInit.o \
	tkMacOSXKeyboard.o tkMacOSXKeyEvent.o tkMacOSXMenu.o \
	tkMacOSXMenubutton.o tkMacOSXMenus.o tkMacOSXMouseEvent.o \
	tkMacOSXNotify.o tkMacOSXRegion.o tkMacOSXScrlbr.o tkMacOSXSend.o \
	tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \
	tkMacOSXWm.o tkMacOSXXStubs.o \
	tkFileFilter.o tkMacWinMenu.o tkPointer.o tkUnix3d.o tkUnixScale.o \
	xcolors.o xdraw.o xgc.o ximage.o xutil.o \
	ttkMacOSXTheme.o
................................................................................
	$(MAC_OSX_DIR)/tkMacOSXBitmap.c $(MAC_OSX_DIR)/tkMacOSXButton.c \
	$(MAC_OSX_DIR)/tkMacOSXClipboard.c $(MAC_OSX_DIR)/tkMacOSXColor.c \
	$(MAC_OSX_DIR)/tkMacOSXConfig.c $(MAC_OSX_DIR)/tkMacOSXCursor.c \
	$(MAC_OSX_DIR)/tkMacOSXDebug.c $(MAC_OSX_DIR)/tkMacOSXDialog.c \
	$(MAC_OSX_DIR)/tkMacOSXDraw.c $(MAC_OSX_DIR)/tkMacOSXEmbed.c \
	$(MAC_OSX_DIR)/tkMacOSXEntry.c $(MAC_OSX_DIR)/tkMacOSXEvent.c \
	$(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXHLEvents.c \

	$(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \
	$(MAC_OSX_DIR)/tkMacOSXKeyEvent.c $(MAC_OSX_DIR)/tkMacOSXMenu.c \
	$(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \
	$(MAC_OSX_DIR)/tkMacOSXMouseEvent.c $(MAC_OSX_DIR)/tkMacOSXNotify.c \
	$(MAC_OSX_DIR)/tkMacOSXRegion.c $(MAC_OSX_DIR)/tkMacOSXScrlbr.c \
	$(MAC_OSX_DIR)/tkMacOSXSend.c $(MAC_OSX_DIR)/tkMacOSXSubwindows.c \
	$(MAC_OSX_DIR)/tkMacOSXTest.c $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c \
................................................................................

tkMacOSXFont.o: $(MAC_OSX_DIR)/tkMacOSXFont.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXFont.c

tkMacOSXHLEvents.o: $(MAC_OSX_DIR)/tkMacOSXHLEvents.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXHLEvents.c




tkMacOSXInit.o: $(MAC_OSX_DIR)/tkMacOSXInit.c tkConfig.sh
	$(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \
	    $(MAC_OSX_DIR)/tkMacOSXInit.c

tkMacOSXKeyboard.o: $(MAC_OSX_DIR)/tkMacOSXKeyboard.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyboard.c







|
|







 







>







 







>
>
>







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
...
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
	tkUnixFocus.o  $(FONT_OBJS) tkUnixInit.o tkUnixKey.o tkUnixMenu.o \
	tkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \
	tkUnixSend.o tkUnixWm.o tkUnixXId.o

AQUA_OBJS = tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \
	tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \
	tkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \
	tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXImage.o \
	tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o tkMacOSXMenu.o \
	tkMacOSXMenubutton.o tkMacOSXMenus.o tkMacOSXMouseEvent.o \
	tkMacOSXNotify.o tkMacOSXRegion.o tkMacOSXScrlbr.o tkMacOSXSend.o \
	tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \
	tkMacOSXWm.o tkMacOSXXStubs.o \
	tkFileFilter.o tkMacWinMenu.o tkPointer.o tkUnix3d.o tkUnixScale.o \
	xcolors.o xdraw.o xgc.o ximage.o xutil.o \
	ttkMacOSXTheme.o
................................................................................
	$(MAC_OSX_DIR)/tkMacOSXBitmap.c $(MAC_OSX_DIR)/tkMacOSXButton.c \
	$(MAC_OSX_DIR)/tkMacOSXClipboard.c $(MAC_OSX_DIR)/tkMacOSXColor.c \
	$(MAC_OSX_DIR)/tkMacOSXConfig.c $(MAC_OSX_DIR)/tkMacOSXCursor.c \
	$(MAC_OSX_DIR)/tkMacOSXDebug.c $(MAC_OSX_DIR)/tkMacOSXDialog.c \
	$(MAC_OSX_DIR)/tkMacOSXDraw.c $(MAC_OSX_DIR)/tkMacOSXEmbed.c \
	$(MAC_OSX_DIR)/tkMacOSXEntry.c $(MAC_OSX_DIR)/tkMacOSXEvent.c \
	$(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXHLEvents.c \
	$(MAC_OSX_DIR)/tkMacOSXImage.c \
	$(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \
	$(MAC_OSX_DIR)/tkMacOSXKeyEvent.c $(MAC_OSX_DIR)/tkMacOSXMenu.c \
	$(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \
	$(MAC_OSX_DIR)/tkMacOSXMouseEvent.c $(MAC_OSX_DIR)/tkMacOSXNotify.c \
	$(MAC_OSX_DIR)/tkMacOSXRegion.c $(MAC_OSX_DIR)/tkMacOSXScrlbr.c \
	$(MAC_OSX_DIR)/tkMacOSXSend.c $(MAC_OSX_DIR)/tkMacOSXSubwindows.c \
	$(MAC_OSX_DIR)/tkMacOSXTest.c $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c \
................................................................................

tkMacOSXFont.o: $(MAC_OSX_DIR)/tkMacOSXFont.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXFont.c

tkMacOSXHLEvents.o: $(MAC_OSX_DIR)/tkMacOSXHLEvents.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXHLEvents.c

tkMacOSXImage.o: $(MAC_OSX_DIR)/tkMacOSXImage.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXImage.c

tkMacOSXInit.o: $(MAC_OSX_DIR)/tkMacOSXInit.c tkConfig.sh
	$(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \
	    $(MAC_OSX_DIR)/tkMacOSXInit.c

tkMacOSXKeyboard.o: $(MAC_OSX_DIR)/tkMacOSXKeyboard.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyboard.c

Changes to unix/tkUnixRFont.c.

854
855
856
857
858
859
860




861
862
863
864
865
866
867
...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
...
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
....
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1046
1047
1048
1049
1050
1051
1052








1053
1054


1055
1056
1057
1058
1059
1060
1061
....
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
....
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
    XGCValues values;
    XftColor *xftcolor;
    int clen, nspec, xStart = x;
    XftGlyphFontSpec specs[NUM_SPEC];
    XGlyphInfo metrics;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));





    if (fontPtr->ftDraw == 0) {
#if DEBUG_FONTSEL
	printf("Switch to drawable 0x%x\n", drawable);
#endif /* DEBUG_FONTSEL */
	fontPtr->ftDraw = XftDrawCreate(display, drawable,
		DefaultVisual(display, fontPtr->screen),
................................................................................
    }
    XGetGCValues(display, gc, GCForeground, &values);
    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }
    nspec = 0;
    while (numBytes > 0 && x <= maxCoord && y <= maxCoord) {
	XftFont *ftFont;
	FcChar32 c;

	clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
	if (clen <= 0) {
	    /*
	     * This should not happen, but it can.
................................................................................
	    goto doUnderlineStrikeout;
	}
	source += clen;
	numBytes -= clen;

	ftFont = GetFont(fontPtr, c, 0.0);
	if (ftFont) {
	    specs[nspec].font = ftFont;


	    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
	    specs[nspec].x = x;
	    specs[nspec].y = y;
	    XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1,
		    &metrics);
	    x += metrics.xOff;
	    y += metrics.yOff;
	    nspec++;





	    if (nspec == NUM_SPEC) {
		XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
			specs, nspec);
		nspec = 0;

	    }
	}
    }
    if (nspec) {
	XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);
    }

................................................................................
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }

    nglyph = 0;
    currentFtFont = NULL;
    originX = originY = 0;		/* lint */

    while (numBytes > 0 && x <= maxCoord && x >= minCoord && y <= maxCoord
	    && y >= minCoord) {
	XftFont *ftFont;
	FcChar32 c;

	clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
	if (clen <= 0) {
	    /*
	     * This should not happen, but it can.
................................................................................
	    }
	    originX = ROUND16(x);
	    originY = ROUND16(y);
	    if (nglyph) {
		XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
			nglyph, &metrics);
		nglyph = 0;








		x += metrics.xOff;
		y += metrics.yOff;


	    }
	    currentFtFont = ftFont;
	}
	glyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c);
    }
    if (nglyph) {
	XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont,
................................................................................
    }
    XGetGCValues(display, gc, GCForeground, &values);
    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }
    nspec = 0;
    while (numBytes > 0 && x <= maxCoord && x >= minCoord
	    && y <= maxCoord && y >= minCoord) {
	XftFont *ftFont, *ft0Font;
	FcChar32 c;

	clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
	if (clen <= 0) {
	    /*
	     * This should not happen, but it can.
................................................................................
	if (ftFont && ft0Font) {
	    specs[nspec].font = ftFont;
	    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
	    specs[nspec].x = ROUND16(x);
	    specs[nspec].y = ROUND16(y);
	    XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,
		    &metrics);
	    x += metrics.xOff*cosA + metrics.yOff*sinA;
	    y += metrics.yOff*cosA - metrics.xOff*sinA;
	    nspec++;

	    if (nspec == NUM_SPEC) {
		XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
			specs, nspec);
		nspec = 0;
	    }
	}
    }
    if (nspec) {






>
>
>
>







 







|







 







|
>
>

<
<


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







 







|
<







 







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







 







<
|







 







|
|
|
>
|







854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
...
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
...
896
897
898
899
900
901
902
903
904
905
906


907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
....
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
....
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078
1079
....
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114
1115
....
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
    XGCValues values;
    XftColor *xftcolor;
    int clen, nspec, xStart = x;
    XftGlyphFontSpec specs[NUM_SPEC];
    XGlyphInfo metrics;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

   if (maxCoord <= y) {
      return; /* nothing to draw */
   }

    if (fontPtr->ftDraw == 0) {
#if DEBUG_FONTSEL
	printf("Switch to drawable 0x%x\n", drawable);
#endif /* DEBUG_FONTSEL */
	fontPtr->ftDraw = XftDrawCreate(display, drawable,
		DefaultVisual(display, fontPtr->screen),
................................................................................
    }
    XGetGCValues(display, gc, GCForeground, &values);
    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }
    nspec = 0;
    while (numBytes > 0) {
	XftFont *ftFont;
	FcChar32 c;

	clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
	if (clen <= 0) {
	    /*
	     * This should not happen, but it can.
................................................................................
	    goto doUnderlineStrikeout;
	}
	source += clen;
	numBytes -= clen;

	ftFont = GetFont(fontPtr, c, 0.0);
	if (ftFont) {
            int cx = x;
            int cy = y;

	    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);


	    XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1,
		    &metrics);
            if ((x += metrics.xOff) >= maxCoord
                  || (y += metrics.yOff) >= maxCoord) {
               break;
            }
            if (metrics.xOff > 0 && cx >= 0 && cy >= 0) {
               specs[nspec].font = ftFont;
               specs[nspec].x = cx;
               specs[nspec].y = cy;
               if (++nspec == NUM_SPEC) {
                   XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
                           specs, nspec);
                   nspec = 0;
               }
	    }
	}
    }
    if (nspec) {
	XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);
    }

................................................................................
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }

    nglyph = 0;
    currentFtFont = NULL;
    originX = originY = 0;		/* lint */

    while (numBytes > 0 && x >= minCoord && y >= minCoord) {

	XftFont *ftFont;
	FcChar32 c;

	clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
	if (clen <= 0) {
	    /*
	     * This should not happen, but it can.
................................................................................
	    }
	    originX = ROUND16(x);
	    originY = ROUND16(y);
	    if (nglyph) {
		XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
			nglyph, &metrics);
		nglyph = 0;
                /*
                 * Breaking at this place is sub-optimal, but the whole algorithm
                 * has a design problem, the choice of NUM_SPEC is arbitrary, and so
                 * the inter-glyph spacing will look arbitrary. This algorithm
                 * has to draw the whole string at once (or whole blocks with same
                 * font), this requires a dynamic 'glyphs' array. In case of overflow
                 * the array has to be divided until the maximal string will fit. (GC)
                 */
                if ((x += metrics.xOff) >= maxCoord || (y += metrics.yOff) >= maxCoord) {

                   break;
                }
	    }
	    currentFtFont = ftFont;
	}
	glyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c);
    }
    if (nglyph) {
	XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont,
................................................................................
    }
    XGetGCValues(display, gc, GCForeground, &values);
    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }
    nspec = 0;

    while (numBytes > 0 && x >= minCoord && y >= minCoord) {
	XftFont *ftFont, *ft0Font;
	FcChar32 c;

	clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
	if (clen <= 0) {
	    /*
	     * This should not happen, but it can.
................................................................................
	if (ftFont && ft0Font) {
	    specs[nspec].font = ftFont;
	    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
	    specs[nspec].x = ROUND16(x);
	    specs[nspec].y = ROUND16(y);
	    XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,
		    &metrics);
            if ((x += metrics.xOff*cosA + metrics.yOff*sinA) > maxCoord
                                 || (y += metrics.yOff*cosA - metrics.xOff*sinA) > maxCoord) {
               break;
            }
            if (++nspec == NUM_SPEC) {
		XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
			specs, nspec);
		nspec = 0;
	    }
	}
    }
    if (nspec) {

Changes to unix/tkUnixScale.c.

9
10
11
12
13
14
15




16
17
18
19
20
21
22
...
263
264
265
266
267
268
269
270


271
272
273
274
275
276
277
...
348
349
350
351
352
353
354

355


356
357
358
359
360
361
362
...
480
481
482
483
484
485
486
487


488
489
490
491
492
493
494
...
547
548
549
550
551
552
553

554


555
556
557
558
559
560
561
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkInt.h"
#include "tkScale.h"





/*
 * Forward declarations for functions defined later in this file:
 */

static void		DisplayHorizontalScale(TkScale *scalePtr,
			    Drawable drawable, XRectangle *drawnAreaPtr);
static void		DisplayHorizontalValue(TkScale *scalePtr,
................................................................................
    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);

    /*
     * Adjust the y-coordinate if necessary to keep the text entirely inside
     * the window.
     */
................................................................................
	     * 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.
	     */

	    ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
		    / tickInterval);

	    sprintf(valueString, scalePtr->format, scalePtr->fromValue);


	    maxTicks = (double) Tk_Width(tkwin)
		    / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
	    if (ticks > maxTicks) {
		tickInterval *= (ticks / maxTicks);
	    }
	    for (tickValue = scalePtr->fromValue; ;
		 tickValue += tickInterval) {
................................................................................
    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);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);

    /*
     * Adjust the x-coordinate if necessary to keep the text entirely inside
     * the window.
     */
................................................................................
    /*
     * Invoke the scale's command if needed.
     */

    Tcl_Preserve(scalePtr);
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
	Tcl_Preserve(interp);

	sprintf(string, scalePtr->format, scalePtr->value);


	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {






>
>
>
>







 







|
>
>







 







>
|
>
>







 







|
>
>







 







>
|
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkInt.h"
#include "tkScale.h"

#if defined(_WIN32)
#define snprintf _snprintf
#endif

/*
 * Forward declarations for functions defined later in this file:
 */

static void		DisplayHorizontalScale(TkScale *scalePtr,
			    Drawable drawable, XRectangle *drawnAreaPtr);
static void		DisplayHorizontalValue(TkScale *scalePtr,
................................................................................
    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;
    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) {
        valueString[TCL_DOUBLE_SPACE - 1] = '\0';
    }
    length = (int) strlen(valueString);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);

    /*
     * Adjust the y-coordinate if necessary to keep the text entirely inside
     * the window.
     */
................................................................................
	     * 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.
	     */

	    ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
		    / tickInterval);
            if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format,
                    scalePtr->fromValue) < 0) {
                valueString[TCL_DOUBLE_SPACE - 1] = '\0';
            }
	    maxTicks = (double) Tk_Width(tkwin)
		    / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
	    if (ticks > maxTicks) {
		tickInterval *= (ticks / maxTicks);
	    }
	    for (tickValue = scalePtr->fromValue; ;
		 tickValue += tickInterval) {
................................................................................
    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;
    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) {
        valueString[TCL_DOUBLE_SPACE - 1] = '\0';
    }
    length = (int) strlen(valueString);
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);

    /*
     * Adjust the x-coordinate if necessary to keep the text entirely inside
     * the window.
     */
................................................................................
    /*
     * Invoke the scale's command if needed.
     */

    Tcl_Preserve(scalePtr);
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
	Tcl_Preserve(interp);
        if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
                scalePtr->value) < 0) {
            string[TCL_DOUBLE_SPACE - 1] = '\0';
        }
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {

Changes to win/makefile.vc.

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
lflags	= $(lflags) -profile
!endif

!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
lflags	= $(lflags) -nodefaultlib:libucrt.lib
!endif

!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
### Align sections for PE size savings.
lflags	= $(lflags) -opt:nowin98
!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
### Align sections for speed in loading by choosing the virtual page size.
lflags	= $(lflags) -align:4096
!endif

!if $(LOIMPACT)
lflags	= $(lflags) -ws:aggressive
!endif

dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console
guilflags = $(lflags) -subsystem:windows
................................................................................

$(TKLIB): $(TKOBJS)
!if $(STATIC_BUILD)
	$(lib32) -nologo -out:[email protected] @<<
$**
<<
!else
	$(link32) $(dlllflags) -base:@$(COFFBASE),tk -out:[email protected] $(guilibs) \
		$(TCLSTUBLIB) @<<
$**
<<
	$(_VC_MANIFEST_EMBED_DLL)
	[email protected] $*.exp
!endif







<
<
<
<
<
<
<
<







 







|







501
502
503
504
505
506
507








508
509
510
511
512
513
514
...
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
lflags	= $(lflags) -profile
!endif

!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
lflags	= $(lflags) -nodefaultlib:libucrt.lib
!endif









!if $(LOIMPACT)
lflags	= $(lflags) -ws:aggressive
!endif

dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console
guilflags = $(lflags) -subsystem:windows
................................................................................

$(TKLIB): $(TKOBJS)
!if $(STATIC_BUILD)
	$(lib32) -nologo -out:[email protected] @<<
$**
<<
!else
	$(link32) $(dlllflags) -out:[email protected] $(guilibs) \
		$(TCLSTUBLIB) @<<
$**
<<
	$(_VC_MANIFEST_EMBED_DLL)
	[email protected] $*.exp
!endif

Changes to win/nmakehlp.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
70
71
72
73
74
75
76

77
78
79
80
81
82
83
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
149
150
151
152
153
154
155
156


157



158
159
160
161
162
163
164
...
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332
...
364
365
366
367
368
369
370


371


372
373
374
375
376
377
378
...
429
430
431
432
433
434
435
436


437
438
439
440
441
442
443
#endif



/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char *option);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */
................................................................................
main(
    int argc,
    char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;


    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);

................................................................................
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForCompilerFeature(argv[2]);
	case 'l':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
	       		"usage: %s -l <linker option>\n"
			"Tests for whether link.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForLinkerFeature(argv[2]);
	case 'f':
	    if (argc == 2) {
		chars = snprintf(msg, sizeof(msg) - 1,
			"usage: %s -f <string> <substring>\n"
			"Find a substring within another\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
................................................................................
		    "Extract a version from a file:\n"
		    "eg: pkgIndex.tcl \"package ifneeded http\"",
		    argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 0;
	    }
	    printf("%s\n", GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0'));


	    return 0;



	case 'Q':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -Q path\n"
		    "Emit the fully qualified path\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
................................................................................
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}
 
static int
CheckForLinkerFeature(
    const char *option)

{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];

    char cmdline[100];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
................................................................................

    lstrcpy(cmdline, "link.exe -nologo ");

    /*
     * Append our option for testing.
     */



    lstrcat(cmdline, option);



    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
................................................................................
    /*
     * Look for the commandline warning code in the stderr stream.
     */

    return !(strstr(Out.buffer, "LNK1117") != NULL ||
	    strstr(Err.buffer, "LNK1117") != NULL ||
	    strstr(Out.buffer, "LNK4044") != NULL ||
	    strstr(Err.buffer, "LNK4044") != NULL);


}
 
static DWORD WINAPI
ReadFromPipe(
    LPVOID args)
{
    pipeinfo *pi = (pipeinfo *) args;






|







 







>







 







|

|






|







 







|
>
>
|
>
>
>







 







|
>








>
|







 







>
>
|
>
>







 







|
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
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
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
#endif



/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */
................................................................................
main(
    int argc,
    char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;
    char *s;

    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);

................................................................................
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForCompilerFeature(argv[2]);
	case 'l':
	    if (argc < 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
	       		"usage: %s -l <linker option> ?<mandatory option> ...?\n"
			"Tests for whether link.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForLinkerFeature(&argv[2], argc-2);
	case 'f':
	    if (argc == 2) {
		chars = snprintf(msg, sizeof(msg) - 1,
			"usage: %s -f <string> <substring>\n"
			"Find a substring within another\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
................................................................................
		    "Extract a version from a file:\n"
		    "eg: pkgIndex.tcl \"package ifneeded http\"",
		    argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 0;
	    }
	    s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
	    if (s && *s) {
		printf("%s\n", s);
		return 0;
	    } else
		return 1; /* Version not found. Return non-0 exit code */

	case 'Q':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -Q path\n"
		    "Emit the fully qualified path\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
................................................................................
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}
 
static int
CheckForLinkerFeature(
    const char **options,
    int count)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    int i;
    char cmdline[255];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
................................................................................

    lstrcpy(cmdline, "link.exe -nologo ");

    /*
     * Append our option for testing.
     */

    for (i = 0; i < count; i++) {
	lstrcat(cmdline, " \"");
	lstrcat(cmdline, options[i]);
	lstrcat(cmdline, "\"");
    }

    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
................................................................................
    /*
     * Look for the commandline warning code in the stderr stream.
     */

    return !(strstr(Out.buffer, "LNK1117") != NULL ||
	    strstr(Err.buffer, "LNK1117") != NULL ||
	    strstr(Out.buffer, "LNK4044") != NULL ||
	    strstr(Err.buffer, "LNK4044") != NULL ||
	    strstr(Out.buffer, "LNK4224") != NULL ||
	    strstr(Err.buffer, "LNK4224") != NULL);
}
 
static DWORD WINAPI
ReadFromPipe(
    LPVOID args)
{
    pipeinfo *pi = (pipeinfo *) args;

Changes to win/rules.vc.

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
...
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
...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
#----------------------------------------------------------
# Set the proper copy method to avoid overwrite questions
# to the user when copying files and selecting the right
# "delete all" method.
#----------------------------------------------------------

!if "$(OS)" == "Windows_NT"
RMDIR	= rmdir /S /Q
ERRNULL  = 2>NUL
!if ![ver | find "4.0" > nul]
CPY	= echo y | xcopy /i >NUL
COPY	= copy >NUL
!else
CPY	= xcopy /i /y >NUL
COPY	= copy /y >NUL
!endif
!else # "$(OS)" != "Windows_NT"
CPY	= xcopy /i >_JUNK.OUT # On Win98 NUL does not work here.
COPY	= copy >_JUNK.OUT # On Win98 NUL does not work here.
RMDIR	= deltree /Y
NULL    = \NUL # Used in testing directory existence
ERRNULL = >NUL # Win9x shell cannot redirect stderr
!endif
MKDIR   = mkdir

#------------------------------------------------------------------------------
# Determine the host and target architectures and compiler version.
#------------------------------------------------------------------------------

_HASH=^#
................................................................................
!message *** Compiler has 'B-stepping errata workarounds'
COMPILERFLAGS   = $(COMPILERFLAGS) -QIA64_Bx
!else
!message *** Compiler does not have 'B-stepping errata workarounds'
!endif
!endif

!if "$(MACHINE)" == "IX86"
### test for -align:4096, when align:512 will do.
!if [nmakehlp -l -opt:nowin98]
!message *** Linker has 'Win98 alignment problem'
ALIGN98_HACK	= 1
!else
!message *** Linker does not have 'Win98 alignment problem'
ALIGN98_HACK	= 0
!endif
!else
ALIGN98_HACK	= 0
!endif

LINKERFLAGS     =

!if [nmakehlp -l -ltcg]
LINKERFLAGS     =-ltcg
!endif

#----------------------------------------------------------
................................................................................
TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
!if !exist($(TCLIMPLIB))
TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:x=).lib"
!endif
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib"
COFFBASE	= \must\have\tcl\sources\to\build\this\target
TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
TCL_INCLUDES    = -I"$(_TCLDIR)\include"
!else
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
!if !exist($(TCLSH))
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:x=).exe"
!endif
................................................................................
TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
!if !exist($(TCLIMPLIB))
TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:x=).lib"
!endif
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib"
COFFBASE	= "$(_TCLDIR)\win\coffbase.txt"
TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
!endif

!endif

#-------------------------------------------------------------------------






<









<
<
<
<
<
<
<







 







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







 







<







 







<







29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44







45
46
47
48
49
50
51
...
176
177
178
179
180
181
182













183
184
185
186
187
188
189
...
570
571
572
573
574
575
576

577
578
579
580
581
582
583
...
585
586
587
588
589
590
591

592
593
594
595
596
597
598
#----------------------------------------------------------
# Set the proper copy method to avoid overwrite questions
# to the user when copying files and selecting the right
# "delete all" method.
#----------------------------------------------------------


RMDIR	= rmdir /S /Q
ERRNULL  = 2>NUL
!if ![ver | find "4.0" > nul]
CPY	= echo y | xcopy /i >NUL
COPY	= copy >NUL
!else
CPY	= xcopy /i /y >NUL
COPY	= copy /y >NUL
!endif







MKDIR   = mkdir

#------------------------------------------------------------------------------
# Determine the host and target architectures and compiler version.
#------------------------------------------------------------------------------

_HASH=^#
................................................................................
!message *** Compiler has 'B-stepping errata workarounds'
COMPILERFLAGS   = $(COMPILERFLAGS) -QIA64_Bx
!else
!message *** Compiler does not have 'B-stepping errata workarounds'
!endif
!endif














LINKERFLAGS     =

!if [nmakehlp -l -ltcg]
LINKERFLAGS     =-ltcg
!endif

#----------------------------------------------------------
................................................................................
TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
!if !exist($(TCLIMPLIB))
TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:x=).lib"
!endif
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib"

TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
TCL_INCLUDES    = -I"$(_TCLDIR)\include"
!else
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
!if !exist($(TCLSH))
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:x=).exe"
!endif
................................................................................
TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
!if !exist($(TCLIMPLIB))
TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:x=).lib"
!endif
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib"

TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
!endif

!endif

#-------------------------------------------------------------------------

Changes to win/tkWinMenu.c.

2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
		    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16)
		    | (1 << 29) | (1 << 30) | (1 << 31));
	    break;
	case XK_Alt_R:
	    scanCode = MapVirtualKey(VK_RMENU, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16) | (1 << 24)
		    | (0x111 << 29) | (1 << 30) | (1 << 31));
	    break;
	case XK_F10:
	    scanCode = MapVirtualKey(VK_F10, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_F10,
		    (int) (scanCode << 16) | (1 << 30) | (1 << 31));
	    break;






|







2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
		    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16)
		    | (1 << 29) | (1 << 30) | (1 << 31));
	    break;
	case XK_Alt_R:
	    scanCode = MapVirtualKey(VK_RMENU, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16) | (1 << 24)
		    | (1 << 29) | (1 << 30) | (1 << 31));
	    break;
	case XK_F10:
	    scanCode = MapVirtualKey(VK_F10, 0);
	    CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYUP, VK_F10,
		    (int) (scanCode << 16) | (1 << 30) | (1 << 31));
	    break;