Index: .fossil-settings/encoding-glob ================================================================== --- .fossil-settings/encoding-glob +++ .fossil-settings/encoding-glob @@ -1,5 +1,3 @@ win/buildall.vc.bat win/makefile.vc -win/mkd.bat -win/rmd.bat win/rules.vc Index: .project ================================================================== --- .project +++ .project @@ -1,8 +1,8 @@ - tk8.6 + tk8.7 Index: ChangeLog.2002 ================================================================== --- ChangeLog.2002 +++ ChangeLog.2002 @@ -2236,11 +2236,11 @@ * unix/tkUnixWm.c (CreateWrapper): Removed redundat setting of inputContext to null. * win/Makefile.in: changed gdb and shell targets to properly build - all binaries before running (otherwise an error often occured). + all binaries before running (otherwise an error often occurred). 2002-03-28 David Gravereaux * win/.cvsignore (new): * win/lamp.bmp (new): Index: ChangeLog.2004 ================================================================== --- ChangeLog.2004 +++ ChangeLog.2004 @@ -809,11 +809,11 @@ default canvas origin. [Bug 956681] 2004-07-05 George Peter Staplin * generic/tkEvent.c: TK_XIM_SPOT preprocessor usage was modified - slightly to fix a bug that occured when TK_XIM_SPOT was defined as 0. + slightly to fix a bug that occurred when TK_XIM_SPOT was defined as 0. Thanks to Joe Mistachkin for reporting this bug. 2004-07-05 Donal K. Fellows TIP#158 IMPLEMENTATION DELETED README Index: README ================================================================== --- README +++ /dev/null @@ -1,41 +0,0 @@ -README: Tk - This is the Tk 8.6.9 source distribution. - http://sourceforge.net/projects/tcl/files/Tcl/ - You can get any source release of Tk from the URL above. - -1. Introduction ---------------- - -This directory contains the sources and documentation for Tk, an X11 -toolkit implemented with the Tcl scripting language. - -For details on features, incompatibilities, and potential problems with -this release, see the Tcl/Tk 8.6 Web page at - - http://www.tcl-lang.org/software/tcltk/8.6.html - -or refer to the "changes" file in this directory, which contains a -historical record of all changes to Tk. - -Tk is maintained, enhanced, and distributed freely by the Tcl community. -Source code development and tracking of bug reports and feature requests -takes place at: - - http://core.tcl-lang.org/tk/ - -with the Tcl Developer Xchange at: - - http://www.tcl-lang.org/ - -Tk is a freely available open source package. You can do virtually -anything you like with it, such as modifying it, redistributing it, -and selling it either in whole or in part. See the file -"license.terms" for complete information. - -2. See Tcl README ------------------ - -Please see the README file that comes with the associated Tcl release -for more information. There are pointers there to extensive -documentation. In addition, there are additional README files -in the subdirectories of this distribution. ADDED README.md Index: README.md ================================================================== --- /dev/null +++ README.md @@ -0,0 +1,37 @@ +# README: Tk + +This is the **Tk 8.7a2** source distribution. + +You can get any source release of Tk from [our distribution +site](https://sourceforge.net/projects/tcl/files/Tcl/). + + +## 1. Introduction + +This directory contains the sources and documentation for Tk, a +cross-platform GUI toolkit implemented with the Tcl scripting language. + +For details on features, incompatibilities, and potential problems with +this release, see [the Tcl/Tk 8.7 Web page](https://www.tcl.tk/software/tcltk/8.7.html) +or refer to the "changes" file in this directory, which contains a +historical record of all changes to Tk. + +Tk is maintained, enhanced, and distributed freely by the Tcl community. +Source code development and tracking of bug reports and feature requests +takes place at [core.tcl-lang.org](https://core.tcl-lang.org/). +Tcl/Tk release and mailing list services are [hosted by +SourceForge](https://sourceforge.net/projects/tcl/) +with the Tcl Developer Xchange hosted at +[www.tcl-lang.org](https://www.tcl-lang.org). + +Tk is a freely available open source package. You can do virtually +anything you like with it, such as modifying it, redistributing it, +and selling it either in whole or in part. See the file +`license.terms` for complete information. + +## 2. See Tcl README.md + +Please see the README.md file that comes with the associated Tcl release +for more information. There are pointers there to extensive +documentation. In addition, there are additional README files +in the subdirectories of this distribution. Index: changes ================================================================== --- changes +++ changes @@ -5097,11 +5097,11 @@ 2001-08-28 (bug fix) fixed tk_chooseDirectory crash on Win95. (baker) 2001-08-28 (bug fix) removed 2 second 'raise' delay seen by some Unix window managers. (hobbs, baker) -2001-09-14 (bug fix) fixed memory leaks that occured if errors were +2001-09-14 (bug fix) fixed memory leaks that occurred if errors were thrown while initializing the channel for an image. (darley) 2001-09-20 (new feature) --enable-64bit support was added for HP 11 when using the native compiler. @@ -7567,5 +7567,28 @@ 2018-10-30 (new platform) port to system changes in Mac OSX 10.14 (culler) 2018-11-04 (bug)[6b22d4] [treeview] binding fix (ohagan) - Released 8.6.9, November 16, 2018 - http://core.tcl-lang.org/tk/ for details - + +Changes to 8.7a1 include all changes to the 8.6 line through 8.6.7, +plus the following, which focuses on the high-level feature changes +in this changeset (new minor version) rather than bug fixes: + +2016-03-07 (feature)[841280] spinbox autoswap -to/-from to get ordering (vogel) + +2016-03-27 (feature)[38dc27] Support & (nijtmans) + +2016-08-29 (TIP 449) [text] undo/redo return character range (vogel) + +2016-11-02 (feature) Removed undocumented command [tk_getFileType] (vogel) + *** POTENTIAL INCOMPATIBILITY *** + +2017-02-05 (bug)[c0dbdd] Compatibility fonts shadowed system fonts (vogel) + +2017-03-21 (TIP 442) display text in a progressbar (zaumseil) + +2017-04-13 \u escaped content in msg files converted to true utf-8 (nijtmans) + +2017-08-28 (TIP 166) Extended color notation for alpha channel (bachmann) + +--- Released 8.7a1, September 8, 2017 --- http://core.tcl.tk/tk/ for details DELETED compat/stdlib.h Index: compat/stdlib.h ================================================================== --- compat/stdlib.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * stdlib.h -- - * - * Declares facilities exported by the "stdlib" portion of the C library. - * This file isn't complete in the ANSI-C sense; it only declares things - * that are needed by Tk. This file is needed even on many systems with - * their own stdlib.h (e.g. SunOS) because not all stdlib.h files declare - * all the procedures needed here (such as strtod). - * - * Copyright (c) 1991 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution of - * this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ - -#ifndef _STDLIB -#define _STDLIB - -#ifndef _TCL -# include -#endif - -extern void abort(void); -extern double atof(const char *string); -extern int atoi(const char *string); -extern long atol(const char *string); -extern char * calloc(unsigned int numElements, unsigned int size); -extern void exit(int status); -extern int free(char *blockPtr); -extern char * getenv(const char *name); -extern char * malloc(unsigned int numBytes); -extern void qsort(void *base, int n, int size, int (*compar)( - const void *element1, const void *element2)); -extern char * realloc(char *ptr, unsigned int numBytes); -extern double strtod(const char *string, char **endPtr); -extern long strtol(const char *string, char **endPtr, int base); -extern unsigned long strtoul(const char *string, char **endPtr, int base); - -#endif /* _STDLIB */ DELETED compat/unistd.h Index: compat/unistd.h ================================================================== --- compat/unistd.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * unistd.h -- - * - * Macros, constants and prototypes for Posix conformance. - * - * Copyright 1989 Regents of the University of California Permission to use, - * copy, modify, and distribute this software and its documentation for any - * purpose and without fee is hereby granted, provided that the above - * copyright notice appear in all copies. The University of California makes - * no representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - */ - -#ifndef _UNISTD -#define _UNISTD - -#include -#ifndef _TCL -# include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/* - * Strict POSIX stuff goes here. Extensions go down below, in the ifndef - * _POSIX_SOURCE section. - */ - -extern void _exit(int status); -extern int access(const char *path, int mode); -extern int chdir(const char *path); -extern int chown(const char *path, uid_t owner, gid_t group); -extern int close(int fd); -extern int dup(int oldfd); -extern int dup2(int oldfd, int newfd); -extern int execl(const char *path, ...); -extern int execle(const char *path, ...); -extern int execlp(const char *file, ...); -extern int execv(const char *path, char **argv); -extern int execve(const char *path, char **argv, char **envp); -extern int execvp(const char *file, char **argv); -extern pid_t fork(void); -extern char * getcwd(char *buf, size_t size); -extern gid_t getegid(void); -extern uid_t geteuid(void); -extern gid_t getgid(void); -extern int getgroups(int bufSize, int *buffer); -extern pid_t getpid(void); -extern uid_t getuid(void); -extern int isatty(int fd); -extern long lseek(int fd, long offset, int whence); -extern int pipe(int *fildes); -extern int read(int fd, char *buf, size_t size); -extern int setgid(gid_t group); -extern int setuid(uid_t user); -extern unsigned sleep(unsigned seconds); -extern char * ttyname(int fd); -extern int unlink(const char *path); -extern int write(int fd, const char *buf, size_t size); - -#ifndef _POSIX_SOURCE -extern char * crypt(const char *, const char *); -extern int fchown(int fd, uid_t owner, gid_t group); -extern int flock(int fd, int operation); -extern int ftruncate(int fd, unsigned long length); -extern int ioctl(int fd, int request, ...); -extern int readlink(const char *path, char *buf, int bufsize); -extern int setegid(gid_t group); -extern int seteuid(uid_t user); -extern int setreuid(int ruid, int euid); -extern int symlink(const char *, const char *); -extern int ttyslot(void); -extern int truncate(const char *path, unsigned long length); -extern int vfork(void); -#endif /* _POSIX_SOURCE */ - -#endif /* _UNISTD */ - Index: doc/3DBorder.3 ================================================================== --- doc/3DBorder.3 +++ doc/3DBorder.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1993 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_Alloc3DBorderFromObj 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_Alloc3DBorderFromObj, Tk_Get3DBorder, Tk_Get3DBorderFromObj, Tk_Draw3DRectangle, Tk_Fill3DRectangle, Tk_Draw3DPolygon, Tk_Fill3DPolygon, Tk_3DVerticalBevel, Tk_3DHorizontalBevel, Tk_SetBackgroundFromBorder, Tk_NameOf3DBorder, Tk_3DBorderColor, Tk_3DBorderGC, Tk_Free3DBorderFromObj, Tk_Free3DBorder \- draw borders with three-dimensional appearance Index: doc/BindTable.3 ================================================================== --- doc/BindTable.3 +++ doc/BindTable.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateBindingTable 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateBindingTable, Tk_DeleteBindingTable, Tk_CreateBinding, Tk_DeleteBinding, Tk_GetBinding, Tk_GetAllBindings, Tk_DeleteAllBindings, Tk_BindEvent \- invoke scripts in response to X events Index: doc/CanvPsY.3 ================================================================== --- doc/CanvPsY.3 +++ doc/CanvPsY.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CanvasPs 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CanvasPsY, Tk_CanvasPsBitmap, Tk_CanvasPsColor, Tk_CanvasPsFont, Tk_CanvasPsPath, Tk_CanvasPsStipple \- utility procedures for generating Postscript for canvases Index: doc/CanvTkwin.3 ================================================================== --- doc/CanvTkwin.3 +++ doc/CanvTkwin.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CanvasTkwin 3 4.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CanvasTkwin, Tk_CanvasGetCoord, Tk_CanvasDrawableCoords, Tk_CanvasSetStippleOrigin, Tk_CanvasWindowCoords, Tk_CanvasEventuallyRedraw, Tk_CanvasTagsOption \- utility procedures for canvas type managers Index: doc/CanvTxtInfo.3 ================================================================== --- doc/CanvTxtInfo.3 +++ doc/CanvTxtInfo.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CanvasTextInfo 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CanvasTextInfo \- additional information for managing text items in canvases Index: doc/Clipboard.3 ================================================================== --- doc/Clipboard.3 +++ doc/Clipboard.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_ClipboardClear 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_ClipboardClear, Tk_ClipboardAppend \- Manage the clipboard Index: doc/ClrSelect.3 ================================================================== --- doc/ClrSelect.3 +++ doc/ClrSelect.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1992-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_ClearSelection 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_ClearSelection \- Deselect a selection Index: doc/ConfigWidg.3 ================================================================== --- doc/ConfigWidg.3 +++ doc/ConfigWidg.3 @@ -105,11 +105,11 @@ int \fItype\fR; const char *\fIargvName\fR; const char *\fIdbName\fR; const char *\fIdbClass\fR; const char *\fIdefValue\fR; - int \fIoffset\fR; + size_t \fIoffset\fR; int \fIspecFlags\fR; const Tk_CustomOption *\fIcustomPtr\fR; } \fBTk_ConfigSpec\fR; .CE The \fItype\fR field indicates what type of configuration option this is @@ -159,13 +159,12 @@ record pointed to by \fIwidgRec\fR. This record is assumed to contain information relevant to the manager of the widget; its exact type is unknown to \fBTk_ConfigureWidget\fR. The \fIoffset\fR field of each \fIspecs\fR entry indicates where in \fIwidgRec\fR to store the information about this configuration option. You should use the -\fBTk_Offset\fR macro to generate \fIoffset\fR values (see below for -a description of \fBTk_Offset\fR). The location indicated by -\fIwidgRec\fR and \fIoffset\fR will be referred to as the +\fBoffsetof\fR macro to generate \fIoffset\fR values. The location +indicated by \fIwidgRec\fR and \fIoffset\fR will be referred to as the .QW target in the descriptions below. .PP The \fItype\fR field of each entry in \fIspecs\fR determines what to do with the string value of that configuration option. The @@ -467,17 +466,10 @@ bits set in its \fIspecFlags\fR field to indicate the widget types for which this entry is valid. When calling \fBTk_ConfigureWidget\fR, \fIflags\fR will have a single one of these bits set to select the entries for the desired widget type. For a working example of this feature, see the code in tkButton.c. -.SH TK_OFFSET -.PP -The \fBTk_Offset\fR macro is provided as a safe way of generating -the \fIoffset\fR values for entries in Tk_ConfigSpec structures. -It takes two arguments: the name of a type of record, and the -name of a field in that record. It returns the byte offset of -the named field in records of the given type. .SH TK_CONFIGUREINFO .PP The \fBTk_ConfigureInfo\fR procedure may be used to obtain information about one or all of the options for a given widget. Given a token for a window (\fItkwin\fR), a table describing the Index: doc/ConfigWind.3 ================================================================== --- doc/ConfigWind.3 +++ doc/ConfigWind.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_ConfigureWindow 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_ConfigureWindow, Tk_MoveWindow, Tk_ResizeWindow, Tk_MoveResizeWindow, Tk_SetWindowBorderWidth, Tk_ChangeWindowAttributes, Tk_SetWindowBackground, Tk_SetWindowBackgroundPixmap, Tk_SetWindowBorder, Tk_SetWindowBorderPixmap, Tk_SetWindowColormap, Tk_DefineCursor, Tk_UndefineCursor \- change window configuration or attributes Index: doc/CoordToWin.3 ================================================================== --- doc/CoordToWin.3 +++ doc/CoordToWin.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CoordsToWindow 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CoordsToWindow \- Find window containing a point Index: doc/CrtCmHdlr.3 ================================================================== --- doc/CrtCmHdlr.3 +++ doc/CrtCmHdlr.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateClientMessageHandler 3 "8.4" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateClientMessageHandler, Tk_DeleteClientMessageHandler \- associate procedure callback with ClientMessage type X events @@ -29,11 +29,11 @@ drop applications. .PP The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR; this mechanism only works in programs that dispatch events through \fBTk_HandleEvent\fR (or through other Tk procedures that -call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or +call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or \fBTk_MainLoop\fR). .PP \fIProc\fR should have arguments and result that match the type \fBTk_ClientMessageProc\fR: .CS Index: doc/CrtConsoleChan.3 ================================================================== --- doc/CrtConsoleChan.3 +++ doc/CrtConsoleChan.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2007 ActiveState Software Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_InitConsoleChannels 3 8.5 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_InitConsoleChannels \- Install the console channels as standard channels Index: doc/CrtErrHdlr.3 ================================================================== --- doc/CrtErrHdlr.3 +++ doc/CrtErrHdlr.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateErrorHandler 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateErrorHandler, Tk_DeleteErrorHandler \- handle X protocol errors Index: doc/CrtGenHdlr.3 ================================================================== --- doc/CrtGenHdlr.3 +++ doc/CrtGenHdlr.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1992-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateGenericHandler 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateGenericHandler, Tk_DeleteGenericHandler \- associate procedure callback with all X events @@ -36,11 +36,11 @@ use with Tk, and so on. .PP The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR; this mechanism only works in programs that dispatch events through \fBTk_HandleEvent\fR (or through other Tk procedures that -call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or +call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or \fBTk_MainLoop\fR). .PP \fIProc\fR should have arguments and result that match the type \fBTk_GenericProc\fR: .CS Index: doc/CrtImgType.3 ================================================================== --- doc/CrtImgType.3 +++ doc/CrtImgType.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateImageType 3 8.5 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateImageType, Tk_GetImageMasterData, Tk_InitImageArgs \- define new kind of image Index: doc/CrtItemType.3 ================================================================== --- doc/CrtItemType.3 +++ doc/CrtItemType.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1994-1995 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateItemType 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateItemType, Tk_GetItemTypes \- define new kind of canvas item @@ -62,11 +62,11 @@ the standard procedures implemented by the type manager: .PP .CS typedef struct Tk_ItemType { const char *\fIname\fR; - int \fIitemSize\fR; + size_t \fIitemSize\fR; Tk_ItemCreateProc *\fIcreateProc\fR; const Tk_ConfigSpec *\fIconfigSpecs\fR; Tk_ItemConfigureProc *\fIconfigProc\fR; Tk_ItemCoordProc *\fIcoordProc\fR; Tk_ItemDeleteProc *\fIdeleteProc\fR; @@ -81,10 +81,13 @@ Tk_ItemCursorProc *\fIicursorProc\fR; Tk_ItemSelectionProc *\fIselectionProc\fR; Tk_ItemInsertProc *\fIinsertProc\fR; Tk_ItemDCharsProc *\fIdCharsProc\fR; Tk_ItemType *\fInextPtr\fR; +.VS "8.7, TIP164" + Tk_ItemRotateProc *\fIrotateProc\fR; +.VE "8.7, TIP164" } \fBTk_ItemType\fR; .CE .PP The fields of a Tk_ItemType structure are described in more detail later in this manual entry. @@ -547,10 +550,50 @@ The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning, and \fIdeltaX\fR and \fIdeltaY\fR give the amounts that should be added to each x and y coordinate within the item. The type manager should adjust the item's coordinates and update the bounding box in the item's header. +.SS ROTATEPROC +.VS "8.7, TIP164" +.PP +\fItypePtr\->rotateProc\fR is invoked by Tk to rotate a canvas item +during the \fBrotate\fR widget command. +The procedure must match the following prototype: +.PP +.CS +typedef void \fBTk_ItemRotateProc\fR( + Tk_Canvas \fIcanvas\fR, + Tk_Item *\fIitemPtr\fR, + double \fIoriginX\fR, + double \fIoriginY\fR, + double \fIangleRad\fR); +.CE +.PP +The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning. +\fIoriginX\fR and \fIoriginY\fR specify an origin relative to which +the item is to be rotated, and \fIangleRad\fR gives the anticlockwise +rotation to be applied in radians. +The item should adjust the coordinates of its control points so that where +they used to have coordinates \fIx\fR and \fIy\fR, they will have new +coordinates \fIx\(fm\fR and \fIy\(fm\fR, where +.PP +.CS +\fIrelX\fR = \fIx\fR - \fIoriginX\fR +\fIrelY\fR = \fIy\fR - \fIoriginY\fR +\fIx\(fm\fR = \fIoriginX\fR + \fIrelX\fR \(mu cos(\fIangleRad\fR) + \fIrelY\fR \(mu sin(\fIangleRad\fR) +\fIy\(fm\fR = \fIoriginY\fR \(mi \fIrelX\fR \(mu sin(\fIangleRad\fR) + \fIrelY\fR \(mu cos(\fIangleRad\fR) +.CE +.PP +The control points for an item are not necessarily the coordinates provided to +the item when it is created (or via the \fItypePtr\->coordProc\fR), but could +instead be derived from them. +\fIrotateProc\fR must also update the bounding box in the item's header. +.PP +Item types do not need to provide a \fItypePtr\->rotateProc\fR. If the +\fItypePtr\->rotateProc\fR is NULL, the \fItypePtr\->coordProc\fR will be +used instead to retrieve and update the list of coordinates. +.VE "8.7, TIP164" .SS INDEXPROC .PP \fItypePtr\->indexProc\fR is invoked by Tk to translate a string index specification into a numerical index, for example during the \fBindex\fR widget command. Index: doc/CrtPhImgFmt.3 ================================================================== --- doc/CrtPhImgFmt.3 +++ doc/CrtPhImgFmt.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Australian National University '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" '\" Author: Paul Mackerras (paulus@cs.anu.edu.au), '\" Department of Computer Science, '\" Australian National University. '\" .TH Tk_CreatePhotoImageFormat 3 8.5 Tk "Tk Library Procedures" Index: doc/DeleteImg.3 ================================================================== --- doc/DeleteImg.3 +++ doc/DeleteImg.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_DeleteImage 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_DeleteImage \- Destroy an image. Index: doc/DrawFocHlt.3 ================================================================== --- doc/DrawFocHlt.3 +++ doc/DrawFocHlt.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_DrawFocusHighlight 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_DrawFocusHighlight \- draw the traversal highlight ring for a widget Index: doc/EventHndlr.3 ================================================================== --- doc/EventHndlr.3 +++ doc/EventHndlr.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_CreateEventHandler 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreateEventHandler, Tk_DeleteEventHandler \- associate procedure callback with an X event @@ -36,11 +36,11 @@ invoked in the future whenever one of the event types specified by \fImask\fR occurs in the window specified by \fItkwin\fR. The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR; this mechanism only works in programs that dispatch events through \fBTk_HandleEvent\fR (or through other Tk procedures that -call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or +call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or \fBTk_MainLoop\fR). .PP \fIProc\fR should have arguments and result that match the type \fBTk_EventProc\fR: .CS Index: doc/FreeXId.3 ================================================================== --- doc/FreeXId.3 +++ doc/FreeXId.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_FreeXId 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_FreeXId \- make X resource identifier available for reuse @@ -23,26 +23,8 @@ Identifier of X resource (window, font, pixmap, cursor, graphics context, or colormap) that is no longer in use. .BE .SH DESCRIPTION .PP -The default allocator for resource identifiers provided by Xlib is very -simple-minded and does not allow resource identifiers to be re-used. -If a long-running application reaches the end of the resource id -space, it will generate an X protocol error and crash. -Tk replaces the default id allocator with its own allocator, which -allows identifiers to be reused. -In order for this to work, \fBTk_FreeXId\fR must be called to -tell the allocator about resources that have been freed. -Tk automatically calls \fBTk_FreeXId\fR whenever it frees a -resource, so if you use procedures like \fBTk_GetFont\fR, -\fBTk_GetGC\fR, and \fBTk_GetPixmap\fR then you need not call -\fBTk_FreeXId\fR. -However, if you allocate resources directly from Xlib, for example -by calling \fBXCreatePixmap\fR, then you should call \fBTk_FreeXId\fR -when you call the corresponding Xlib free procedure, such as -\fBXFreePixmap\fR. -If you do not call \fBTk_FreeXId\fR then the resource identifier will -be lost, which could cause problems if the application runs long enough -to lose all of the available identifiers. +This function is deprecated, it doesn't do anything since 2008-08-19. .SH KEYWORDS resource identifier Index: doc/GeomReq.3 ================================================================== --- doc/GeomReq.3 +++ doc/GeomReq.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GeometryRequest 3 "8.4" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GeometryRequest, Tk_SetMinimumRequestSize, Tk_SetInternalBorder, Tk_SetInternalBorderEx \- specify desired geometry or internal border for a window Index: doc/GetAnchor.3 ================================================================== --- doc/GetAnchor.3 +++ doc/GetAnchor.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetAnchorFromObj 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetAnchorFromObj, Tk_GetAnchor, Tk_NameOfAnchor \- translate between strings and anchor positions Index: doc/GetBitmap.3 ================================================================== --- doc/GetBitmap.3 +++ doc/GetBitmap.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_AllocBitmapFromObj 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_AllocBitmapFromObj, Tk_GetBitmap, Tk_GetBitmapFromObj, Tk_DefineBitmap, Tk_NameOfBitmap, Tk_SizeOfBitmap, Tk_FreeBitmapFromObj, Tk_FreeBitmap \- maintain database of single-plane pixmaps Index: doc/GetCapStyl.3 ================================================================== --- doc/GetCapStyl.3 +++ doc/GetCapStyl.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetCapStyle 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetCapStyle, Tk_NameOfCapStyle \- translate between strings and cap styles Index: doc/GetClrmap.3 ================================================================== --- doc/GetClrmap.3 +++ doc/GetClrmap.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetColormap 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetColormap, Tk_PreserveColormap, Tk_FreeColormap \- allocate and free colormaps Index: doc/GetDash.3 ================================================================== --- doc/GetDash.3 +++ doc/GetDash.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetDash 3 8.3 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetDash \- convert from string to valid dash structure. Index: doc/GetGC.3 ================================================================== --- doc/GetGC.3 +++ doc/GetGC.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetGC 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetGC, Tk_FreeGC \- maintain database of read-only graphics contexts Index: doc/GetHINSTANCE.3 ================================================================== --- doc/GetHINSTANCE.3 +++ doc/GetHINSTANCE.3 @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. -'\" +'\" .TH Tk_GetHISTANCE 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetHINSTANCE \- retrieve the global application instance handle Index: doc/GetHWND.3 ================================================================== --- doc/GetHWND.3 +++ doc/GetHWND.3 @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. -'\" +'\" .TH HWND 3 8.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetHWND, Tk_AttachHWND \- manage interactions between the Windows handle and an X window Index: doc/GetImage.3 ================================================================== --- doc/GetImage.3 +++ doc/GetImage.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetImage 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetImage, Tk_RedrawImage, Tk_SizeOfImage, Tk_FreeImage \- use an image in a widget Index: doc/GetJoinStl.3 ================================================================== --- doc/GetJoinStl.3 +++ doc/GetJoinStl.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetJoinStyle 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetJoinStyle, Tk_NameOfJoinStyle \- translate between strings and join styles Index: doc/GetJustify.3 ================================================================== --- doc/GetJustify.3 +++ doc/GetJustify.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetJustifyFromObj 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetJustifyFromObj, Tk_GetJustify, Tk_NameOfJustify \- translate between strings and justification styles Index: doc/GetOption.3 ================================================================== --- doc/GetOption.3 +++ doc/GetOption.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetOption 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetOption \- retrieve an option from the option database Index: doc/GetPixels.3 ================================================================== --- doc/GetPixels.3 +++ doc/GetPixels.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetPixelsFromObj 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetPixelsFromObj, Tk_GetPixels, Tk_GetMMFromObj, Tk_GetScreenMM \- translate between strings and screen units Index: doc/GetPixmap.3 ================================================================== --- doc/GetPixmap.3 +++ doc/GetPixmap.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetPixmap 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetPixmap, Tk_FreePixmap \- allocate and free pixmaps Index: doc/GetRelief.3 ================================================================== --- doc/GetRelief.3 +++ doc/GetRelief.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetReliefFromObj 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetReliefFromObj, Tk_GetRelief, Tk_NameOfRelief \- translate between strings and relief values Index: doc/GetRootCrd.3 ================================================================== --- doc/GetRootCrd.3 +++ doc/GetRootCrd.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetRootCoords 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetRootCoords \- Compute root-window coordinates of window Index: doc/GetScroll.3 ================================================================== --- doc/GetScroll.3 +++ doc/GetScroll.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetScrollInfo 3 8.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetScrollInfoObj, Tk_GetScrollInfo \- parse arguments for scrolling commands @@ -13,14 +13,14 @@ .SH SYNOPSIS .nf \fB#include \fR .sp int -\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, dblPtr, intPtr\fB)\fR +\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, fractionPtr, stepsPtr\fB)\fR .sp int -\fBTk_GetScrollInfo(\fIinterp, argc, argv, dblPtr, intPtr\fB)\fR +\fBTk_GetScrollInfo(\fIinterp, argc, argv, fractionPtr, stepsPtr\fB)\fR .SH ARGUMENTS .AS "Tcl_Interp" *fractionPtr .AP Tcl_Interp *interp in Interpreter to use for error reporting. .AP int objc in @@ -48,22 +48,22 @@ It receives the entire list of words that make up a widget command and parses the words starting with \fIobjv\fR[2]. The words starting with \fIobjv\fR[2] must have one of the following forms: .CS \fBmoveto \fIfraction\fR -\fBscroll \fInumber\fB units\fR \fBscroll \fInumber\fB pages\fR +\fBscroll \fInumber\fB units\fR .CE .LP -Any of the \fBmoveto\fR, \fBscroll\fR, \fBunits\fR, and \fBpages\fR +Any of the \fBmoveto\fR, \fBscroll\fR, \fBpages\fR, and \fBunits\fR keywords may be abbreviated. If \fIobjv\fR has the \fBmoveto\fR form, \fBTK_SCROLL_MOVETO\fR is returned as result and \fI*fractionPtr\fR is filled in with the \fIfraction\fR argument to the command, which must be a proper real value. -If \fIobjv\fR has the \fBscroll\fR form, \fBTK_SCROLL_UNITS\fR -or \fBTK_SCROLL_PAGES\fR is returned and \fI*stepsPtr\fR is filled +If \fIobjv\fR has the \fBscroll\fR form, \fBTK_SCROLL_PAGES\fR +or \fBTK_SCROLL_UNITS\fR is returned and \fI*stepsPtr\fR is filled in with the \fInumber\fR value, which must be a proper integer. If an error occurs in parsing the arguments, \fBTK_SCROLL_ERROR\fR is returned and an error message is left in interpreter \fIinterp\fR's result. .PP Index: doc/GetSelect.3 ================================================================== --- doc/GetSelect.3 +++ doc/GetSelect.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetSelection 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetSelection \- retrieve the contents of a selection Index: doc/GetUid.3 ================================================================== --- doc/GetUid.3 +++ doc/GetUid.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetUid 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetUid, Tk_Uid \- convert from string to unique identifier Index: doc/GetVRoot.3 ================================================================== --- doc/GetVRoot.3 +++ doc/GetVRoot.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetVRootGeometry 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetVRootGeometry \- Get location and size of virtual root for window Index: doc/GetVisual.3 ================================================================== --- doc/GetVisual.3 +++ doc/GetVisual.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_GetVisual 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetVisual \- translate from string to visual Index: doc/Grab.3 ================================================================== --- doc/Grab.3 +++ doc/Grab.3 @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. -'\" +'\" .TH Tk_Grab 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_Grab, Tk_Ungrab \- manipulate grab state in an application Index: doc/HWNDToWindow.3 ================================================================== --- doc/HWNDToWindow.3 +++ doc/HWNDToWindow.3 @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. -'\" +'\" .TH Tk_HWNDToWindow 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_HWNDToWindow \- Find Tk's window information for a Windows window Index: doc/HandleEvent.3 ================================================================== --- doc/HandleEvent.3 +++ doc/HandleEvent.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_HandleEvent 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_HandleEvent \- invoke event handlers for window system events @@ -23,11 +23,11 @@ .BE .SH DESCRIPTION .PP \fBTk_HandleEvent\fR is a lower-level procedure that deals with window events. It is called by \fBTcl_ServiceEvent\fR (and indirectly by -\fBTk_DoOneEvent\fR), and in a few other cases within Tk. +\fBTcl_DoOneEvent\fR), and in a few other cases within Tk. It makes callbacks to any window event handlers (created by calls to \fBTk_CreateEventHandler\fR) that match \fIeventPtr\fR and then returns. In some cases it may be useful for an application to bypass the Tk event queue and call \fBTk_HandleEvent\fR directly instead of Index: doc/IdToWindow.3 ================================================================== --- doc/IdToWindow.3 +++ doc/IdToWindow.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_IdToWindow 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_IdToWindow \- Find Tk's window information for an X window Index: doc/ImgChanged.3 ================================================================== --- doc/ImgChanged.3 +++ doc/ImgChanged.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_ImageChanged 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_ImageChanged \- notify widgets that image needs to be redrawn Index: doc/Inactive.3 ================================================================== --- doc/Inactive.3 +++ doc/Inactive.3 @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. -'\" +'\" .TH Tk_GetUserInactiveTime 3 8.5 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_GetUserInactiveTime, Tk_ResetUserInactiveTime \- discover user inactivity time Index: doc/InternAtom.3 ================================================================== --- doc/InternAtom.3 +++ doc/InternAtom.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_InternAtom 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_InternAtom, Tk_GetAtomName \- manage cache of X atoms Index: doc/MainLoop.3 ================================================================== --- doc/MainLoop.3 +++ doc/MainLoop.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_MainLoop 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_MainLoop \- loop for events until all windows are deleted Index: doc/MainWin.3 ================================================================== --- doc/MainWin.3 +++ doc/MainWin.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_MainWindow 3 7.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_MainWindow, Tk_GetNumMainWindows \- functions for querying main window information Index: doc/MaintGeom.3 ================================================================== --- doc/MaintGeom.3 +++ doc/MaintGeom.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_MaintainGeometry 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_MaintainGeometry, Tk_UnmaintainGeometry \- maintain geometry of one window relative to another Index: doc/ManageGeom.3 ================================================================== --- doc/ManageGeom.3 +++ doc/ManageGeom.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_ManageGeometry 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_ManageGeometry \- arrange to handle geometry requests for a window Index: doc/MoveToplev.3 ================================================================== --- doc/MoveToplev.3 +++ doc/MoveToplev.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_MoveToplevelWindow 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_MoveToplevelWindow \- Adjust the position of a top-level window @@ -44,8 +44,8 @@ menus that want to appear at a particular place on the screen. .PP When \fBTk_MoveToplevelWindow\fR is called it does not immediately pass on the new desired location to the window manager; it defers this action until all other outstanding work has been completed, -using the \fBTk_DoWhenIdle\fR mechanism. +using the \fBTcl_DoWhenIdle\fR mechanism. .SH KEYWORDS position, top-level window, window manager Index: doc/Name.3 ================================================================== --- doc/Name.3 +++ doc/Name.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_Name 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_Name, Tk_PathName, Tk_NameToWindow \- convert between names and window tokens Index: doc/NameOfImg.3 ================================================================== --- doc/NameOfImg.3 +++ doc/NameOfImg.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_NameOfImage 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_NameOfImage \- Return name of image. @@ -12,14 +12,14 @@ .SH SYNOPSIS .nf \fB#include \fR .sp const char * -\fBTk_NameOfImage\fR(\fItypePtr\fR) +\fBTk_NameOfImage\fR(\fIimageMaster\fR) .SH ARGUMENTS -.AS Tk_ImageMaster *masterPtr -.AP Tk_ImageMaster *masterPtr in +.AS Tk_ImageMaster imageMaster +.AP Tk_ImageMaster imageMaster in Token for image, which was passed to image manager's \fIcreateProc\fR when the image was created. .BE .SH DESCRIPTION .PP Index: doc/OwnSelect.3 ================================================================== --- doc/OwnSelect.3 +++ doc/OwnSelect.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_OwnSelection 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_OwnSelection \- make a window the owner of the primary selection Index: doc/ParseArgv.3 ================================================================== --- doc/ParseArgv.3 +++ doc/ParseArgv.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_ParseArgv 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_ParseArgv \- process command-line options @@ -70,12 +70,12 @@ expected; each of its entries has the following structure: .CS typedef struct { const char *\fIkey\fR; int \fItype\fR; - char *\fIsrc\fR; - char *\fIdst\fR; + void *\fIsrc\fR; + void *\fIdst\fR; const char *\fIhelp\fR; } \fBTk_ArgvInfo\fR; .CE The \fIkey\fR field is a string such as .QW \-display @@ -310,17 +310,17 @@ /* * Define option descriptions. */ Tk_ArgvInfo argTable[] = { - {"\-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag, + {"\-X", TK_ARGV_CONSTANT, (char *) 1, &debugFlag, "Turn on debugging printfs"}, - {"\-N", TK_ARGV_INT, NULL, (char *) &numReps, + {"\-N", TK_ARGV_INT, NULL, &numReps, "Number of repetitions"}, - {"\-of", TK_ARGV_STRING, NULL, (char *) &fileName, + {"\-of", TK_ARGV_STRING, NULL, &fileName, "Name of file for output"}, - {"x", TK_ARGV_REST, NULL, (char *) &exec, + {"x", TK_ARGV_REST, NULL, &exec, "File to exec, followed by any arguments (must be last argument)."}, {NULL, TK_ARGV_END, NULL, NULL, NULL} }; Index: doc/QWinEvent.3 ================================================================== --- doc/QWinEvent.3 +++ doc/QWinEvent.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_QueueWindowEvent 3 7.5 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CollapseMotionEvents, Tk_QueueWindowEvent \- Add a window event to the Tcl event queue Index: doc/Restack.3 ================================================================== --- doc/Restack.3 +++ doc/Restack.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_RestackWindow 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_RestackWindow \- Change a window's position in the stacking order Index: doc/RestrictEv.3 ================================================================== --- doc/RestrictEv.3 +++ doc/RestrictEv.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_RestrictEvents 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_RestrictEvents \- filter and selectively delay X events @@ -28,11 +28,11 @@ .BE .SH DESCRIPTION .PP This procedure is useful in certain situations where applications are only prepared to receive certain X events. After -\fBTk_RestrictEvents\fR is called, \fBTk_DoOneEvent\fR (and +\fBTk_RestrictEvents\fR is called, \fBTcl_DoOneEvent\fR (and hence \fBTk_MainLoop\fR) will filter X input events through \fIproc\fR. \fIProc\fR indicates whether a given event is to be processed immediately, deferred until some later time (e.g. when the event restriction is lifted), or discarded. \fIProc\fR @@ -46,11 +46,11 @@ The \fIarg\fR argument is a copy of the \fIarg\fR passed to \fBTk_RestrictEvents\fR; it may be used to provide \fIproc\fR with information it needs to filter events. The \fIeventPtr\fR points to an event under consideration. \fIProc\fR returns a restrict action (enumerated type \fBTk_RestrictAction\fR) that indicates what -\fBTk_DoOneEvent\fR should do with the event. If the return value is +\fBTcl_DoOneEvent\fR should do with the event. If the return value is \fBTK_PROCESS_EVENT\fR, then the event will be handled immediately. If the return value is \fBTK_DEFER_EVENT\fR, then the event will be left on the event queue for later processing. If the return value is \fBTK_DISCARD_EVENT\fR, then the event will be removed from the event queue and discarded without being processed. @@ -72,8 +72,8 @@ .QW obvious solution in these situations is to call \fBXNextEvent\fR or \fBXWindowEvent\fR, but these procedures cannot be used because Tk keeps its own event queue that is separate from the X event queue. Instead, call \fBTk_RestrictEvents\fR to set up a filter, -then call \fBTk_DoOneEvent\fR to retrieve the desired event(s). +then call \fBTcl_DoOneEvent\fR to retrieve the desired event(s). .SH KEYWORDS delay, event, filter, restriction Index: doc/SetAppName.3 ================================================================== --- doc/SetAppName.3 +++ doc/SetAppName.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetAppName 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_SetAppName \- Set the name of an application for 'send' commands Index: doc/SetCaret.3 ================================================================== --- doc/SetCaret.3 +++ doc/SetCaret.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2002 ActiveState Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetCaretPos 3 8.4 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_SetCaretPos \- set the display caret location Index: doc/SetClass.3 ================================================================== --- doc/SetClass.3 +++ doc/SetClass.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetClass 3 "" Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_SetClass, Tk_Class \- set or retrieve a window's class Index: doc/SetClassProcs.3 ================================================================== --- doc/SetClassProcs.3 +++ doc/SetClassProcs.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetClassProcs 3 8.4 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_SetClassProcs \- register widget specific procedures @@ -31,11 +31,11 @@ are used as callbacks in different places. .PP The structure pointed to by \fIprocs\fR contains the following: .CS typedef struct Tk_ClassProcs { - unsigned int \fIsize\fR; + size_t \fIsize\fR; Tk_ClassWorldChangedProc *\fIworldChangedProc\fR; Tk_ClassCreateProc *\fIcreateProc\fR; Tk_ClassModalProc *\fImodalProc\fR; } \fBTk_ClassProcs\fR; .CE Index: doc/SetGrid.3 ================================================================== --- doc/SetGrid.3 +++ doc/SetGrid.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetGrid 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_SetGrid, Tk_UnsetGrid \- control the grid for interactive resizing Index: doc/SetOptions.3 ================================================================== --- doc/SetOptions.3 +++ doc/SetOptions.3 @@ -1,16 +1,16 @@ '\" '\" Copyright (c) 1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetOptions 3 8.1 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME -Tk_CreateOptionTable, Tk_DeleteOptionTable, Tk_InitOptions, Tk_SetOptions, Tk_FreeSavedOptions, Tk_RestoreSavedOptions, Tk_GetOptionValue, Tk_GetOptionInfo, Tk_FreeConfigOptions, Tk_Offset \- process configuration options +Tk_CreateOptionTable, Tk_DeleteOptionTable, Tk_InitOptions, Tk_SetOptions, Tk_FreeSavedOptions, Tk_RestoreSavedOptions, Tk_GetOptionValue, Tk_GetOptionInfo, Tk_FreeConfigOptions \- process configuration options .SH SYNOPSIS .nf \fB#include \fR .sp Tk_OptionTable @@ -33,13 +33,10 @@ .sp Tcl_Obj * \fBTk_GetOptionInfo(\fIinterp, recordPtr, optionTable, namePtr, tkwin\fB)\fR .sp \fBTk_FreeConfigOptions(\fIrecordPtr, optionTable, tkwin\fB)\fR -.sp -int -\fBTk_Offset(\fItype, field\fB)\fR .SH ARGUMENTS .AS Tk_SavedOptions "*const objv[]" in/out .AP Tcl_Interp *interp in A Tcl interpreter. Most procedures use this only for returning error messages; if it is NULL then no error messages are returned. For @@ -50,11 +47,11 @@ options that are supported. Used to build a Tk_OptionTable. The information pointed to by this argument must exist for the lifetime of the Tk_OptionTable. .AP Tk_OptionTable optionTable in Token for an option table. Must have been returned by a previous call to \fBTk_CreateOptionTable\fR. -.AP char *recordPtr in/out +.AP void *recordPtr in/out Points to structure in which values of configuration options are stored; fields of this record are modified by procedures such as \fBTk_SetOptions\fR and read by procedures such as \fBTk_GetOptionValue\fR. .AP Tk_Window tkwin in For options such as \fBTK_OPTION_COLOR\fR, this argument indicates @@ -237,16 +234,10 @@ \fIinterp\fR is NULL. .PP \fBTk_FreeConfigOptions\fR must be invoked when a widget is deleted. It frees all of the resources associated with any of the configuration options defined in \fIrecordPtr\fR by \fIoptionTable\fR. -.PP -The \fBTk_Offset\fR macro is provided as a safe way of generating the -\fIobjOffset\fR and \fIinternalOffset\fR values for entries in -Tk_OptionSpec structures. It takes two arguments: the name of a type -of record, and the name of a field in that record. It returns the byte -offset of the named field in records of the given type. .SH "TEMPLATES" .PP The array of Tk_OptionSpec structures passed to \fBTk_CreateOptionTable\fR via its \fItemplatePtr\fR argument describes the configuration options supported by a particular class of widgets. Each structure specifies @@ -256,12 +247,12 @@ Tk_OptionType \fItype\fR; const char *\fIoptionName\fR; const char *\fIdbName\fR; const char *\fIdbClass\fR; const char *\fIdefValue\fR; - int \fIobjOffset\fR; - int \fIinternalOffset\fR; + size_t \fIobjOffset\fR; + size_t \fIinternalOffset\fR; int \fIflags\fR; const void *\fIclientData\fR; int \fItypeMask\fR; } \fBTk_OptionSpec\fR; .CE @@ -279,11 +270,11 @@ specifies a default value for this configuration option if no value is specified in the option database. The \fIobjOffset\fR and \fIinternalOffset\fR fields indicate where to store the value of this option in widget records (more on this below); values for the \fIobjOffset\fR and \fIinternalOffset\fR fields should always be generated with the -\fBTk_Offset\fR macro. +\fBoffsetof\fR macro. The \fIflags\fR field contains additional information to control the processing of this configuration option (see below for details). \fIClientData\fR provides additional type-specific data needed by certain types. For instance, for \fBTK_OPTION_COLOR\fR types, Index: doc/SetVisual.3 ================================================================== --- doc/SetVisual.3 +++ doc/SetVisual.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_SetWindowVisual 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_SetWindowVisual \- change visual characteristics of window Index: doc/StrictMotif.3 ================================================================== --- doc/StrictMotif.3 +++ doc/StrictMotif.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_StrictMotif 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_StrictMotif \- Return value of tk_strictMotif variable Index: doc/TkInitStubs.3 ================================================================== --- doc/TkInitStubs.3 +++ doc/TkInitStubs.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_InitStubs 3 8.4 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_InitStubs \- initialize the Tk stubs mechanism Index: doc/Tk_Init.3 ================================================================== --- doc/Tk_Init.3 +++ doc/Tk_Init.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_Init 3 8.0 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_Init, Tk_SafeInit \- add Tk to an interpreter and make a new Tk application. Index: doc/bell.n ================================================================== --- doc/bell.n +++ doc/bell.n @@ -3,11 +3,11 @@ '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH bell n 8.4 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/bind.n ================================================================== --- doc/bind.n +++ doc/bind.n @@ -3,11 +3,11 @@ '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 1998 by Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH bind n 8.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -350,11 +350,11 @@ .RE .SS "EVENT DETAILS" .PP The last part of a long event specification is \fIdetail\fR. In the case of a \fBButtonPress\fR or \fBButtonRelease\fR event, it is the -number of a button (1\-5). If a button number is given, then only an +number of a button (1\-9). If a button number is given, then only an event on that particular button will match; if no button number is given, then an event on any button will match. Note: giving a specific button number is different than specifying a button modifier; in the first case, it refers to a button being pressed or released, while in the second it refers to some other button that is already @@ -564,12 +564,12 @@ .IP "\fB%X\fR, \fB%Y\fR" 5 The \fIx_root\fR and \fIy_root\fR fields from the event. If a virtual-root window manager is being used then the substituted values are the corresponding x-coordinate and y-coordinate in the virtual root. Valid only for -\fBButtonPress\fR, \fBButtonRelease\fR, \fBKeyPress\fR, \fBKeyRelease\fR, -and \fBMotion\fR events. +\fBButtonPress\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR, +\fBKeyRelease\fR, \fBLeave\fR and \fBMotion\fR events. Same meaning as \fB%x\fR and \fB%y\fR, except relative to the (virtual) root window. .LP The replacement string for a %-replacement is formatted as a proper Tcl list element. @@ -631,12 +631,13 @@ .RS .IP (a) an event pattern that specifies a specific button or key is more specific than one that does not; .IP (b) -a longer sequence (in terms of number -of events matched) is more specific than a shorter sequence; +a sequence with the most highest-ordered patterns (in term of highest +repetition count) is more specific than a sequence with less +highest-ordered patterns; .IP (c) if the modifiers specified in one pattern are a subset of the modifiers in another pattern, then the pattern with more modifiers is more specific; .IP (d) Index: doc/bindtags.n ================================================================== --- doc/bindtags.n +++ doc/bindtags.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH bindtags n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/bitmap.n ================================================================== --- doc/bitmap.n +++ doc/bitmap.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH bitmap n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/busy.n ================================================================== --- doc/busy.n +++ doc/busy.n @@ -26,13 +26,15 @@ .TH busy n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME -busy \- confine pointer events to a window sub-tree +busy \- Make Tk widgets busy, temporarily blocking user interactions .SH SYNOPSIS \fBtk busy\fR \fIwindow \fR?\fIoptions\fR? +.sp +\fBtk busy busywindow \fIwindow\fR .sp \fBtk busy hold\fR \fIwindow \fR?\fIoptions\fR? .sp \fBtk busy configure \fIwindow\fR ?\fIoption value\fR?... .sp @@ -42,12 +44,12 @@ .sp \fBtk busy status \fIwindow\fR .BE .SH DESCRIPTION .PP -The \fBtk busy\fR command provides a simple means to block pointer events from -Tk widgets, while overriding the widget's cursor with a configurable busy +The \fBtk busy\fR command provides a simple means to block mouse pointer events +from Tk widgets, while overriding the widget's cursor with a configurable busy cursor. Note this command does not prevent keyboard events from being sent to the widgets made busy. .SH INTRODUCTION .PP There are many times in applications where you want to temporarily restrict @@ -126,28 +128,15 @@ .TP \fBtk busy \fIwindow\fR ?\fIoption value\fR?... . Shortcut for \fBtk busy hold\fR command. .TP -\fBtk busy hold \fIwindow\fR ?\fIoption value\fR?... -. -Makes the specified \fIwindow\fR (and its descendants in the Tk window -hierarchy) appear busy. \fIWindow\fR must be a valid path name of a Tk widget. -A transparent window is put in front of the specified window. This transparent -window is mapped the next time idle tasks are processed, and the specified -window and its descendants will be blocked from user interactions. Normally -\fBupdate\fR should be called immediately afterward to insure that the hold -operation is in effect before the application starts its processing. The -following configuration options are valid: -.RS -.TP -\fB\-cursor \fIcursorName\fR -. -Specifies the cursor to be displayed when the widget is made busy. -\fICursorName\fR can be in any form accepted by \fBTk_GetCursor\fR. The -default cursor is \fBwait\fR on Windows and \fBwatch\fR on other platforms. -.RE +\fBtk busy busywindow \fIwindow\fR +. +Returns the pathname of the busy window (i.e. the transparent window +shielding the window appearing busy) created by the \fBtk busy hold\fR +command for \fIwindow\fR, or the empty string if \fIwindow\fR is not busy. .TP \fBtk busy cget \fIwindow\fR \fIoption\fR . Queries the \fBtk busy\fR command configuration options for \fIwindow\fR. \fIWindow\fR must be the path name of a widget previously made busy by the @@ -178,24 +167,45 @@ .CS option add *frame.busyCursor gumby option add *Frame.BusyCursor gumby .CE .RE +.TP +\fBtk busy current \fR?\fIpattern\fR? +. +Returns the pathnames of all widgets that are currently busy. If a +\fIpattern\fR is given, only the path names of busy widgets matching +\fIpattern\fR are returned. .TP \fBtk busy forget \fIwindow\fR ?\fIwindow\fR?... . Releases resources allocated by the \fBtk busy\fR command for \fIwindow\fR, including the transparent window. User events will again be received by \fIwindow\fR. Resources are also released when \fIwindow\fR is destroyed. \fIWindow\fR must be the name of a widget specified in the \fBhold\fR operation, otherwise an error is reported. .TP -\fBtk busy current \fR?\fIpattern\fR? +\fBtk busy hold \fIwindow\fR ?\fIoption value\fR?... +. +Makes the specified \fIwindow\fR (and its descendants in the Tk window +hierarchy) appear busy. \fIWindow\fR must be a valid path name of a Tk widget. +A transparent window is put in front of the specified window. This transparent +window is mapped the next time idle tasks are processed, and the specified +window and its descendants will be blocked from user interactions. Normally +\fBupdate\fR should be called immediately afterward to insure that the hold +operation is in effect before the application starts its processing. The +command returns the pathname of the busy window that was created (i.e. the +transparent window shielding the window appearing busy). The following +configuration options are valid: +.RS +.TP +\fB\-cursor \fIcursorName\fR . -Returns the pathnames of all widgets that are currently busy. If a -\fIpattern\fR is given, only the path names of busy widgets matching -\fIpattern\fR are returned. +Specifies the cursor to be displayed when the widget is made busy. +\fICursorName\fR can be in any form accepted by \fBTk_GetCursor\fR. The +default cursor is \fBwait\fR on Windows and \fBwatch\fR on other platforms. +.RE .TP \fBtk busy status \fIwindow\fR . Returns the status of a widget \fIwindow\fR. If \fIwindow\fR presently can not receive user interactions, \fB1\fR is returned, otherwise \fB0\fR. @@ -204,36 +214,22 @@ .PP The event blocking feature is implemented by creating and mapping a transparent window that completely covers the widget. When the busy window is mapped, it invisibly shields the widget and its hierarchy from all events that may be sent. Like Tk widgets, busy windows have widget names in the Tk window -hierarchy. This means that you can use the \fBbind\fR command, to handle -events in the busy window. +hierarchy. This means that you can use the \fBbind\fR command to handle +events in the busy window: .PP .CS \fBtk busy\fR hold .frame.canvas -bind .frame.canvas_Busy { ... } +bind [\fBtk busy\fR busywindow .frame.canvas] { ... } .CE .PP -Normally the busy window is a sibling of the widget. The name of the busy -window is -.QW \fIwidget\fB_Busy\fR -where \fIwidget\fR is the name of the widget to be made busy. In the previous -example, the pathname of the busy window is -.QW \fB.frame.canvas_Busy\fR . -The exception is when the widget is a toplevel widget (such as -.QW . ) -where the busy window can't be made a sibling. The busy window is then a child -of the widget named -.QW \fIwidget\fB._Busy\fR -where \fIwidget\fR is the name of the toplevel widget. In the following -example, the pathname of the busy window is -.QW \fB._Busy\fR . -.PP +or .CS -\fBtk busy\fR hold . -bind ._Busy { ... } +set busyWin [\fBtk busy\fR hold .frame.canvas] +bind $busyWin { ... } .CE .SS "ENTER/LEAVE EVENTS" .PP Mapping and unmapping busy windows generates Enter/Leave events for all widgets they cover. Please note this if you are tracking Enter/Leave events in Index: doc/canvas.n ================================================================== --- doc/canvas.n +++ doc/canvas.n @@ -218,12 +218,16 @@ \fBxview\fR and \fByview\fR widget commands; this is typically used for scrolling. Canvases do not support scaling or rotation of the canvas coordinate system relative to the window coordinate system. .PP -Individual items may be moved or scaled using widget commands -described below, but they may not be rotated. +Individual items may be moved, scaled +.VS "8.7, TIP164" +or rotated +.VE "8.7, TIP164" +using widget commands +described below. .PP Note that the default origin of the canvas's visible area is coincident with the origin for the whole window as that makes bindings using the mouse position easier to work with; you only need to use the \fBcanvasx\fR and \fBcanvasy\fR widget commands if you adjust the @@ -311,10 +315,11 @@ 5 possible characters .QW "\fB.,-_ \fR" . The space can be used to enlarge the space between other line elements, and cannot occur as the first position in the string. Some examples: +.PP .CS \-dash . \(-> \-dash {2 4} \-dash - \(-> \-dash {6 4} \-dash -. \(-> \-dash {6 4 2 4} \-dash -.. \(-> \-dash {6 4 2 4 2 4} @@ -655,19 +660,32 @@ Note: the insertion cursor is only displayed in an item if that item currently has the keyboard focus (see the \fBfocus\fR widget command, above), but the cursor position may be set even when the item does not have the focus. This command returns an empty string. +.TP +\fIpathName \fBimage \fIimagename\fR ?\fIsubsample\fR? ?\fIzoom\fR? +. +Draw the canvas into the Tk photo image named \fIimagename\fR. If a \fB-scrollregion\fR +has been defined then this will be the boundaries of the canvas region drawn and the +final size of the photo image. Otherwise the widget width and height with an origin +of 0,0 will be the size of the canvas region drawn and the final size of the photo +image. Optionally an integer \fIsubsample\fR factor may be given and the photo image +will be reduced in size. In addition to the \fIsubsample\fR an integer \fIzoom\fR +factor can also be given and the photo image will be enlarged. The image background +will be filled with the canvas background colour. The canvas widget does not need to +be mapped for this widget command to work, but at least one of it's ancestors must be +mapped. +This command returns an empty string. .TP \fIpathName \fBimove \fItagOrId index x y\fR -.VS 8.6 +. This command causes the \fIindex\fR'th coordinate of each of the items indicated by \fItagOrId\fR to be relocated to the location (\fIx\fR,\fIy\fR). Each item interprets \fIindex\fR independently according to the rules described in \fBINDICES\fR above. Out of the standard set of items, only line and polygon items may have their coordinates relocated this way. -.VE 8.6 .TP \fIpathName \fBindex \fItagOrId index\fR . This command returns a decimal string giving the numerical index within \fItagOrId\fR corresponding to \fIindex\fR. @@ -749,20 +767,19 @@ associated with the item and \fIyAmount\fR to the y-coordinate of each point associated with the item. This command returns an empty string. .TP \fIpathName \fBmoveto \fItagOrId xPos yPos\fR -.VS 8.6 +. Move the items given by \fItagOrId\fR in the canvas coordinate space so that the first coordinate pair of the bottommost item with tag \fItagOrId\fR is located at position (\fIxPos\fR,\fIyPos\fR). \fIxPos\fR and \fIyPos\fR may be the empty string, in which case the corresponding coordinate will be unchanged. All items matching \fItagOrId\fR remain in the same positions relative to each other. This command returns an empty string. -.VE 8.6 .TP \fIpathName \fBpostscript \fR?\fIoption value option value ...\fR? . Generate a Postscript representation for part or all of the canvas. If the \fB\-file\fR option is specified then the Postscript is written @@ -944,20 +961,40 @@ determined by the \fBraise\fR command and \fBlower\fR command, not the \fBraise\fR widget command and \fBlower\fR widget command for canvases. .RE .TP \fIpathName \fBrchars \fItagOrId first last string\fR -.VS 8.6 +. This command causes the text or coordinates between \fIfirst\fR and \fIlast\fR for each of the items indicated by \fItagOrId\fR to be replaced by \fIstring\fR. Each item interprets \fIfirst\fR and \fIlast\fR independently according to the rules described in \fBINDICES\fR above. Out of the standard set of items, text items support this operation by altering their text as directed, and line and polygon items support this operation by altering their coordinate list (in which case \fIstring\fR should be a list of coordinates to use as a replacement). The other items ignore this operation. -.VE 8.6 +.TP +\fIpathName \fBrotate \fItagOrId xOrigin yOrigin angle\fR +.VS "8.7, TIP164" +Rotate the coordinates of all of the items given by \fItagOrId\fR in canvas +coordinate space. +\fIXOrigin\fR and \fIyOrigin\fR identify the origin for the rotation +operation and \fIangle\fR identifies the amount to rotate the coordinates +anticlockwise, in degrees. (Negative values rotate clockwise.) +This command returns an empty string. +.RS +.PP +Implementation note: not all item types work the same with rotations. In +particular,\fB bitmap\fR,\fB image\fR,\fB text\fR and\fB window\fR items only +rotate their anchor points and do not rotate the items themselves about those +points, and the \fBarc\fR, \fBoval\fR and \fBrectangle\fR types rotate about a +computed center point instead of moving the bounding box coordinates directly. +.PP +Some items (currently \fBarc\fR and\fB text\fR) have angles in their options; +this command \fIdoes not\fR affect those options. +.RE +.VE "8.7, TIP164" .TP \fIpathName \fBscale \fItagOrId xOrigin yOrigin xScale yScale\fR . Rescale the coordinates of all of the items given by \fItagOrId\fR in canvas coordinate space. @@ -1108,20 +1145,20 @@ \fIpathName \fBxview scroll \fInumber what\fR . This command shifts the view in the window left or right according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation of one of these. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right in units -of the \fBxScrollIncrement\fR option, if it is greater than zero, -or in units of one-tenth the window's width otherwise. If \fIwhat is \fBpages\fR then the view adjusts in units of nine-tenths the window's width. If \fInumber\fR is negative then information farther to the left becomes visible; if it is positive then information farther to the right becomes visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right in units +of the \fBxScrollIncrement\fR option, if it is greater than zero, +or in units of one-tenth the window's width otherwise. .RE .TP \fIpathName \fByview \fI?args\fR? . This command is used to query and change the vertical position of the @@ -1149,19 +1186,19 @@ \fIpathName \fByview scroll \fInumber what\fR . This command adjusts the view in the window up or down according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. -If \fIwhat\fR is \fBunits\fR, the view adjusts up or down in units -of the \fByScrollIncrement\fR option, if it is greater than zero, -or in units of one-tenth the window's height otherwise. +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR. If \fIwhat\fR is \fBpages\fR then the view adjusts in units of nine-tenths the window's height. If \fInumber\fR is negative then higher information becomes visible; if it is positive then lower information becomes visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts up or down in units +of the \fByScrollIncrement\fR option, if it is greater than zero, +or in units of one-tenth the window's height otherwise. .RE .SH "OVERVIEW OF ITEM TYPES" .PP The sections below describe the various types of items supported by canvas widgets. Each item type is characterized by two things: @@ -1321,20 +1358,22 @@ .SH "STANDARD ITEM TYPES" .SS "ARC ITEMS" .PP Items of type \fBarc\fR appear on the display as arc-shaped regions. An arc is a section of an oval delimited by two angles (specified -by the \fB\-start\fR and \fB\-extent\fR options) and displayed in -one of several ways (specified by the \fB\-style\fR option). +by either the \fB\-start\fR and \fB\-extent\fR options or the \fB\-height\fR option) +and displayed in one of several ways (specified by the \fB\-style\fR option). Arcs are created with widget commands of the following form: .CS \fIpathName \fBcreate arc \fIx1 y1 x2 y2 \fR?\fIoption value ...\fR? \fIpathName \fBcreate arc \fIcoordList\fR ?\fIoption value ...\fR? .CE The arguments \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR or \fIcoordList\fR give the coordinates of two diagonally opposite corners of a -rectangular region enclosing the oval that defines the arc. +rectangular region enclosing the oval that defines the arc (except when +\fB\-height\fR is specified - see below). +. After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR pairs, each of which sets one of the configuration options for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be used in \fBitemconfigure\fR widget commands to change the item's configuration. An arc item becomes the current item when the mouse pointer is @@ -1370,10 +1409,38 @@ \fB\-start \fIdegrees\fR Specifies the beginning of the angular range occupied by the arc. \fIDegrees\fR is given in units of degrees measured counter-clockwise from the 3-o'clock position; it may be either positive or negative. +.TP +\fB\-height \fIdistance\fR +Provides a shortcut for creating a circular arc segment by defining the +distance of the mid-point of the arc from its chord. When this option +is used the coordinates are interpreted as the start and end coordinates +of the chord, and the options \fB\-start\fR and \fB-extent\fR are ignored. +The value of \fIdistance\fR has the following meaning: +.RS +.PP +.RS +\fIdistance\fR > 0 creates a clockwise arc +.br +\fIdistance\fR < 0 creates an counter-clockwise arc +.br +\fIdistance\fR = 0 creates an arc as if this option had not been specified +.RE +.PP +If you want the arc to have a specific radius, \fIr\fR, use the formula: +.PP +.RS +\fIdistance\fR = \fIr\fR \(+- sqrt(\fIr\fR**2 - (chordLength / 2)**2) +.RE +.PP +choosing the minus sign for the minor arc and the plus sign for the major arc. +.PP +Note that \fBitemcget \-height\fR always returns 0 so that introspection code +can be kept simple. +.RE .TP \fB\-style \fItype\fR Specifies how to draw the arc. If \fItype\fR is \fBpieslice\fR (the default) then the arc's region is defined by a section of the oval's perimeter plus two line segments, one between the center @@ -1787,17 +1854,16 @@ \fB\-tags\fR .DE The following extra options are supported for text items: .TP \fB\-angle \fIrotationDegrees\fR -.VS 8.6 +. \fIRotationDegrees\fR tells how many degrees to rotate the text anticlockwise about the positioning point for the text; it may have any floating-point value from 0.0 to 360.0. For example, if \fIrotationDegrees\fR is \fB90\fR, then the text will be drawn vertically from bottom to top. This option defaults to \fB0.0\fR. -.VE 8.6 .TP \fB\-font \fIfontName\fR Specifies the font to use for the text item. \fIFontName\fR may be any string acceptable to \fBTk_GetFont\fR. If this option is not specified, it defaults to a system-dependent Index: doc/chooseColor.n ================================================================== --- doc/chooseColor.n +++ doc/chooseColor.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_chooseColor n 4.2 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/colors.n ================================================================== --- doc/colors.n +++ doc/colors.n @@ -782,13 +782,14 @@ .DE .SH "PORTABILITY ISSUES" .TP \fBMac OS X\fR . -On Mac OS X, the following additional system colors are available -(note that the actual color values depend on the currently active OS theme, -and typically many of these will in fact be patterns rather than pure colors): +On macOS, the following additional system colors are available. +This first group contains all colors available in the HIToolbox library. +(Note that in some cases the actual color values may depend on the +current Appearance.) .RS .DS systemActiveAreaFill systemAlertActiveText systemAlertBackgroundActive @@ -898,10 +899,11 @@ systemRootMenuSelectedText systemScrollBarDelimiterActive systemScrollBarDelimiterInactive systemSecondaryGroupBoxBackground systemSecondaryHighlightColor +systemSelectedTabTextColor systemSheetBackground systemSheetBackgroundOpaque systemSheetBackgroundTransparent systemStaticAreaFill systemSystemDetailText @@ -923,11 +925,44 @@ systemWindowHeaderActiveText systemWindowHeaderBackground systemWindowHeaderInactiveText .DE .RE +. +The second group of MacOS colors below are based on Apple's "semantic" +NScolors. On OSX 10.14 (Mojave) and later these colors change value +when Dark Mode is enabled. However, the change is only observable +when the Apple window manager is drawing to the screen. So the +\fBwinfo rgb\fR command will return the color coordinates used in the +standard Aqua mode, even if Dark Mode has been selected in the system +preferences. The numbered systemWindowBackgroundColors are used in +the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets to provide a +contrasting background. Each numbered color constrasts with its +predecessor. +.RS +.DS +systemControlAccentColor +systemControlTextColor +systemDisabledControlTextColor +systemLabelColor +systemSelectedTextBackgroundColor +systemSelectedTextColor +systemTextBackgroundColor +systemTextColor +systemWindowBackgroundColor +systemWindowBackgroundColor1 +systemWindowBackgroundColor2 +systemWindowBackgroundColor3 +systemWindowBackgroundColor4 +systemWindowBackgroundColor5 +systemWindowBackgroundColor6 +systemWindowBackgroundColor7 +.DE +.RE .TP + + \fBWindows\fR . On Windows, the following additional system colors are available (note that the actual color values depend on the currently active OS theme): .RS Index: doc/console.n ================================================================== --- doc/console.n +++ doc/console.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2001 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH console n 8.4 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/cursors.n ================================================================== --- doc/cursors.n +++ doc/cursors.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. -'\" +'\" '\" Copyright (c) 2006-2007 Daniel A. Steffen -'\" +'\" .TH cursors n 8.3 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/destroy.n ================================================================== --- doc/destroy.n +++ doc/destroy.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH destroy n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/dialog.n ================================================================== --- doc/dialog.n +++ doc/dialog.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_dialog n 4.1 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/entry.n ================================================================== --- doc/entry.n +++ doc/entry.n @@ -3,11 +3,11 @@ '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 1998-2000 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH entry n 8.3 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -21,10 +21,11 @@ \-exportselection \-insertofftime \-takefocus \-font \-insertontime \-textvariable \-foreground \-insertwidth \-xscrollcommand \-highlightbackground \-justify \-highlightcolor \-relief +\-placeholder \-placeholderforeground .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-disabledbackground disabledBackground DisabledBackground Specifies the background color to use when the entry is disabled. If this option is the empty string, the normal background color is used. @@ -401,18 +402,18 @@ .TP \fIpathName \fBxview scroll \fInumber what\fR This command shifts the view in the window left or right according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation of one of these. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by -\fInumber\fR average-width characters on the display; if it is -\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. -If \fInumber\fR is negative then characters farther to the left -become visible; if it is positive then characters farther to the right +If \fIwhat\fR is \fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then characters farther to the left become +visible; if it is positive then characters farther to the right become visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR average-width characters on the display. .RE .SH "DEFAULT BINDINGS" .PP Tk automatically creates class bindings for entries that give them the following default behavior. In the descriptions below, Index: doc/focus.n ================================================================== --- doc/focus.n +++ doc/focus.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH focus n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/focusNext.n ================================================================== --- doc/focusNext.n +++ doc/focusNext.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_focusNext n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/fontchooser.n ================================================================== --- doc/fontchooser.n +++ doc/fontchooser.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2008 Daniel A. Steffen '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH fontchooser n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/frame.n ================================================================== --- doc/frame.n +++ doc/frame.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH frame n 8.4 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -23,10 +23,20 @@ This option is the same as the standard \fB\-background\fR option except that its value may also be specified as an empty string. In this case, the widget will display no background or border, and no colors will be consumed from its colormap for its background and border. +.VS "8.7, TIP262" +An empty background will disable drawing the background image. +.OP \-backgroundimage backgroundImage BackgroundImage +This specifies an image to display on the frame's background within +the border of the frame (i.e., the image will be clipped by the +frame's highlight ring and border, if either are present); subwidgets +of the frame will be drawn on top. The image must have been created +with the \fBimage create\fR command. If specified as the empty string, +no image will be displayed. +.VE "8.7, TIP262" .OP \-class class Class Specifies a class for the window. This class will be used when querying the option database for the window's other options, and it will also be used later for other purposes such as bindings. @@ -60,10 +70,19 @@ to zero then the window will not request any size at all. Note that this sets the total height of the frame, any \fB\-borderwidth\fR or similar is not added. Normally \fB\-height\fR should not be used if a propagating geometry manager, such as \fBgrid\fR or \fBpack\fR, is used within the frame since the geometry manager will override the height of the frame. +.OP \-tile tile Tile +.VS "8.7, TIP262" +This specifies how to draw the background image (see +\fB\-backgroundimage\fR) on the frame. +If true (according to \fBTcl_GetBoolean\fR), the image will be tiled +to fill the whole frame, with the origin of the first copy of the +image being the top left of the interior of the frame. +If false (the default), the image will be centered within the frame. +.VE "8.7, TIP262" .OP \-visual visual Visual Specifies visual information for the new window in any of the forms accepted by \fBTk_GetVisual\fR. If this option is not specified, the new window will use the same visual as its parent. @@ -89,33 +108,37 @@ and relief. The \fBframe\fR command returns the path name of the new window. .PP A frame is a simple widget. Its primary purpose is to act as a spacer or container for complex window layouts. The only features -of a frame are its background color and an optional 3-D border to make the +of a frame are its background and an optional 3-D border to make the frame appear raised or sunken. .SH "WIDGET COMMAND" .PP The \fBframe\fR command creates a new Tcl command whose name is the same as the path name of the frame's window. This command may be used to invoke various operations on the widget. It has the following general form: +.PP .CS \fIpathName option \fR?\fIarg arg ...\fR? .CE +.PP \fIPathName\fR is the name of the command, which is the same as the frame widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for frame widgets: .TP \fIpathName \fBcget\fR \fIoption\fR +. Returns the current value of the configuration option given by \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBframe\fR command. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR? +. Query or modify the configuration options of the widget. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for information on the format of this list). If \fIoption\fR is specified with no \fIvalue\fR, then the command returns a list describing the Index: doc/grab.n ================================================================== --- doc/grab.n +++ doc/grab.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH grab n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/grid.n ================================================================== --- doc/grid.n +++ doc/grid.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH grid n 8.5 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -175,11 +175,11 @@ . If a slave's cell is larger than its requested dimensions, this option may be used to position (or stretch) the slave within its cell. \fIStyle\fR is a string that contains zero or more of the characters \fBn\fR, \fBs\fR, \fBe\fR or \fBw\fR. -The string can optionally contains spaces or +The string can optionally contain spaces or commas, but they are ignored. Each letter refers to a side (north, south, east, or west) that the slave will .QW stick to. If both \fBn\fR and \fBs\fR (or \fBe\fR and \fBw\fR) are specified, the slave will be stretched to fill the entire @@ -200,10 +200,18 @@ master and unmaps their windows. The slaves will no longer be managed by the grid geometry manager. The configuration options for that window are forgotten, so that if the slave is managed once more by the grid geometry manager, the initial default settings are used. +.RS +.PP +.VS TIP518 +If the last slave of the master becomes unmanaged, this will also send +the virtual event \fB<>\fR to the master; the master +may choose to resize itself (or otherwise respond) to such a change. +.VE TIP518 +.RE .TP \fBgrid info \fIslave\fR . Returns a list whose elements are the current configuration state of the slave given by \fIslave\fR in the same option-value form that @@ -276,10 +284,18 @@ The slaves will no longer be managed by the grid geometry manager. However, the configuration options for that window are remembered, so that if the slave is managed once more by the grid geometry manager, the previous values are retained. +.RS +.PP +.VS TIP518 +If the last slave of the master becomes unmanaged, this will also send +the virtual event \fB<>\fR to the master; the master +may choose to resize itself (or otherwise respond) to such a change. +.VE TIP518 +.RE .TP \fBgrid size \fImaster\fR . Returns the size of the grid (in columns then rows) for \fImaster\fR. The size is determined either by the \fIslave\fR occupying the largest Index: doc/image.n ================================================================== --- doc/image.n +++ doc/image.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH image n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/label.n ================================================================== --- doc/label.n +++ doc/label.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH label n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/listbox.n ================================================================== --- doc/listbox.n +++ doc/listbox.n @@ -382,19 +382,20 @@ \fIpathName \fBxview scroll \fInumber what\fR . This command shifts the view in the window left or right according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation of one of these. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by -\fInumber\fR character units (the width of the \fB0\fR character) -on the display; if it is \fBpages\fR then the view adjusts by +If \fIwhat\fR is \fBpages\fR then the view adjusts by \fInumber\fR screenfuls. If \fInumber\fR is negative then characters farther to the left become visible; if it is positive then characters farther to the right become visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR character units (the width of the \fB0\fR character) +on the display. .RE .TP \fIpathName \fByview \fR?\fIargs\fR? . This command is used to query and change the vertical position of the @@ -429,17 +430,18 @@ \fIpathName \fByview scroll \fInumber what\fR . This command adjusts the view in the window up or down according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. -If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by -\fInumber\fR lines; if it is \fBpages\fR then +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR. +If \fIwhat\fR is \fBpages\fR then the view adjusts by \fInumber\fR screenfuls. If \fInumber\fR is negative then earlier elements become visible; if it is positive then later elements become visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by +\fInumber\fR lines. .RE .SH "DEFAULT BINDINGS" .PP Tk automatically creates class bindings for listboxes that give them Motif-like behavior. Much of the behavior of a listbox is determined Index: doc/lower.n ================================================================== --- doc/lower.n +++ doc/lower.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH lower n 3.3 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/menu.n ================================================================== --- doc/menu.n +++ doc/menu.n @@ -17,11 +17,11 @@ \fBtk_menuSetFocus\fR \fIpathName\fR .SO \-activebackground \-borderwidth \-foreground \-activeborderwidth \-cursor \-relief \-activeforeground \-disabledforeground \-takefocus -\-background \-font +\-background \-font \-activerelief .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-postcommand postCommand Command If this option is specified then it provides a Tcl command to execute each time the menu is posted. The command is invoked by the \fBpost\fR @@ -32,16 +32,16 @@ .OP \-selectcolor selectColor Background For menu entries that are check buttons or radio buttons, this option specifies the color to display in the indicator when the check button or radio button is selected. .OP \-tearoff tearOff TearOff -This option must have a proper boolean value, which specifies -whether or not the menu should include a tear-off entry at the -top. If so, it will exist as entry 0 of the menu and the other -entries will number starting at 1. The default -menu bindings arrange for the menu to be torn off when the tear-off -entry is invoked. +This option must have a proper boolean value (default is false), +which specifies whether or not the menu should include a tear-off +entry at the top. If so, it will exist as entry 0 of the menu and +the other entries will number starting at 1. The default menu +bindings arrange for the menu to be torn off when the tear-off entry +is invoked. This option is ignored under Aqua/Mac OS X, where menus cannot be torn off. .OP \-tearoffcommand tearOffCommand TearOffCommand If this option has a non-empty value, then it specifies a Tcl command to invoke whenever the menu is torn off. The actual command will @@ -265,11 +265,11 @@ the menu are provided by Mac OS X, and the names of the current toplevels are automatically appended after all the Tk-defined items and a separator. The Window menu on the Mac also allows toggling the window into a fullscreen state, and managing a tabbed window interface (multiple windows grouped into a single window) if supported by that -version of the operating system. +version of the operating system. .PP When Tk sees a .menubar.help menu on the Macintosh, the menu's contents are appended to the standard Help menu of the user's menubar whenever the window's menubar is in front. The first items in the menu are provided by Mac OS X. @@ -468,22 +468,23 @@ command. Otherwise the result is an empty string. Note: invoking a menu entry does not automatically unpost the menu; the default bindings normally take care of this before invoking the \fBinvoke\fR widget command. .TP -\fIpathName \fBpost \fIx y\fR +\fIpathName \fBpost \fIx y\fR ?\fIindex\fR? . Arrange for the menu to be displayed on the screen at the root-window -coordinates given by \fIx\fR and \fIy\fR. These coordinates are -adjusted if necessary to guarantee that the entire menu is visible on -the screen. This command normally returns an empty string. -If the \fB\-postcommand\fR option has been specified, then its value is -executed as a Tcl script before posting the menu and the result of -that script is returned as the result of the \fBpost\fR widget -command. -If an error returns while executing the command, then the error is -returned without posting the menu. +coordinates given by \fIx\fR and \fIy\fR. If an index is specified +the menu will be located so that the entry with that index is +displayed at the point. These coordinates are adjusted if necessary to +guarantee that the entire menu is visible on the screen. This command +normally returns an empty string. If the \fB\-postcommand\fR option +has been specified, then its value is executed as a Tcl script before +posting the menu and the result of that script is returned as the +result of the \fBpost\fR widget command. If an error returns while +executing the command, then the error is returned without posting the +menu. .TP \fIpathName \fBpostcascade \fIindex\fR . Posts the submenu associated with the cascade entry given by \fIindex\fR, and unposts any previously posted submenu. Index: doc/menubar.n ================================================================== --- doc/menubar.n +++ doc/menubar.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_menuBar n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/menubutton.n ================================================================== --- doc/menubutton.n +++ doc/menubutton.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH menubutton n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/message.n ================================================================== --- doc/message.n +++ doc/message.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH message n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/option.n ================================================================== --- doc/option.n +++ doc/option.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH option n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/optionMenu.n ================================================================== --- doc/optionMenu.n +++ doc/optionMenu.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_optionMenu n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/options.n ================================================================== --- doc/options.n +++ doc/options.n @@ -56,10 +56,13 @@ This option is typically only available in widgets displaying more than one element at a time (e.g. menus but not buttons). .OP \-activeforeground activeForeground Background Specifies foreground color to use when drawing active elements. See above for definition of active elements. +.OP \-activerelief activeRelief Relief +Specifies the 3-D effect desired for the active item of the widget. +See the \fB-relief\fR option for details. .OP \-anchor anchor Anchor Specifies how the information in a widget (e.g. text or a bitmap) is to be displayed in the widget. Must be one of the values \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR. @@ -219,10 +222,18 @@ manager can satisfy this request, the widget will end up with extra internal space above and/or below what it displays inside. Most widgets only use this option for padding text: if they are displaying a bitmap or image, then they usually ignore padding options. +.OP \-placeholder placeHolder PlaceHolder +Specifies a help text string to display if no text is otherwise displayed, +that is when the widget is empty. The placeholder text is displayed using +the values of the \fB\-font\fR and \fB\-justify\fR options. +.OP \-placeholderforeground placeholderForeground PlaceholderForeground +Specifies the foreground color to use when the placeholder text is +displayed. If this option is the empty string, the default color gray70 +is used. .OP \-relief relief Relief Specifies the 3-D effect desired for the widget. Acceptable values are \fBraised\fR, \fBsunken\fR, \fBflat\fR, \fBridge\fR, \fBsolid\fR, and \fBgroove\fR. The value Index: doc/pack-old.n ================================================================== --- doc/pack-old.n +++ doc/pack-old.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH pack-old n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/pack.n ================================================================== --- doc/pack.n +++ doc/pack.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH pack n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -127,10 +127,18 @@ .TP \fBpack forget \fIslave \fR?\fIslave ...\fR? Removes each of the \fIslave\fRs from the packing order for its master and unmaps their windows. The slaves will no longer be managed by the packer. +.RS +.PP +.VS TIP518 +If the last slave of the master becomes unmanaged, this will also send +the virtual event \fB<>\fR to the master; the master +may choose to resize itself (or otherwise respond) to such a change. +.VE TIP518 +.RE .TP \fBpack info \fIslave\fR Returns a list whose elements are the current configuration state of the slave given by \fIslave\fR in the same option-value form that might be specified to \fBpack configure\fR. Index: doc/palette.n ================================================================== --- doc/palette.n +++ doc/palette.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_setPalette n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/panedwindow.n ================================================================== --- doc/panedwindow.n +++ doc/panedwindow.n @@ -329,11 +329,11 @@ When a pane is resized from outside (e.g. it is packed to expand and fill, and the containing toplevel is resized), space is added to the final (rightmost or bottommost) pane in the window. .PP Unlike slave windows managed by e.g. pack or grid, the panes managed by a -panedwindow do not change width or height to accomodate changes in the +panedwindow do not change width or height to accommodate changes in the requested widths or heights of the panes, once these have become mapped. Therefore it may be advisable, particularly when creating layouts interactively, to not add a pane to the panedwindow widget until after the geometry requests of that pane has been finalized (i.e., all components of the pane inserted, all options affecting geometry set to their proper Index: doc/photo.n ================================================================== --- doc/photo.n +++ doc/photo.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1994 The Australian National University '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" '\" Author: Paul Mackerras (paulus@cs.anu.edu.au), '\" Department of Computer Science, '\" Australian National University. '\" .TH photo n 4.0 Tk "Tk Built-In Commands" @@ -22,56 +22,62 @@ \fIimageName \fBblank\fR \fIimageName \fBcget \fIoption\fR \fIimageName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? \fIimageName \fBcopy \fIsourceImage\fR ?\fIoption value(s) ...\fR? \fIimageName \fBdata\fR ?\fIoption value(s) ...\fR? -\fIimageName \fBget \fIx y\fR +\fIimageName \fBget \fIx y\fR ?\fIoption\fR? \fIimageName \fBput \fIdata\fR ?\fIoption value(s) ...\fR? \fIimageName \fBread \fIfilename\fR ?\fIoption value(s) ...\fR? \fIimageName \fBredither\fR \fIimageName \fBtransparency \fIsubcommand \fR?\fIarg arg ...\fR? \fIimageName \fBwrite \fIfilename\fR ?\fIoption value(s) ...\fR? .fi .BE .SH DESCRIPTION .PP -A photo is an image whose pixels can display any color or be -transparent. A photo image is stored internally in full color (32 -bits per pixel), and is displayed using dithering if necessary. Image -data for a photo image can be obtained from a file or a string, or it -can be supplied from -C code through a procedural interface. At present, only +A photo is an image whose pixels can display any color with a varying +degree of transparency (the alpha channel). A photo image is stored +internally in full color (32 bits per pixel), and is displayed using +dithering if necessary. Image data for a photo image can be obtained +from a file or a string, or it can be supplied from C code through a +procedural interface. At present, only .VS 8.6 PNG, .VE 8.6 -GIF and PPM/PGM -formats are supported, but an interface exists to allow additional -image file formats to be added easily. A photo image is transparent -in regions where no image data has been supplied -or where it has been set transparent by the \fBtransparency set\fR -subcommand. +GIF and PPM/PGM formats are supported, but an interface exists to +allow additional image file formats to be added easily. A photo image +is (semi)transparent if the image data it was obtained from had +transparency informaton. In regions where no image data has been +supplied, it is fully transparent. Transparency may also be modified +with the \fBtransparency set\fR subcommand. .SH "CREATING PHOTOS" .PP Like all images, photos are created using the \fBimage create\fR command. Photos support the following \fIoptions\fR: .TP \fB\-data \fIstring\fR . -Specifies the contents of the image as a string. The string should -contain binary data or, for some formats, base64-encoded data (this is +Specifies the contents of the image as a string. +.VS 8.7 +The string should +contain data in the default list-of-lists form, +.VE 8.7 +binary data or, for some formats, base64-encoded data (this is currently guaranteed to be supported for PNG and GIF images). The -format of the -string must be one of those for which there is an image file format -handler that will accept string data. If both the \fB\-data\fR -and \fB\-file\fR options are specified, the \fB\-file\fR option takes -precedence. +format of the string must be one of those for which there is an image +file format handler that will accept string data. If both the +\fB\-data\fR and \fB\-file\fR options are specified, the \fB\-file\fR +option takes precedence. .TP -\fB\-format \fIformat-name\fR +\fB\-format\fR {\fIformat-name\fR ?\fIoption value ...\fR?} . Specifies the name of the file format for the data specified with the -\fB\-data\fR or \fB\-file\fR option. +\fB\-data\fR or \fB\-file\fR option and optional arguments passed to +the format handler. Note: the value of this option must be a Tcl list. +This means that the braces may be omitted if the argument has only one +word. Also, instead of braces, double quotes may be used for quoting. .TP \fB\-file \fIname\fR . \fIname\fR gives the name of a file that is to be read to supply data for the photo image. The file format must be one of those for which @@ -231,33 +237,43 @@ \fIoverlay\fR. .RE .TP \fIimageName \fBdata\fR ?\fIoption value(s) ...\fR? . -Returns image data in the form of a string. The following options -may be specified: +Returns image data in the form of a string. +.VS 8.7 +The format of the string depends on the format handler. By default, a +human readable format as a list of lists of pixel data is used, other +formats can be chosen with the \fB-format\fR option. +See \fBIMAGE FORMATS\fR below for details. +.VE 8.7 +The following options may be specified: .RS .TP \fB\-background\fI color\fR . If the color is specified, the data will not contain any transparency information. In all transparent pixels the color will be replaced by the specified color. .TP -\fB\-format\fI format-name\fR -. -Specifies the name of the image file format handler to be used. -Specifically, this subcommand searches -for the first handler whose name matches an initial substring of -\fIformat-name\fR and which has the capability to write a string -containing this image data. -If this option is not given, this subcommand uses a format that -consists of a list (one element per row) of lists (one element per -pixel/column) of colors in +\fB\-format\fR {\fIformat-name\fR ?\fIoption value ...\fR?} +. +Specifies the name of the image file format handler to use and, +optionally, arguments to the format handler. Specifically, this +subcommand searches for the first handler whose name matches an +initial substring of \fIformat-name\fR and which has the capability to +write a string containing this image data. +.VS 8.7 +If this option is not given, this subcommand uses the default format +that consists of a list (one element per row) of lists (one element +per pixel/column) of colors in .QW \fB#\fIrrggbb\fR -format (where \fIrr\fR is a pair of hexadecimal digits for the red -channel, \fIgg\fR for green, and \fIbb\fR for blue). +format (see \fBIMAGE FORMATS\fR below). +.VE 8.7 +Note: the value of this option must be a Tcl list. +This means that the braces may be omitted if the argument has only one +word. Also, instead of braces, double quotes may be used for quoting. .TP \fB\-from \fIx1 y1 x2 y2\fR . Specifies a rectangular region of \fIimageName\fR to be returned. If only \fIx1\fR and \fIy1\fR are specified, the region @@ -270,47 +286,55 @@ \fB\-grayscale\fR . If this options is specified, the data will not contain color information. All pixel data will be transformed into grayscale. .RE +.VS 8.7 .TP -\fIimageName \fBget\fR \fIx y\fR +\fIimageName \fBget\fR \fIx y\fR ?\fB-withalpha\fR? . Returns the color of the pixel at coordinates (\fIx\fR,\fIy\fR) in the image as a list of three integers between 0 and 255, representing the -red, green and blue components respectively. +red, green and blue components respectively. If the \fB-withalpha\fR +option is specified, the returned list will have a fourth element +representing the alpha value of the pixel as an integer between 0 and +255. +.VE 8.7 .TP \fIimageName \fBput\fR \fIdata\fR ?\fIoption value(s) ...\fR? . Sets pixels in \fI imageName\fR to the data specified in \fIdata\fR. -This command first searches the list of image file format handlers for +.VS 8.7 +This command searches the list of image file format handlers for a handler that can interpret the data in \fIdata\fR, and then reads the image encoded within into \fIimageName\fR (the destination image). -If \fIdata\fR does not match any known format, an attempt to interpret -it as a (top-to-bottom) list of scan-lines is made, with each -scan-line being a (left-to-right) list of pixel colors (see -\fBTk_GetColor\fR for a description of valid colors.) Every scan-line -must be of the same length. Note that when \fIdata\fR is a single -color name, you are instructing Tk to fill a rectangular region with -that color. The following options may be specified: +See \fBIMAGE FORMATS\fR below for details on formats for image data. +.VE 8.7 +The following options may be specified: .RS .TP -\fB\-format \fIformat-name\fR +\fB\-format\fR {\fIformat-name\fR ?\fIoption value ..\fR?} . -Specifies the format of the image data in \fIdata\fR. +Specifies the format of the image data in \fIdata\fR and, optionally, +arguments to be passed to the format handler. Specifically, only image file format handlers whose names begin with \fIformat-name\fR will be used while searching for an image data format handler to read the data. +Note: the value of this option must be a Tcl list. +This means that the braces may be omitted if the argument has only one +word. Also, instead of braces, double quotes may be used for quoting. .TP \fB\-to \fIx1 y1\fR ?\fIx2 y2\fR? . Specifies the coordinates of the top-left corner (\fIx1\fR,\fIy1\fR) of the region of \fIimageName\fR into which the image data will be copied. The default position is (0,0). If \fIx2\fR,\fIy2\fR is given and \fIdata\fR is not large enough to cover the rectangle specified by this option, the image data extracted will be tiled so it covers the -entire destination rectangle. Note that if \fIdata\fR specifies a +entire destination rectangle. If the region specified with this opion +is smaller than the supplied \fIdata\fR, the exceeding data is silently +discarded. Note that if \fIdata\fR specifies a single color value, then a region extending to the bottom-right corner represented by (\fIx2\fR,\fIy2\fR) will be filled with that color. .RE .TP \fIimageName \fBread\fR \fIfilename\fR ?\fIoption value(s) ...\fR? @@ -321,16 +345,20 @@ in \fIfilename\fR, and then reads the image in \fIfilename\fR into \fIimageName\fR (the destination image). The following options may be specified: .RS .TP -\fB\-format \fIformat-name\fR +\fB\-format {\fIformat-name\fR ?\fIoption value ..\fR?} . -Specifies the format of the image data in \fIfilename\fR. +Specifies the format of the image data in \fIfilename\fR and, +optionally, additional options to the format handler. Specifically, only image file format handlers whose names begin with \fIformat-name\fR will be used while searching for an image data format handler to read the data. +Note: the value of this option must be a Tcl list. +This means that the braces may be omitted if the argument has only one +word. Also, instead of braces, double quotes may be used for quoting. .TP \fB\-from \fIx1 y1 x2 y2\fR . Specifies a rectangular sub-region of the image file data to be copied to the destination image. If only \fIx1\fR and \fIy1\fR are @@ -369,20 +397,30 @@ \fIimageName \fBtransparency \fIsubcommand \fR?\fIarg arg ...\fR? . Allows examination and manipulation of the transparency information in the photo image. Several subcommands are available: .RS -.TP -\fIimageName \fBtransparency get \fIx y\fR -. -Returns a boolean indicating if the pixel at (\fIx\fR,\fIy\fR) is -transparent. -.TP -\fIimageName \fBtransparency set \fIx y boolean\fR -. -Makes the pixel at (\fIx\fR,\fIy\fR) transparent if \fIboolean\fR is -true, and makes that pixel opaque otherwise. +.VS 8.7 +.TP +\fIimageName \fBtransparency get \fIx y\fR ?\fB-alpha\fR? +. +Returns true if the pixel at (\fIx\fR,\fIy\fR) is fully transparent, +false otherwise. If the option \fB-alpha\fR is passed, returns the +alpha value of the pixel instead, as an integer in the range 0 to 255. +.VE 8.7 + +.VS 8.7 +.TP +\fIimageName \fBtransparency set \fIx y\fR \fInewVal\fR ?\fB-alpha\fR? +. +Change the transparency of the pixel at (\fIx\fR,\fIy\fR) to +\fInewVal.\fR If no additional option is passed, \fInewVal\fR is +interpreted as a boolean and the pixel is made fully transparent if +that value is true, fully opaque otherwise. If the \fB-alpha\fR +option is passed, \fInewVal\fR is interpreted as an integral alpha +value for the pixel, which must be in the range 0 to 255. +.VE 8.7 .RE .TP \fIimageName \fBwrite \fIfilename\fR ?\fIoption value(s) ...\fR? . Writes image data from \fIimageName\fR to a file named \fIfilename\fR. @@ -393,19 +431,23 @@ . If the color is specified, the data will not contain any transparency information. In all transparent pixels the color will be replaced by the specified color. .TP -\fB\-format\fI format-name\fR +\fB\-format\fR {\fIformat-name\fR ?\fIoption value ...\fR?} . Specifies the name of the image file format handler to be used to -write the data to the file. Specifically, this subcommand searches -for the first handler whose name matches an initial substring of -\fIformat-name\fR and which has the capability to write an image -file. If this option is not given, the format is guessed from -the file extension. If that cannot be determined, this subcommand -uses the first handler that has the capability to write an image file. +write the data to the file and, optionally, options to pass to the +format handler. Specifically, this subcommand searches for the first +handler whose name matches an initial substring of \fIformat-name\fR +and which has the capability to write an image file. If this option +is not given, the format is guessed from the file extension. If that +cannot be determined, this subcommand uses the first handler that has +the capability to write an image file. +Note: the value of this option must be a Tcl list. +This means that the braces may be omitted if the argument has only one +word. Also, instead of braces, double quotes may be used for quoting. .TP \fB\-from \fIx1 y1 x2 y2\fR . Specifies a rectangular region of \fIimageName\fR to be written to the image file. If only \fIx1\fR and \fIy1\fR are specified, the region @@ -424,24 +466,28 @@ The photo image code is structured to allow handlers for additional image file formats to be added easily. The photo image code maintains a list of these handlers. Handlers are added to the list by registering them with a call to \fBTk_CreatePhotoImageFormat\fR. The standard Tk distribution comes with handlers for PPM/PGM, PNG and GIF -formats, which are automatically registered on initialization. +formats, +.VS 8.7 +as well as the \fBdefault\fR handler to encode/decode image +data in a human readable form. +.VE 8.7 +These handlers are automatically registered on initialization. .PP -When reading an image file or processing -string data specified with the \fB\-data\fR configuration option, the -photo image code invokes each handler in turn until one is -found that claims to be able to read the data in the file or string. -Usually this will find the correct handler, but if it does not, the -user may give a format name with the \fB\-format\fR option to specify -which handler to use. In fact the photo image code will try those -handlers whose names begin with the string specified for the -\fB\-format\fR option (the comparison is case-insensitive). For -example, if the user specifies \fB\-format gif\fR, then a handler -named GIF87 or GIF89 may be invoked, but a handler -named JPEG may not (assuming that such handlers had been +When reading an image file or processing string data specified with +the \fB\-data\fR configuration option, the photo image code invokes +each handler in turn until one is found that claims to be able to read +the data in the file or string. Usually this will find the correct +handler, but if it does not, the user may give a format name with the +\fB\-format\fR option to specify which handler to use. In this case, +the photo image code will try those handlers whose names begin with +the string specified for the \fB\-format\fR option (the comparison is +case-insensitive). For example, if the user specifies \fB\-format +gif\fR, then a handler named GIF87 or GIF89 may be invoked, but a +handler named JPEG may not (assuming that such handlers had been registered). .PP When writing image data to a file, the processing of the \fB\-format\fR option is slightly different: the string value given for the \fB\-format\fR option must begin with the complete name of the @@ -448,31 +494,166 @@ requested handler, and may contain additional information following that, which the handler can use, for example, to specify which variant to use of the formats supported by the handler. Note that not all image handlers may support writing transparency data to a file, even where the target image format does. +.VS 8.7 +.SS "THE DEFAULT IMAGE HANDLER" +.PP +The \fBdefault\fR image handler cannot be used to read or write data +from/to a file. Its sole purpose is to encode and decode image data in +string form in a clear text, human readable, form. The \fIimageName\fR +\fBdata\fR subcommand uses this handler when no other format is +specified. When reading image data from a string with \fIimageName\fR +\fBput\fR or the \fB-data\fR option, the default handler is treated +as the other handlers. +.PP +Image data in the \fBdefault\fR string format is a (top-to-bottom) +list of scan-lines, with each scan-line being a (left-to-right) list +of pixel data. Every scan-line has the same length. The color +and, optionally, alpha value of each pixel is specified in any of +the forms described in the \fBCOLOR FORMATS\fR section below. +.VE 8.7 + .SS "FORMAT SUBOPTIONS" .PP .VS 8.6 -Some image formats support sub-options, which are specified at the time that -the image is loaded using additional words in the \fB\-format\fR option. At -the time of writing, the following are supported: +Image formats may support sub-options, wich ahre specified using +additional words in the value to the \fB\-format\fR option. These +suboptions can affect how image data is read or written to file or +string. The nature and values of these options is up to the format +handler. +The built-in handlers support these suboptions: +.VS 8.7 +.TP +\fBdefault \-colorformat\fI formatType\fR +. +The option is allowed when writing image data to a string with +\fIimageName\fR \fBdata\fR. Specifies the format to use for the color +string of each pixel. \fIformatType\fR may be one of: \fBrgb\fR to +encode pixel data in the form \fB#\fIRRGGBB\fR, \fBrgba\fR to encode +pixel data in the form \fB#\fIRRGGBBAA\fR or \fBlist\fR to encode +pixel data as a list with four elements. See \fBCOLOR FORMATS\fR +below for details. The default is \fBrgb\fR. +.VE 8.7 .TP \fBgif \-index\fI indexValue\fR . -When parsing a multi-part GIF image, Tk normally only accesses the first -image. By giving the \fB\-index\fR sub-option, the \fIindexValue\fR'th value -may be used instead. The \fIindexValue\fR must be an integer from 0 up to the -number of image parts in the GIF data. +The option has effect when reading image data from a file. When +parsing a multi-part GIF image, Tk normally only accesses the first +image. By giving the \fB\-index\fR sub-option, the \fIindexValue\fR'th +value may be used instead. The \fIindexValue\fR must be an integer +from 0 up to the number of image parts in the GIF data. .TP \fBpng \-alpha\fI alphaValue\fR . -An additional alpha filtering for the overall image, which allows the -background on which the image is displayed to show through. This usually also -has the effect of desaturating the image. The \fIalphaValue\fR must be between -0.0 and 1.0. +The option has effect when reading image data from a file. Specifies +an additional alpha filtering for the overall image, which allows the +background on which the image is displayed to show through. This +usually also has the effect of desaturating the image. The +\fIalphaValue\fR must be between 0.0 and 1.0. +.TP +\fBsvg \-dpi\fI dpiValue\fB \-scale\fI scaleValue\fB \-unit\fI unitValue\fR +. +\fIdpiValue\fR is used in conversion between given coordinates and +screen resolution. The value must be greater than 0 and the default +value is 96. +\fIscaleValue\fR is used to scale the resulting image. The value must +be greater than 0 and the default value is 1. +\fIunitValue\fR is the unit of all coordinates in the SVG data. +Available units are px (default, coordinates in pixel), pt (1/72 inch), +pc (12 pt), mm , cm and in. +The svg format supports a wide range of SVG features, but the +full SVG standard is not available, for instance the 'text' feature +is missing and silently ignores when reading the SVG data. +The supported SVG features are: +. +.RS +\fB elements:\fR g, path, rect, circle, ellipse, line, polyline, polygon, +linearGradient, radialGradient, stop, defs, svg, style +.PP +\fB attributes:\fR width, height, viewBox, +preserveAspectRatio with none, xMin, xMid, xMax, yMin, yMid, yMax, slice +.PP +\fB gradient attributes:\fR gradientUnits with objectBoundingBox, +gradientTransform, cx, cy, r fx, fy x1, y1, x2, y2 +spreadMethod with pad, reflect or repeat, +xlink:href +.PP +\fB poly attributes: \fR points +.PP +\fB line attributes: \fR x1, y1, x2, y2 +.PP +\fB ellipse attributes: \fR cx, cy, rx, ry +.PP +\fB circle attributes: \fR cx, cy, r +.PP +\fB rectangle attributes: \fR x, y, width, height, rx, ry +.PP +\fB path attributes: \fR d with m, M, l, L, h, H, v, V, c, C, s, S, q, Q, t, T, a, A, z, Z +.PP +\fB style attributes: \fR display with none, visibility, hidden, visible, +fill with nonzero and evenodd, opacity, fill-opacity, +stroke, stroke-width, stroke-dasharray, stroke-dashoffset, stroke-opacity, +stroke-linecap with butt, round and square, +stroke-linejoin with miter, round and bevel, stroke-miterlimit +fill-rule, font-size, +transform with matrix, translate, scale, rotate, skewX and skewY, +stop-color, stop-opacity, offset, id, class +.RE +. +Currently only SVG images reading and conversion into (pixel-based +format) photos is supported: Tk does not (yet) support bundling photo +images in SVG vector graphics. .VE 8.6 +.VS 8.7 +.SH "COLOR FORMATS" +.PP +The default image handler can represent/parse color and alpha values +of a pixel in one of the formats listed below. If a color format does +not contain transparency information, full opacity is assumed. The +available color formats are: +.IP \(bu 3 +The empty string - interpreted as full transparency, the color value +is undefined. +.IP \(bu 3 +Any value accepted by \fBTk_GetColor\fR, optionally followed by an +alpha suffix. The alpha suffix may be one of: +.RS +.TP +\fB@\fR\fIA\fR +. +The alpha value \fIA\fR must be a fractional value in the range 0.0 +(fully transparent) to 1.0 (fully opaque). +.TP +\fB#\fR\fIX\fR +. +The alpha value \fIX\fR is a hexadecimal digit that specifies an integer +alpha value in the range 0 (fully transparent) to 255 (fully opaque). +This is expanded in range from 4 bits wide to 8 bits wide by +multiplication by 0x11. +.TP +\fB#\fR\fIXX\fR +. +The alpha value \fIXX\fR is passed as two hexadecimal digits that +specify an integer alpha value in the range 0 (fully transparent) to 255 +(fully opaque). +.RE +.IP \(bu 3 +A Tcl list with three or four integers in the range 0 to 255, +specifying the values for the red, green, blue and (optionally) +alpha channels respectively. +.IP \(bu 3 +\fB#\fR\fIRGBA\fR format: a \fB#\fR followed by four hexadecimal digits, +where each digit is the value for the red, green, blue and alpha +channels respectively. Each digit will be expanded internally to +8 bits by multiplication by 0x11. +.IP \(bu 3 +\fB#\fR\fIRRGGBBAA\fR format: \fB#\fR followed by eight hexadecimal digits, +where each pair of subsequent digits represents the value for the red, +green, blue and alpha channels respectively. +.VE 8.7 .SH "COLOR ALLOCATION" .PP When a photo image is displayed in a window, the photo image code allocates colors to use to display the image and dithers the image, if necessary, to display a reasonable approximation to the image using @@ -532,12 +713,29 @@ \fBimage create photo\fR iconDisabled \-file "icon.png" \e \-format "png \-alpha 0.5" button .b \-image icon \-disabledimage iconDisabled .CE .VE 8.6 +.PP +.VS 8.7 +Create a green box with a simple shadow effect +.PP +.CS +\fBimage create photo\fR foo + +# Make a simple graduated fill varying in alpha for the shadow +for {set i 14} {$i > 0} {incr i -1} { + set i2 [expr {$i + 30}] + foo \fBput\fR [format black#%x [expr {15-$i}]] -to $i $i $i2 $i2 +} + +# Put a solid green rectangle on top +foo \fBput\fR #F080 -to 0 0 30 30 +.VE 8.7 +.CE .SH "SEE ALSO" image(n) .SH KEYWORDS photo, image, color '\" Local Variables: '\" mode: nroff '\" End: Index: doc/place.n ================================================================== --- doc/place.n +++ doc/place.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH place n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/popup.n ================================================================== --- doc/popup.n +++ doc/popup.n @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk_popup n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/raise.n ================================================================== --- doc/raise.n +++ doc/raise.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH raise n 3.3 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/scale.n ================================================================== --- doc/scale.n +++ doc/scale.n @@ -53,11 +53,11 @@ For vertical scales this is the scale's height; for horizontal scales it is the scale's width. .OP \-resolution resolution Resolution A real value specifying the resolution for the scale. If this value is greater than zero then the scale's value will always be -rounded to an even multiple of this value, as will tick marks and +rounded to an even multiple of this value, as will the endpoints of the scale. If the value is less than zero then no rounding occurs. Defaults to 1 (i.e., the value will be integral). .OP \-showvalue showValue ShowValue Specifies a boolean value indicating whether or not the current value of the scale is to be displayed. @@ -76,11 +76,11 @@ If the scale is active, the slider is displayed using the color specified by the \fB\-activebackground\fR option. .OP \-tickinterval tickInterval TickInterval Must be a real value. Determines the spacing between numerical -tick marks displayed below or to the left of the slider. +tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval. If 0, no tick marks will be displayed. .OP \-to to To Specifies a real value corresponding to the right or bottom end of the scale. This value may be either less than or greater than the \fB\-from\fR option. Index: doc/scrollbar.n ================================================================== --- doc/scrollbar.n +++ doc/scrollbar.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH scrollbar n 4.1 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -213,28 +213,28 @@ If \fIfraction\fR is 0 it refers to the beginning of the document. 1.0 refers to the end of the document, 0.333 refers to a point one-third of the way through the document, and so on. .TP -\fIprefix \fBscroll \fInumber \fBunits\fR -. -The widget should adjust its view by \fInumber\fR units. -The units are defined in whatever way makes sense for the widget, -such as characters or lines in a text widget. -\fINumber\fR is either 1, which means one unit should scroll off -the top or left of the window, or \-1, which means that one unit -should scroll off the bottom or right of the window. -.TP \fIprefix \fBscroll \fInumber \fBpages\fR . The widget should adjust its view by \fInumber\fR pages. It is up to the widget to define the meaning of a page; typically it is slightly less than what fits in the window, so that there is a slight overlap between the old and new views. \fINumber\fR is either 1, which means the next page should become visible, or \-1, which means that the previous page should become visible. +.TP +\fIprefix \fBscroll \fInumber \fBunits\fR +. +The widget should adjust its view by \fInumber\fR units. +The units are defined in whatever way makes sense for the widget, +such as characters or lines in a text widget. +\fINumber\fR is either 1, which means one unit should scroll off +the top or left of the window, or \-1, which means that one unit +should scroll off the bottom or right of the window. .SH "OLD COMMAND SYNTAX" .PP In versions of Tk before 4.0, the \fBset\fR and \fBget\fR widget commands used a different form. This form is still supported for backward compatibility, but it Index: doc/send.n ================================================================== --- doc/send.n +++ doc/send.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH send n 4.0 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/spinbox.n ================================================================== --- doc/spinbox.n +++ doc/spinbox.n @@ -2,11 +2,11 @@ '\" Copyright (c) 2000 Jeffrey Hobbs. '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH spinbox n 8.4 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -21,10 +21,11 @@ \-exportselection \-insertwidth \-takefocus \-font \-insertofftime \-textvariable \-foreground \-justify \-xscrollcommand \-highlightbackground \-relief \-highlightcolor \-repeatdelay +\-placeholder \-placeholderforeground .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-buttonbackground buttonBackground Background The background color to be used for the spin buttons. .OP \-buttoncursor buttonCursor Cursor @@ -52,11 +53,12 @@ as it will format a floating-point number. .OP \-from from From A floating-point value corresponding to the lowest value for a spinbox, to be used in conjunction with \fB\-to\fR and \fB\-increment\fR. When all are specified correctly, the spinbox will use these values to control its -contents. This value must be less than the \fB\-to\fR option. +contents. If this value is greater than the \fB\-to\fR option, then +\fB\-from\fR and \fB\-to\fR values are automatically swapped. If \fB\-values\fR is specified, it supersedes this option. .OP "\-invalidcommand or \-invcmd" invalidCommand InvalidCommand Specifies a script to eval when \fB\-validatecommand\fR returns 0. Setting it to an empty string disables this feature (the default). The best use of this option is to set it to \fIbell\fR. See \fBVALIDATION\fR below for @@ -81,11 +83,12 @@ \fB\-disabledforeground\fR and \fB\-disabledbackground\fR options. .OP \-to to To A floating-point value corresponding to the highest value for the spinbox, to be used in conjunction with \fB\-from\fR and \fB\-increment\fR. When all are specified correctly, the spinbox will use these values to control -its contents. This value must be greater than the \fB\-from\fR option. +its contents. If this value is less than the \fB\-from\fR option, then +\fB\-from\fR and \fB\-to\fR values are automatically swapped. If \fB\-values\fR is specified, it supersedes this option. .OP \-validate validate Validate Specifies the mode in which validation should operate: \fBnone\fR, \fBfocus\fR, \fBfocusin\fR, \fBfocusout\fR, \fBkey\fR, or \fBall\fR. It defaults to \fBnone\fR. When you want validation, you must explicitly @@ -466,18 +469,18 @@ .TP \fIpathName \fBxview scroll \fInumber what\fR This command shifts the view in the window left or right according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation of one of these. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by -\fInumber\fR average-width characters on the display; if it is -\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. -If \fInumber\fR is negative then characters farther to the left +If \fIwhat\fR is \fBpages\fR then the view adjusts by \fInumber\fR +screenfuls. If \fInumber\fR is negative then characters farther to the left become visible; if it is positive then characters farther to the right become visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR average-width characters on the display. .RE .SH "DEFAULT BINDINGS" .PP Tk automatically creates class bindings for spinboxes that give them the following default behavior. Index: doc/text.n ================================================================== --- doc/text.n +++ doc/text.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH text n 8.5 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -1307,12 +1307,13 @@ of the widget to \fIboolean\fR. .TP \fIpathName \fBedit redo\fR . When the \fB\-undo\fR option is true, reapplies the last undone edits provided -no other edits were done since then. Generates an error when the redo stack is -empty. Does nothing when the \fB\-undo\fR option is false. +no other edits were done since then, and returns a list of indices indicating +what ranges were changed by the redo operation. Generates an error when the +redo stack is empty. Does nothing when the \fB\-undo\fR option is false. .TP \fIpathName \fBedit reset\fR . Clears the undo and redo stacks. .TP @@ -1321,13 +1322,14 @@ Inserts a separator (boundary) on the undo stack. Does nothing when the \fB\-undo\fR option is false. .TP \fIpathName \fBedit undo\fR . -Undoes the last edit action when the \fB\-undo\fR option is true. An edit -action is defined as all the insert and delete commands that are recorded on -the undo stack in between two separators. Generates an error when the undo +Undoes the last edit action when the \fB\-undo\fR option is true, and returns a +list of indices indicating what ranges were changed by the undo operation. An +edit action is defined as all the insert and delete commands that are recorded +on the undo stack in between two separators. Generates an error when the undo stack is empty. Does nothing when the \fB\-undo\fR option is false. .RE .TP \fIpathName \fBget\fR ?\fB\-displaychars\fR? ?\fB\-\-\fR? \fIindex1\fR ?\fIindex2 ...\fR? . @@ -1926,22 +1928,22 @@ and 1. .TP \fIpathName \fBxview scroll \fInumber what\fR . This command shifts the view in the window left or right according to -\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBunits\fR, \fBpages\fR or -\fBpixels\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then \fInumber\fR -must be an integer, otherwise number may be specified in any of the forms -acceptable to \fBTk_GetPixels\fR, such as +\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBpages\fR, +\fBpixels\fR, or \fBunits\fR. If \fIwhat\fR is \fBpages\fR or +\fBunits\fR then \fInumber\fR must be an integer, otherwise number may be +specified in any of the forms acceptable to \fBTk_GetPixels\fR, such as .QW 2.0c or .QW 1i (the result is rounded to the nearest integer value. If no units are given, -pixels are assumed). If \fIwhat\fR is \fBunits\fR, the view adjusts left or -right by \fInumber\fR average-width characters on the display; if it is -\fBpages\fR then the view adjusts by \fInumber\fR screenfuls; if it is -\fBpixels\fR then the view adjusts by \fInumber\fR pixels. If \fInumber\fR is +pixels are assumed). If \fIwhat\fR is \fBpages\fR then the view adjusts by +\fInumber\fR screenfuls; if it is \fBpixels\fR then the view adjusts by +\fInumber\fR pixels; if it is \fBunits\fR, the view adjusts left or +right by \fInumber\fR average-width characters on the display. If \fInumber\fR is negative then characters farther to the left become visible; if it is positive then characters farther to the right become visible. .RE .TP \fIpathName \fByview \fR?\fIargs\fR? @@ -1974,14 +1976,14 @@ the bottom of the window, and some other pixel is at the top. .TP \fIpathName \fByview scroll \fInumber what\fR . This command adjust the view in the window up or down according to -\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBunits\fR, \fBpages\fR or -\fBpixels\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then \fInumber\fR -must be an integer, otherwise number may be specified in any of the forms -acceptable to \fBTk_GetPixels\fR, such as +\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBpages\fR, +\fBpixels\fR, or \fBunits\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then +\fInumber\fR must be an integer, otherwise number may be specified in any of +the forms acceptable to \fBTk_GetPixels\fR, such as .QW 2.0c or .QW 1i (the result is rounded to the nearest integer value. If no units are given, pixels are assumed). If \fIwhat\fR is \fBunits\fR, the view adjusts up or down @@ -2153,15 +2155,15 @@ insertion cursor without moving the insertion cursor. .IP [29] Meta-backspace and Meta-Delete delete the word to the left of the insertion cursor. .IP [30] +Control-t reverses the order of the two characters to the right of the +insertion cursor. +.IP [31] Control-x deletes whatever is selected in the text widget after copying it to the clipboard. -.IP [31] -Control-t reverses the order of the two characters to the right of the -insertion cursor. .IP [32] Control-z undoes the last edit action if the \fB\-undo\fR option is true. Does nothing otherwise. .IP [33] Control-Z (or Control-y on Windows) reapplies the last undone edit action if Index: doc/tk.n ================================================================== --- doc/tk.n +++ doc/tk.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk n 8.4 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/tk4.0.ps ================================================================== --- doc/tk4.0.ps +++ doc/tk4.0.ps @@ -14,11 +14,11 @@ % This file fixes the problem with NeWS printers dithering color output. % Any questions should be sent to mickey@magickingdom.eng.sun.com % % Known Problems: % Due to bugs in Transcript, the 'PS-Adobe-' is omitted from line 1 -/FMversion (3.0) def +/FMversion (3.0) def % Set up Color vs. Black-and-White /FMPrintInColor { % once-thru loop gimmick % See if we're a NeWSprint printer /currentcanvas where { @@ -36,38 +36,38 @@ systemdict /currentcolortransfer known and exit } loop def % Uncomment the following line to force b&w on color printer % /FMPrintInColor false def -/FrameDict 195 dict def +/FrameDict 195 dict def systemdict /errordict known not {/errordict 10 dict def errordict /rangecheck {stop} put} if % The readline in 23.0 doesn't recognize cr's as nl's on AppleTalk -FrameDict /tmprangecheck errordict /rangecheck get put -errordict /rangecheck {FrameDict /bug true put} put -FrameDict /bug false put -mark +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark % Some PS machines read past the CR, so keep the following 3 lines together! currentfile 5 string readline 00 0000000000 -cleartomark -errordict /rangecheck FrameDict /tmprangecheck get put -FrameDict /bug get { +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { /readline { /gstring exch def /gfile exch def /gindex 0 def { - gfile read pop - dup 10 eq {exit} if - dup 13 eq {exit} if - gstring exch gindex exch put - /gindex gindex 1 add def + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def } loop - pop - gstring 0 gindex getinterval true + pop + gstring 0 gindex getinterval true } def } if /FMVERSION { FMversion ne { /Times-Roman findfont 18 scalefont setfont @@ -74,16 +74,16 @@ 100 100 moveto (FrameMaker version does not match postscript_prolog!) dup = show showpage } if - } def + } def /FMLOCAL { FrameDict begin - 0 def - end - } def + 0 def + end + } def /gstring FMLOCAL /gfile FMLOCAL /gindex FMLOCAL /orgxfer FMLOCAL /orgproc FMLOCAL @@ -92,12 +92,12 @@ /yscale FMLOCAL /xscale FMLOCAL /manualfeed FMLOCAL /paperheight FMLOCAL /paperwidth FMLOCAL -/FMDOCUMENT { - array /FMfonts exch def +/FMDOCUMENT { + array /FMfonts exch def /#copies exch def FrameDict begin 0 ne dup {setmanualfeed} if /manualfeed exch def /paperheight exch def @@ -105,109 +105,109 @@ /yscale exch def /xscale exch def currenttransfer cvlit /orgxfer exch def currentscreen cvlit /orgproc exch def /organgle exch def /orgfreq exch def - setpapername - manualfeed {true} {papersize} ifelse - {manualpapersize} {false} ifelse + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse {desperatepapersize} if - end - } def + end + } def /pagesave FMLOCAL /orgmatrix FMLOCAL /landscape FMLOCAL -/FMBEGINPAGE { - FrameDict begin +/FMBEGINPAGE { + FrameDict begin /pagesave save def 3.86 setmiterlimit /landscape exch 0 ne def - landscape { - 90 rotate 0 exch neg translate pop + landscape { + 90 rotate 0 exch neg translate pop } {pop pop} ifelse xscale yscale scale /orgmatrix matrix def - gsave - } def + gsave + } def /FMENDPAGE { - grestore + grestore pagesave restore - end + end showpage - } def -/FMFONTDEFINE { + } def +/FMFONTDEFINE { FrameDict begin - findfont - ReEncode - 1 index exch - definefont - FMfonts 3 1 roll + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll put - end - } def + end + } def /FMFILLS { FrameDict begin array /fillvals exch def - end - } def + end + } def /FMFILL { FrameDict begin fillvals 3 1 roll put - end - } def -/FMNORMALIZEGRAPHICS { + end + } def +/FMNORMALIZEGRAPHICS { newpath 0.0 0.0 moveto 1 setlinewidth 0 setlinecap 0 0 0 sethsbcolor - 0 setgray + 0 setgray } bind def /fx FMLOCAL /fy FMLOCAL /fh FMLOCAL /fw FMLOCAL /llx FMLOCAL /lly FMLOCAL /urx FMLOCAL /ury FMLOCAL -/FMBEGINEPSF { - end - /FMEPSF save def - /showpage {} def - FMNORMALIZEGRAPHICS - [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall - fx fy translate +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fy translate rotate - fw urx llx sub div fh ury lly sub div scale - llx neg lly neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate } bind def /FMENDEPSF { FMEPSF restore - FrameDict begin + FrameDict begin } bind def -FrameDict begin +FrameDict begin /setmanualfeed { %%BeginFeature *ManualFeed True statusdict /manualfeed true put %%EndFeature } def /max {2 copy lt {exch} if pop} bind def /min {2 copy gt {exch} if pop} bind def /inch {72 mul} def -/pagedimen { - paperheight sub abs 16 lt exch +/pagedimen { + paperheight sub abs 16 lt exch paperwidth sub abs 16 lt and {/papername exch def} {pop} ifelse } def /papersizedict FMLOCAL -/setpapername { - /papersizedict 14 dict def +/setpapername { + /papersizedict 14 dict def papersizedict begin - /papername /unknown def + /papername /unknown def /Letter 8.5 inch 11.0 inch pagedimen /LetterSmall 7.68 inch 10.16 inch pagedimen /Tabloid 11.0 inch 17.0 inch pagedimen /Ledger 17.0 inch 11.0 inch pagedimen /Legal 8.5 inch 14.0 inch pagedimen @@ -235,13 +235,13 @@ /B4 {b4tray b4} def /B5 {b5tray b5} def /unknown {unknown} def papersizedict dup papername known {papername} {/unknown} ifelse get end - /FMdicttop countdictstack 1 add def - statusdict begin stopped end - countdictstack -1 FMdicttop {pop end} for + /FMdicttop countdictstack 1 add def + statusdict begin stopped end + countdictstack -1 FMdicttop {pop end} for } def /manualpapersize { papersizedict begin /Letter {letter} def /LetterSmall {lettersmall} def @@ -256,18 +256,18 @@ /B4 {b4} def /B5 {b5} def /unknown {unknown} def papersizedict dup papername known {papername} {/unknown} ifelse get end - stopped + stopped } def /desperatepapersize { statusdict /setpageparams known { - paperwidth paperheight 0 1 + paperwidth paperheight 0 1 statusdict begin - {setpageparams} stopped pop + {setpageparams} stopped pop end } if } def /savematrix { orgmatrix currentmatrix pop @@ -312,22 +312,22 @@ /Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute /Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve /Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron /breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron ] def -/ReEncode { - dup - length - dict begin - { - 1 index /FID ne - {def} - {pop pop} ifelse - } forall - 0 eq {/Encoding DiacriticEncoding def} if - currentdict - end +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end } bind def /graymode true def /bwidth FMLOCAL /bpside FMLOCAL /bstring FMLOCAL @@ -340,11 +340,11 @@ /setpattern { /bwidth exch def /bpside exch def /bstring exch def /onbits 0 def /offbits 0 def - freq sangle landscape {90 add} if + freq sangle landscape {90 add} if {/y exch def /x exch def /xindex x 1 add 2 div bpside mul cvi def /yindex y 1 add 2 div bpside mul cvi def bstring yindex bwidth mul xindex 8 idiv add get @@ -368,65 +368,65 @@ } bind def /HUE FMLOCAL /SAT FMLOCAL /BRIGHT FMLOCAL /Colors FMLOCAL -FMPrintInColor - +FMPrintInColor + { /HUE 0 def /SAT 0 def /BRIGHT 0 def % array of arrays Hue and Sat values for the separations [HUE BRIGHT] - /Colors + /Colors [[0 0 ] % black [0 0 ] % white [0.00 1.0] % red [0.37 1.0] % green [0.60 1.0] % blue [0.50 1.0] % cyan [0.83 1.0] % magenta [0.16 1.0] % comment / yellow ] def - - /BEGINBITMAPCOLOR { + + /BEGINBITMAPCOLOR { BITMAPCOLOR} def - /BEGINBITMAPCOLORc { + /BEGINBITMAPCOLORc { BITMAPCOLORc} def - /BEGINBITMAPTRUECOLOR { + /BEGINBITMAPTRUECOLOR { BITMAPTRUECOLOR } def - /BEGINBITMAPTRUECOLORc { + /BEGINBITMAPTRUECOLORc { BITMAPTRUECOLORc } def - /K { + /K { Colors exch get dup - 0 get /HUE exch store + 0 get /HUE exch store 1 get /BRIGHT exch store HUE 0 eq BRIGHT 0 eq and {1.0 SAT sub setgray} - {HUE SAT BRIGHT sethsbcolor} + {HUE SAT BRIGHT sethsbcolor} ifelse } def - /FMsetgray { - /SAT exch 1.0 exch sub store + /FMsetgray { + /SAT exch 1.0 exch sub store HUE 0 eq BRIGHT 0 eq and {1.0 SAT sub setgray} - {HUE SAT BRIGHT sethsbcolor} + {HUE SAT BRIGHT sethsbcolor} ifelse } bind def } - + { - /BEGINBITMAPCOLOR { + /BEGINBITMAPCOLOR { BITMAPGRAY} def - /BEGINBITMAPCOLORc { + /BEGINBITMAPCOLORc { BITMAPGRAYc} def - /BEGINBITMAPTRUECOLOR { + /BEGINBITMAPTRUECOLOR { BITMAPTRUEGRAY } def - /BEGINBITMAPTRUECOLORc { + /BEGINBITMAPTRUECOLORc { BITMAPTRUEGRAYc } def /FMsetgray {setgray} bind def - /K { + /K { pop } def } ifelse /normalize { @@ -433,66 +433,66 @@ transform round exch round exch itransform } bind def /dnormalize { dtransform round exch round exch idtransform } bind def -/lnormalize { +/lnormalize { 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop } bind def -/H { +/H { lnormalize setlinewidth } bind def /Z { setlinecap } bind def /fillvals FMLOCAL -/X { +/X { fillvals exch get dup type /stringtype eq - {8 1 setpattern} + {8 1 setpattern} {grayness} ifelse } bind def -/V { +/V { gsave eofill grestore } bind def -/N { +/N { stroke } bind def /M {newpath moveto} bind def /E {lineto} bind def /D {curveto} bind def /O {closepath} bind def /n FMLOCAL -/L { +/L { /n exch def newpath normalize - moveto + moveto 2 1 n {pop normalize lineto} for } bind def -/Y { - L +/Y { + L closepath } bind def /x1 FMLOCAL /x2 FMLOCAL /y1 FMLOCAL /y2 FMLOCAL /rad FMLOCAL -/R { +/R { /y2 exch def /x2 exch def /y1 exch def /x1 exch def x1 y1 x2 y1 x2 y2 x1 y2 - 4 Y + 4 Y } bind def -/RR { +/RR { /rad exch def normalize /y2 exch def /x2 exch def normalize @@ -505,91 +505,91 @@ x2 y1 x1 y1 rad arcto x1 y1 x1 y2 rad arcto closepath 16 {pop} repeat } bind def -/C { +/C { grestore gsave - R + R clip } bind def /FMpointsize FMLOCAL -/F { +/F { FMfonts exch get FMpointsize scalefont setfont } bind def -/Q { +/Q { /FMpointsize exch def - F + F } bind def -/T { +/T { moveto show } bind def -/RF { +/RF { rotate 0 ne {-1 1 scale} if } bind def -/TF { +/TF { gsave - moveto + moveto RF show grestore } bind def -/P { +/P { moveto 0 32 3 2 roll widthshow } bind def -/PF { +/PF { gsave - moveto + moveto RF 0 32 3 2 roll widthshow grestore } bind def -/S { +/S { moveto 0 exch ashow } bind def -/SF { +/SF { gsave moveto RF 0 exch ashow grestore } bind def -/B { +/B { moveto 0 32 4 2 roll 0 exch awidthshow } bind def -/BF { +/BF { gsave moveto RF 0 32 4 2 roll 0 exch awidthshow grestore } bind def -/G { +/G { gsave newpath - normalize translate 0.0 0.0 moveto - dnormalize scale - 0.0 0.0 1.0 5 3 roll arc + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc closepath fill grestore } bind def -/A { +/A { gsave savematrix newpath - 2 index 2 div add exch 3 index 2 div sub exch - normalize 2 index 2 div sub exch 3 index 2 div add exch - translate - scale - 0.0 0.0 1.0 5 3 roll arc + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc restorematrix stroke grestore } bind def /x FMLOCAL @@ -601,41 +601,41 @@ /ww FMLOCAL /hh FMLOCAL /FMsaveobject FMLOCAL /FMoptop FMLOCAL /FMdicttop FMLOCAL -/BEGINPRINTCODE { - /FMdicttop countdictstack 1 add def - /FMoptop count 4 sub def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 4 sub def /FMsaveobject save def - userdict begin - /showpage {} def - FMNORMALIZEGRAPHICS + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS 3 index neg 3 index neg translate } bind def /ENDPRINTCODE { - count -1 FMoptop {pop pop} for - countdictstack -1 FMdicttop {pop end} for - FMsaveobject restore + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore } bind def -/gn { - 0 - { 46 mul - cf read pop - 32 sub - dup 46 lt {exit} if - 46 sub add +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add } loop - add + add } bind def /str FMLOCAL -/cfs { - /str sl string def - 0 1 sl 1 sub {str exch val put} for - str def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def } bind def -/ic [ +/ic [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 0 {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} @@ -653,112 +653,112 @@ /im FMLOCAL /bs FMLOCAL /cs FMLOCAL /len FMLOCAL /pos FMLOCAL -/ms { - /sl exch def - /val 255 def - /ws cfs - /im cfs - /val 0 def - /bs cfs - /cs cfs - } bind def -400 ms -/ip { - is - 0 - cf cs readline pop - { ic exch get exec - add - } forall - pop - - } bind def -/wh { - /len exch def - /pos exch def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def ws 0 len getinterval im pos len getinterval copy pop - pos len + pos len } bind def -/bl { - /len exch def - /pos exch def +/bl { + /len exch def + /pos exch def bs 0 len getinterval im pos len getinterval copy pop - pos len + pos len } bind def /s1 1 string def -/fl { - /len exch def - /pos exch def +/fl { + /len exch def + /pos exch def /val cf s1 readhexstring pop 0 get def pos 1 pos len add 1 sub {im exch val put} for - pos len + pos len } bind def -/hx { - 3 copy getinterval - cf exch readhexstring pop pop +/hx { + 3 copy getinterval + cf exch readhexstring pop pop } bind def /h FMLOCAL /w FMLOCAL /d FMLOCAL /lb FMLOCAL /bitmapsave FMLOCAL /is FMLOCAL /cf FMLOCAL -/wbytes { - dup - 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse - } bind def -/BEGINBITMAPBWc { - 1 {} COMMONBITMAPc - } bind def -/BEGINBITMAPGRAYc { - 8 {} COMMONBITMAPc - } bind def -/BEGINBITMAP2BITc { - 2 {} COMMONBITMAPc - } bind def -/COMMONBITMAPc { - /r exch def - /d exch def - gsave - translate rotate scale /h exch def /w exch def - /lb w d wbytes def - sl lb lt {lb ms} if - /bitmapsave save def - r - /is im 0 lb getinterval def - ws 0 lb getinterval is copy pop - /cf currentfile def - w h d [w 0 0 h neg 0 h] - {ip} image - bitmapsave restore - grestore - } bind def -/BEGINBITMAPBW { - 1 {} COMMONBITMAP - } bind def -/BEGINBITMAPGRAY { - 8 {} COMMONBITMAP - } bind def -/BEGINBITMAP2BIT { - 2 {} COMMONBITMAP - } bind def -/COMMONBITMAP { - /r exch def - /d exch def - gsave - translate rotate scale /h exch def /w exch def - /bitmapsave save def - r - /is w d wbytes string def - /cf currentfile def - w h d [w 0 0 h neg 0 h] - {cf is readhexstring pop} image - bitmapsave restore +/wbytes { + dup + 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + /r exch def + /d exch def + gsave + translate rotate scale /h exch def /w exch def + /lb w d wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + r + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /r exch def + /d exch def + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + r + /is w d wbytes string def + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {cf is readhexstring pop} image + bitmapsave restore grestore } bind def /proc1 FMLOCAL /proc2 FMLOCAL /newproc FMLOCAL @@ -811,131 +811,131 @@ {} setblackgeneration } bind def /tran FMLOCAL /fakecolorsetup { /tran 256 string def - 0 1 255 {/indx exch def + 0 1 255 {/indx exch def tran indx red indx get 77 mul green indx get 151 mul blue indx get 28 mul add add 256 idiv put} for currenttransfer {255 mul cvi tran exch get 255.0 div} exch Fmcc settransfer } bind def -/BITMAPCOLOR { - /d 8 def - gsave - translate rotate scale /h exch def /w exch def - /bitmapsave save def - colorsetup - /is w d wbytes string def - /cf currentfile def - w h d [w 0 0 h neg 0 h] - {cf is readhexstring pop} {is} {is} true 3 colorimage - bitmapsave restore - grestore - } bind def -/BITMAPCOLORc { - /d 8 def - gsave - translate rotate scale /h exch def /w exch def - /lb w d wbytes def - sl lb lt {lb ms} if - /bitmapsave save def - colorsetup - /is im 0 lb getinterval def - ws 0 lb getinterval is copy pop - /cf currentfile def - w h d [w 0 0 h neg 0 h] - {ip} {is} {is} true 3 colorimage - bitmapsave restore - grestore - } bind def -/BITMAPTRUECOLORc { - gsave - translate rotate scale /h exch def /w exch def - /bitmapsave save def - - /is w string def - - ws 0 w getinterval is copy pop - /cf currentfile def - w h 8 [w 0 0 h neg 0 h] - {ip} {gip} {bip} true 3 colorimage - bitmapsave restore - grestore - } bind def -/BITMAPTRUECOLOR { - gsave - translate rotate scale /h exch def /w exch def - /bitmapsave save def +/BITMAPCOLOR { + /d 8 def + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + colorsetup + /is w d wbytes string def + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {cf is readhexstring pop} {is} {is} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /d 8 def + gsave + translate rotate scale /h exch def /w exch def + /lb w d wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {ip} {is} {is} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + + /is w string def + + ws 0 w getinterval is copy pop + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + {ip} {gip} {bip} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def /is w string def /gis w string def /bis w string def - /cf currentfile def - w h 8 [w 0 0 h neg 0 h] - { cf is readhexstring pop } - { cf gis readhexstring pop } - { cf bis readhexstring pop } - true 3 colorimage - bitmapsave restore + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore grestore } bind def -/BITMAPTRUEGRAYc { +/BITMAPTRUEGRAYc { gsave translate rotate scale /h exch def /w exch def - /bitmapsave save def - + /bitmapsave save def + /is w string def - - ws 0 w getinterval is copy pop - /cf currentfile def - w h 8 [w 0 0 h neg 0 h] + + ws 0 w getinterval is copy pop + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] {ip gip bip w gray} image - bitmapsave restore + bitmapsave restore grestore } bind def /ww FMLOCAL /r FMLOCAL /g FMLOCAL /b FMLOCAL /i FMLOCAL -/gray { +/gray { /ww exch def /b exch def /g exch def /r exch def 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul b i get .114 mul add add r i 3 -1 roll floor cvi put } for r } bind def -/BITMAPTRUEGRAY { +/BITMAPTRUEGRAY { gsave translate rotate scale /h exch def /w exch def - /bitmapsave save def + /bitmapsave save def /is w string def /gis w string def /bis w string def - /cf currentfile def - w h 8 [w 0 0 h neg 0 h] - { cf is readhexstring pop - cf gis readhexstring pop + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + { cf is readhexstring pop + cf gis readhexstring pop cf bis readhexstring pop w gray} image - bitmapsave restore + bitmapsave restore grestore } bind def -/BITMAPGRAY { +/BITMAPGRAY { 8 {fakecolorsetup} COMMONBITMAP } bind def -/BITMAPGRAYc { +/BITMAPGRAYc { 8 {fakecolorsetup} COMMONBITMAPc } bind def /ENDBITMAP { } bind def -end +end /ALDsave FMLOCAL /ALDmatrix matrix def ALDmatrix currentmatrix pop /StartALD { /ALDsave save def savematrix Index: doc/tk_mac.n ================================================================== --- doc/tk_mac.n +++ doc/tk_mac.n @@ -2,35 +2,41 @@ '\" Copyright (c) 2011 Kevin Walzer. '\" Copyright (c) 2011 Donal K. Fellows. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tk::mac n 8.6 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tk::mac \- Access Mac-Specific Functionality on OS X from Tk .SH SYNOPSIS .nf +\fB::tk::mac::DoScriptFile\fR +\fB::tk::mac::DoScriptText\fR \fB::tk::mac::ShowPreferences\fR \fB::tk::mac::OpenApplication\fR \fB::tk::mac::ReopenApplication\fR \fB::tk::mac::OpenDocument \fIfile...\fR \fB::tk::mac::PrintDocument \fIfile...\fR \fB::tk::mac::Quit\fR \fB::tk::mac::OnHide\fR \fB::tk::mac::OnShow\fR \fB::tk::mac::ShowHelp\fR +\fB::tk::mac::PerformService\fR +\fB::tk::mac::LaunchURL \fIURL...\fR +\fB::tk::mac::GetAppPath\fR \fB::tk::mac::standardAboutPanel\fR \fB::tk::mac::useCompatibilityMetrics \fIboolean\fR \fB::tk::mac::CGAntialiasLimit \fIlimit\fR \fB::tk::mac::antialiasedtext \fInumber\fR \fB::tk::mac::useThemedToplevel \fIboolean\fR + \fB::tk::mac::iconBitmap \fIname width height \-kind value\fR .fi .BE .SH "EVENT HANDLER CALLBACKS" @@ -38,10 +44,24 @@ The Aqua/Mac OS X application environment defines a number of additional events that applications should respond to. These events are mapped by Tk to calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if the command is absent, no action will be taken. .TP +\fB::tk::mac::DoScriptFile\fR +. +The default Apple Event handler for AEDoScriptHandler. This command, +if defined, executes a Tcl file when an AppleScript sends a +.QW "do script" +command to Wish with a file path as a parameter. +.TP +\fB::tk::mac::DoScriptText\fR +. +The default Apple Event handler for AEDoScriptHandler. This command, +if defined, executes Tcl code when an AppleScript sends a +.QW "do script" +command to Wish with Tcl code or a Tcl procedure as a parameter. +.TP \fB::tk::mac::ShowPreferences\fR . The default Apple Event handler for kAEShowPreferences, .QW pref . The application menu @@ -59,11 +79,11 @@ .RE .TP \fB::tk::mac::OpenApplication\fR . If a proc of this name is defined, this proc fill fire when your application -is intially opened. It is the default Apple Event handler for +is initially opened. It is the default Apple Event handler for kAEOpenApplication, .QW oapp . .TP \fB::tk::mac::ReopenApplication\fR . @@ -108,13 +128,12 @@ \fB::tk::mac::PrintDocument \fIfile...\fR . If a proc of this name is defined it is the default Apple Event handler for kAEPrintDocuments, .QW pdoc , -the Apple Event sent when your application is asked to print one or more -documents (e.g., via the Print menu item in the Finder). It works the same -way as \fBtk::mac::OpenDocument\fR in terms of arguments. +the Apple Event sent when your application is asked to print a +document. It takes a single absolute file path as an argument. .TP \fB::tk::mac::Quit\fR . If a proc of this name is defined it is the default Apple Event handler for kAEQuitApplication, @@ -139,11 +158,61 @@ . Customizes behavior of Apple Help menu; if this procedure is not defined, the platform-specific standard Help menu item .QW "YourApp Help" performs the default Cocoa action of showing the Help Book configured in the -application's Info.plist (or displaying an alert if no Help Book is set). +application's Info.plist (or displaying an alert if no Help Book is +set). +.TP +\fB::tk::mac::PerformService\fR +. +Executes a Tcl procedure called from the macOS +.QW Services +menu in the Application menu item. The +.QW Services +menu item allows for inter-application communication; data from one +application, such as selected text, can be sent to another application +for processing, for example to Safari as a search item for Google, or +to TextEdit to be appended to a file. An example of the proc is below, +and should be rewritten in an application script for customization: +.RS +.PP +.CS +proc ::tk::mac::PerformService {} { + set data [clipboard get] + $w insert end $data +} +.CE +.RE +Note that the mechanism for retrieving the data is from the clipboard; +there is no other supported way to obtain the data. If the Services +process is not desired, the NSServices keys can be deleted from +the application's Info.plist file. The underlying code supporting this +command also allows the text, entry and ttk::entry widgets to access +services from other applications via the Services menu. The NSPortName +key in Wish's Info.plist file is currently set as +.QW "Wish" +; if a developer changes the name of the Wish executable to something + else, this key should be modified with the same name. +.TP +\fB::tk::mac::LaunchURL \fIURL...\fR +. +If defined, launches a URL within Tk. This would be used if a Tk +application wants to handle a URL itself, such as displaying data from +an RSS feed, rather than launching a default application to handle the +URL, although it can defined as such. Wish includes a stub URL scheme +of +.QW foo:// +in the CFBundleURLSchemes key of its Info.plist file; this should be customized for the specific URL +scheme the developer wants to support. +.TP +\fB::tk::mac::GetAppPath\fR +. +Returns the current applications's file path. +.TP + + .SH "ADDITIONAL DIALOGS" .PP The Aqua/Mac OS X defines additional dialogs that applications should support. .TP Index: doc/tkvars.n ================================================================== --- doc/tkvars.n +++ doc/tkvars.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tkvars n 4.1 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/tkwait.n ================================================================== --- doc/tkwait.n +++ doc/tkwait.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1992 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH tkwait n "" Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/toplevel.n ================================================================== --- doc/toplevel.n +++ doc/toplevel.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH toplevel n 8.4 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -23,10 +23,21 @@ This option is the same as the standard \fB\-background\fR option except that its value may also be specified as an empty string. In this case, the widget will display no background or border, and no colors will be consumed from its colormap for its background and border. +.VS "8.7, TIP262" +An empty background will disable drawing the background image. +.OP \-backgroundimage backgroundImage BackgroundImage +This specifies an image to display on the toplevel's background within +the border of the toplevel (i.e., the image will be clipped by the +toplevel's highlight ring and border, if either are present) on top of +the background; +subwidgets of the toplevel will be drawn on top. The image must have +been created with the \fBimage create\fR command. If specified as the +empty string, no image will be displayed. +.VE "8.7, TIP262" .OP \-class class Class Specifies a class for the window. This class will be used when querying the option database for the window's other options, and it will also be used later for other purposes such as bindings. @@ -69,10 +80,19 @@ different display. Defaults to the same screen as its parent. This option is special in that it may not be specified via the option database, and it may not be modified with the \fBconfigure\fR widget command. +.OP \-tile tile Tile +.VS "8.7, TIP262" +This specifies how to draw the background image (see +\fB\-backgroundimage\fR) on the toplevel. +If true (according to \fBTcl_GetBoolean\fR), the image will be tiled +to fill the whole toplevel, with the origin of the first copy of the +image being the top left of the interior of the toplevel. +If false (the default), the image will be centered within the toplevel. +.VE "8.7, TIP262" .OP \-use use Use This option is used for embedding. If the value is not an empty string, it must be the window identifier of a container window, specified as a hexadecimal string like the ones returned by the \fBwinfo id\fR command. The toplevel widget will be created as a child of the given @@ -102,38 +122,42 @@ or in the option database to configure aspects of the toplevel such as its background color and relief. The \fBtoplevel\fR command returns the path name of the new window. .PP -A toplevel is similar to a frame except that it is created as a +A toplevel is similar to a \fBframe\fR except that it is created as a top-level window: its X parent is the root window of a screen -rather than the logical parent from its path name. The primary +rather than the logical parent from its Tk path name. The primary purpose of a toplevel is to serve as a container for dialog boxes and other collections of widgets. The only visible features -of a toplevel are its background color and an optional 3-D border +of a toplevel are its background and an optional 3-D border to make the toplevel appear raised or sunken. .SH "WIDGET COMMAND" .PP The \fBtoplevel\fR command creates a new Tcl command whose name is the same as the path name of the toplevel's window. This command may be used to invoke various operations on the widget. It has the following general form: +.PP .CS \fIpathName option \fR?\fIarg arg ...\fR? .CE +.PP \fIPathName\fR is the name of the command, which is the same as the toplevel widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for toplevel widgets: .TP \fIpathName \fBcget \fIoption\fR +. Returns the current value of the configuration option given by \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBtoplevel\fR command. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? +. Query or modify the configuration options of the widget. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for information on the format of this list). If \fIoption\fR is specified with no \fIvalue\fR, then the command returns a list describing the @@ -146,12 +170,14 @@ command. .SH BINDINGS .PP When a new toplevel is created, it has no default event bindings: toplevels are not intended to be interactive. +.PP +Be aware that bindings on toplevels may receive events from subwidgets. .SH "SEE ALSO" -frame(n) +bind(n), bindtags(n), frame(n), wm(n) .SH KEYWORDS toplevel, widget '\" Local Variables: '\" mode: nroff '\" End: Index: doc/ttk_Theme.3 ================================================================== --- doc/ttk_Theme.3 +++ doc/ttk_Theme.3 @@ -1,11 +1,11 @@ '\" '\" Copyright (c) 2003 Joe English '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Ttk_CreateTheme 3 8.5 Tk "Tk Themed Widget" .so man.macros .BS .SH NAME Ttk_CreateTheme, Ttk_GetTheme, Ttk_GetDefaultTheme, Ttk_GetCurrentTheme \- create and use Tk themes. Index: doc/ttk_button.n ================================================================== --- doc/ttk_button.n +++ doc/ttk_button.n @@ -15,11 +15,11 @@ .SH DESCRIPTION A \fBttk::button\fR widget displays a textual label and/or image, and evaluates a command when pressed. .SO ttk_widget \-class \-compound \-cursor -\-image \-state \-style +\-image \-justify \-state \-style \-takefocus \-text \-textvariable \-underline \-width .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-command command Command Index: doc/ttk_combobox.n ================================================================== --- doc/ttk_combobox.n +++ doc/ttk_combobox.n @@ -17,11 +17,11 @@ A \fBttk::combobox\fR combines a text field with a pop-down list of values; the user may select the value of the text field from among the values in the list. .SO ttk_widget \-class \-cursor \-takefocus -\-style +\-style \-placeholder .SE .\" ALSO: Other entry widget options .SH "WIDGET-SPECIFIC OPTIONS" .OP \-exportselection exportSelection ExportSelection Boolean value. @@ -65,11 +65,13 @@ '\"Modify or query widget options. '\"See \fIttk::widget(n)\fR. .TP \fIpathName \fBcurrent\fR ?\fInewIndex\fR? If \fInewIndex\fR is supplied, sets the combobox value -to the element at position \fInewIndex\fR in the list of \fB\-values\fR. +to the element at position \fInewIndex\fR in the list of \fB\-values\fR +(in addition to integers, the \fBend\fR index is supported and indicates +the last element of the list). Otherwise, returns the index of the current value in the list of \fB\-values\fR or \fB\-1\fR if the current value does not appear in the list. .TP \fIpathName \fBget\fR Returns the current value of the combobox. @@ -121,10 +123,12 @@ .PP \fBTCombobox\fP styling options configurable with \fBttk::style\fP are: .PP \fB\-arrowcolor\fP \fIcolor\fP +.br +\fB\-arrowsize\fP \fIamount\fP .br \fB\-background\fP \fIcolor\fP .br \fB\-bordercolor\fP \fIcolor\fP .br Index: doc/ttk_entry.n ================================================================== --- doc/ttk_entry.n +++ doc/ttk_entry.n @@ -21,23 +21,23 @@ The value of the string may be linked to a Tcl variable with the \fB\-textvariable\fR option. Entry widgets support horizontal scrolling with the standard \fB\-xscrollcommand\fR option and \fBxview\fR widget command. .SO ttk_widget -\-class \-cursor \-style -\-takefocus \-xscrollcommand +\-class \-cursor +\-font \-foreground +\-style +\-takefocus \-xscrollcommand \-placeholder .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-exportselection exportSelection ExportSelection A boolean value specifying whether or not a selection in the widget should be linked to the X selection. If the selection is exported, then selecting in the widget deselects the current X selection, selecting outside the widget deselects any widget selection, and the widget will respond to selection retrieval requests when it has a selection. -.\" MAYBE: .OP \-font font Font -.\" MAYBE: .OP \-foreground foreground Foreground .\" MAYBE: .OP \-insertbackground insertBackground Foreground .\" MAYBE: .OP \-insertwidth insertWidth InsertWidth .OP \-invalidcommand invalidCommand InvalidCommand A script template to evaluate whenever the \fB\-validatecommand\fR returns 0. See \fBVALIDATION\fR below for more information. @@ -220,56 +220,17 @@ Force revalidation, independent of the conditions specified by the \fB\-validate\fR option. Returns 0 if validation fails, 1 if it succeeds. Sets or clears the \fBinvalid\fR state accordingly. See \fBVALIDATION\fR below for more details. -.TP -\fIpathName \fBxview \fIargs\fR -This command is used to query and change the horizontal position of the -text in the widget's window. It can take any of the following -forms: -.RS -.TP -\fIpathName \fBxview\fR -Returns a list containing two elements. -Each element is a real fraction between 0 and 1; together they describe -the horizontal span that is visible in the window. -For example, if the first element is .2 and the second element is .6, -20% of the entry's text is off-screen to the left, the middle 40% is visible -in the window, and 40% of the text is off-screen to the right. -These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR -option. -.TP -\fIpathName \fBxview\fR \fIindex\fR -Adjusts the view in the window so that the character given by \fIindex\fR -is displayed at the left edge of the window. -.TP -\fIpathName \fBxview moveto\fI fraction\fR -Adjusts the view in the window so that the character \fIfraction\fR of the -way through the text appears at the left edge of the window. -\fIFraction\fR must be a fraction between 0 and 1. -.TP -\fIpathName \fBxview scroll \fInumber what\fR -This command shifts the view in the window left or right according to -\fInumber\fR and \fIwhat\fR. -\fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. -'\" or an abbreviation of one of these, but we don't document that. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by -\fInumber\fR average-width characters on the display; if it is -\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. -If \fInumber\fR is negative then characters farther to the left -become visible; if it is positive then characters farther to the right -become visible. -.RE .PP The entry widget also supports the following generic \fBttk::widget\fR widget subcommands (see \fIttk::widget(n)\fR for details): .DS .ta 5.5c 11c \fBcget\fR \fBconfigure\fR \fBidentify\fR -\fBinstate\fR \fBstate\fR +\fBinstate\fR \fBstate\fR \fBxview\fR .DE .SH VALIDATION .PP The \fB\-validate\fR, \fB\-validatecommand\fR, and \fB\-invalidcommand\fR options are used to enable entry widget validation. @@ -470,20 +431,20 @@ \fBTEntry\fP styling options configurable with \fBttk::style\fP are: .PP \fB\-background\fP \fIcolor\fP .RS -When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. +For backwards compatibility, when using the aqua theme (for macOS), this +option behaves as an alias for the \fB\-fieldbackground\fP provided that no +value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored. .RE \fB\-bordercolor\fP \fIcolor\fP .br \fB\-darkcolor\fP \fIcolor\fP .br \fB\-fieldbackground\fP \fIcolor\fP .RS -Does not work with the aqua theme (Mac OS X). -.br Some themes use a graphical background and their field background colors cannot be changed. .RE \fB\-foreground\fP \fIcolor\fP .br \fB\-insertwidth\fP \fIamount\fP Index: doc/ttk_frame.n ================================================================== --- doc/ttk_frame.n +++ doc/ttk_frame.n @@ -56,10 +56,14 @@ .PP Some options are only available for specific themes. .PP See the \fBttk::style\fP manual page for information on how to configure ttk styles. +.SH BINDINGS +.PP +When a new \fBttk::frame\fR is created, it has no default event bindings; +\fBttk::frame\fRs are not intended to be interactive. .SH "SEE ALSO" ttk::widget(n), ttk::labelframe(n), frame(n) .SH "KEYWORDS" widget, frame, container '\" Local Variables: Index: doc/ttk_label.n ================================================================== --- doc/ttk_label.n +++ doc/ttk_label.n @@ -16,35 +16,20 @@ .PP A \fBttk::label\fR widget displays a textual label and/or image. The label may be linked to a Tcl variable to automatically change the displayed text. .SO ttk_widget -\-class \-compound \-cursor -\-image \-padding \-state \-style \-takefocus +\-anchor \-class \-compound \-cursor +\-font \-foreground +\-image \-justify \-padding \-state \-style \-takefocus \-text \-textvariable \-underline -\-width +\-width \-wraplength .SE .SH "WIDGET-SPECIFIC OPTIONS" -.OP \-anchor anchor Anchor -Specifies how the information in the widget is positioned -relative to the inner margins. Legal values are -\fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, -\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, and \fBcenter\fR. -See also \fB\-justify\fR. .OP \-background frameColor FrameColor The widget's background color. If unspecified, the theme default is used. -.OP \-font font Font -Font to use for label text. -.OP \-foreground textColor TextColor -The widget's foreground color. -If unspecified, the theme default is used. -.OP \-justify justify Justify -If there are multiple lines of text, specifies how -the lines are laid out relative to one another. -One of \fBleft\fR, \fBcenter\fR, or \fBright\fR. -See also \fB\-anchor\fR. .OP \-relief relief Relief .\" Rewrite this: Specifies the 3-D effect desired for the widget border. Valid values are \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR, Index: doc/ttk_progressbar.n ================================================================== --- doc/ttk_progressbar.n +++ doc/ttk_progressbar.n @@ -17,18 +17,26 @@ A \fBttk::progressbar\fR widget shows the status of a long-running operation. They can operate in two modes: \fIdeterminate\fR mode shows the amount completed relative to the total amount of work to be done, and \fIindeterminate\fR mode provides an animated display to let the user know that something is happening. +.PP +If the value of \fB-orient\fR is \fBhorizontal\fR a text string can be +displayed inside the progressbar. This string can be configured using +the \fB-anchor\fR, \fB-font\fR, \fB-foreground\fR, \fB-justify\fR, +\fB-text\fR and \fB-wraplength\fR options. If the value of \fB-orient\fR +is \fBvertical\fR then these options are ignored. .SO ttk_widget -\-class \-cursor \-takefocus -\-style +\-anchor \-class \-cursor +\-font \-foreground \-justify \-style +\-takefocus \-text \-wraplength .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-length length Length Specifies the length of the long axis of the progress bar -(width if horizontal, height if vertical). +(width if horizontal, height if vertical). The value may have any of the forms +acceptable to \fBTk_GetPixels\fR. .OP \-maximum maximum Maximum A floating point number specifying the maximum \fB\-value\fR. Defaults to 100. .OP \-mode mode Mode One of \fBdeterminate\fR or \fBindeterminate\fR. Index: doc/ttk_scale.n ================================================================== --- doc/ttk_scale.n +++ doc/ttk_scale.n @@ -91,11 +91,11 @@ Get the coordinates corresponding to \fIvalue\fR, or the coordinates corresponding to the current value of the \fB\-value\fR option if \fIvalue\fR is omitted. .SH "STYLING OPTIONS" .PP -The class name for a \fBttk::scale\fP is \fBTProgressbar\fP. +The class name for a \fBttk::scale\fP is \fBTScale\fP. .PP Dynamic states: \fBactive\fP. .PP \fBTProgressbar\fP styling options configurable with \fBttk::style\fP are: Index: doc/ttk_scrollbar.n ================================================================== --- doc/ttk_scrollbar.n +++ doc/ttk_scrollbar.n @@ -74,11 +74,11 @@ \fIpathName \fBstate\fR ?\fIstateSpec\fR? Modify or query the widget state; see \fIttk::widget(n)\fR. .SH "INTERNAL COMMANDS" .PP The following widget commands are used internally -by the TScrollbar widget class bindings. +by the \fBTScrollbar\fP widget class bindings. .TP \fIpathName \fBdelta \fIdeltaX deltaY\fR Returns a real number indicating the fractional change in the scrollbar setting that corresponds to a given change in thumb position. For example, if the scrollbar is horizontal, @@ -116,26 +116,26 @@ If \fIfraction\fR is 0 it refers to the beginning of the document. 1.0 refers to the end of the document, 0.333 refers to a point one-third of the way through the document, and so on. .TP -\fIprefix \fBscroll \fInumber \fBunits\fR -The widget should adjust its view by \fInumber\fR units. -The units are defined in whatever way makes sense for the widget, -such as characters or lines in a text widget. -\fINumber\fR is either 1, which means one unit should scroll off -the top or left of the window, or \-1, which means that one unit -should scroll off the bottom or right of the window. -.TP \fIprefix \fBscroll \fInumber \fBpages\fR The widget should adjust its view by \fInumber\fR pages. It is up to the widget to define the meaning of a page; typically it is slightly less than what fits in the window, so that there is a slight overlap between the old and new views. \fINumber\fR is either 1, which means the next page should become visible, or \-1, which means that the previous page should become visible. +.TP +\fIprefix \fBscroll \fInumber \fBunits\fR +The widget should adjust its view by \fInumber\fR units. +The units are defined in whatever way makes sense for the widget, +such as characters or lines in a text widget. +\fINumber\fR is either 1, which means one unit should scroll off +the top or left of the window, or \-1, which means that one unit +should scroll off the bottom or right of the window. .SH "WIDGET STATES" .PP The scrollbar automatically sets the \fBdisabled\fR state bit. when the entire range is visible (range is 0.0 to 1.0), and clears it otherwise. @@ -151,31 +151,37 @@ grid $f.t \-row 0 \-column 0 \-sticky nsew grid $f.vsb \-row 0 \-column 1 \-sticky nsew grid $f.hsb \-row 1 \-column 0 \-sticky nsew grid columnconfigure $f 0 \-weight 1 grid rowconfigure $f 0 \-weight 1 +pack $f .CE .SH "STYLING OPTIONS" .PP The class name for a \fBttk::scrollbar\fP is \fBTScrollbar\fP. .PP Dynamic states: \fBactive\fP, \fBdisabled\fP. .PP -\fBTScrollbar\fP styling options configurable with \fBttk::style\fP -are: +\fBTScrollbar\fP (or more specifically \fBVertical.TScrollbar\fP and +\fBHorizontal.TScrollbar\fP) styling options that are configurable with +\fBttk::style\fP are: .PP \fB\-arrowcolor\fP \fIcolor\fP +.br +\fB\-arrowsize\fP \fIamount\fP .br \fB\-background\fP \fIcolor\fP .br \fB\-bordercolor\fP \fIcolor\fP .br -\fB\-darkcolor\fP \fIcolor\fP +\fB\-darkcolor\fP \fIcolor\fP (color of the dark part of the 3D relief) .br \fB\-foreground\fP \fIcolor\fP .br -\fB\-lightcolor\fP \fIcolor\fP +\fB\-gripcount\fP \fIcount\fP (number of lines on the thumb) +.br +\fB\-lightcolor\fP \fIcolor\fP (color of the light part of the 3D relief) .br \fB\-troughcolor\fP \fIcolor\fP .PP Some options are only available for specific themes. .PP Index: doc/ttk_spinbox.n ================================================================== --- doc/ttk_spinbox.n +++ doc/ttk_spinbox.n @@ -20,11 +20,11 @@ of the \fBttk::entry\fR widget including support of the \fB\-textvariable\fR option to link the value displayed by the widget to a Tcl variable. .SO ttk_widget \-class \-cursor \-state \-style -\-takefocus \-xscrollcommand +\-takefocus \-xscrollcommand \-placeholder .SE .SO ttk_entry \-validate \-validatecommand .SE .SH "WIDGET-SPECIFIC OPTIONS" @@ -93,20 +93,20 @@ .br \fB\-arrowsize\fP \fIamount\fP .br \fB\-background\fP \fIcolor\fP .RS -When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. +For backwards compatibility, when using the aqua theme (for macOS), this +option behaves as an alias for the \fB\-fieldbackground\fP provided that no +value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored. .RE \fB\-bordercolor\fP \fIcolor\fP .br \fB\-darkcolor\fP \fIcolor\fP .br \fB\-fieldbackground\fP \fIcolor\fP -.RS -Does not work with the aqua theme (Mac OS X). -.RE +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-lightcolor\fP \fIcolor\fP .br \fB\-padding\fP \fIpadding\fP Index: doc/ttk_treeview.n ================================================================== --- doc/ttk_treeview.n +++ doc/ttk_treeview.n @@ -131,29 +131,33 @@ \fB\-id \fIname\fR The column name. This is a read-only option. For example, [\fI$pathname \fBcolumn #\fIn \fB\-id\fR] returns the data column associated with display column #\fIn\fR. .TP -\fB\-anchor\fR +\fB\-anchor \fIanchor\fR Specifies how the text in this column should be aligned -with respect to the cell. One of +with respect to the cell. \fIAnchor\fR is one of \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR. .TP -\fB\-minwidth\fR +\fB\-minwidth \fIminwidth\fR The minimum width of the column in pixels. The treeview widget will not make the column any smaller than \fB\-minwidth\fR when the widget is resized or the user drags a -column separator. -.TP -\fB\-stretch\fR -Specifies whether or not the column's width should be adjusted -when the widget is resized. -.TP -\fB\-width \fIw\fR -The width of the column in pixels. Default is something reasonable, -probably 200 or so. +column separator. Default is 20 pixels. +.TP +\fB\-stretch \fIboolean\fR +Specifies whether or not the column width should be adjusted +when the widget is resized or the user drags a column separator. +\fIBoolean\fR may have any of the forms accepted by \fBTcl_GetBoolean\fR. +By default columns are stretchable. +.TP +\fB\-width \fIwidth\fR +The width of the column in pixels. Default is 200 pixels. The specified +column width may be changed by Tk in order to honor \fB\-stretch\fR +and/or \fB\-minwidth\fR, or when the widget is resized or the user drags a +column separator. .PP Use \fIpathname column #0\fR to configure the tree column. .RE .TP \fIpathname \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? @@ -386,16 +390,17 @@ Removes the specified \fItag\fR from each of the listed \fIitems\fR. If \fIitems\fR is omitted, removes \fItag\fR from each item in the tree. If \fItag\fR is not present for a particular item, then the \fB\-tags\fR for that item are unchanged. .RE -.TP -\fIpathName \fBxview \fIargs\fR -Standard command for horizontal scrolling; see \fIwidget(n)\fR. -.TP -\fIpathName \fByview \fIargs\fR -Standard command for vertical scrolling; see \fIttk::widget(n)\fR. +.PP +The treeview widget also supports the following generic \fBttk::widget\fR +widget subcommands (see \fIttk::widget(n)\fR for details): +.DS +.ta 5.5c 11c +\fBxview\fR \fByview\fR +.DE .SH "ITEM OPTIONS" .PP The following item options may be specified for items in the \fBinsert\fR and \fBitem\fR widget commands. .OP \-text text Text @@ -432,10 +437,13 @@ .\" ??? Maybe: .IP \-text .IP \fB\-image\fR Specifies the item image, in case the item's \fB\-image\fR option is empty. .\" .PP .\" \fI(@@@ TODO: sort out order of precedence for options)\fR +.PP +Tag priority is decided by the creation order: tags created first receive +higher priority. .SH "COLUMN IDENTIFIERS" .PP Column identifiers take any of the following forms: .IP \(bu A symbolic name from the list of \fB\-columns\fR. Index: doc/ttk_widget.n ================================================================== --- doc/ttk_widget.n +++ doc/ttk_widget.n @@ -69,10 +69,16 @@ A command prefix, used to communicate with vertical scrollbars. See the description of \fB\-xscrollcommand\fR above for details. .SH "LABEL OPTIONS" The following options are supported by labels, buttons, and other button-like widgets: +.OP \-anchor anchor Anchor +Specifies how the information in the widget is positioned +relative to the inner margins. Legal values are +\fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, +\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, and \fBcenter\fR. +See also \fB\-justify\fR (for widgets supporting this option). .OP \-compound compound Compound Specifies how to display the image relative to the text, in the case both \fB\-text\fR and \fB\-image\fR are present. Valid values are: .RS @@ -88,18 +94,28 @@ .IP right Display image above, below, left of, or right of the text, respectively. .IP none The default; display the image if present, otherwise the text. .RE +.OP \-font font Font +Font to use for the text displayed by the widget. +.OP \-foreground textColor TextColor +The widget's foreground color. +If unspecified, the theme default is used. .OP \-image image Image Specifies an image to display. This is a list of 1 or more elements. The first element is the default image name. The rest of the list is a sequence of \fIstatespec / value\fR pairs as per \fBstyle map\fR, specifying different images to use when the widget is in a particular state or combination of states. All images in the list should have the same size. +.OP \-justify justify Justify +If there are multiple lines of text, specifies how +the lines are laid out relative to one another. +One of \fBleft\fR, \fBcenter\fR, or \fBright\fR. +See also \fB\-anchor\fR (for widgets supporting this option). .OP \-padding padding Padding Specifies the internal padding for the widget. The padding is a list of up to four length specifications \fIleft top right bottom\fR. If fewer than four elements are specified, @@ -109,11 +125,11 @@ In other words, a list of three numbers specify the left, vertical, and right padding; a list of two numbers specify the horizontal and the vertical padding; a single number specifies the same padding all the way around the widget. .OP \-text text Text Specifies a text string to be displayed inside the widget -(unless overridden by \fB\-textvariable\fR). +(unless overridden by \fB\-textvariable\fR for the widgets supporting this option). .OP \-textvariable textVariable Variable Specifies the name of a global variable whose value will be used in place of the \fB\-text\fR resource. .OP \-underline underline Underline If set, specifies the integer index (0-based) of a character to underline @@ -122,10 +138,26 @@ .OP \-width width Width If greater than zero, specifies how much space, in character widths, to allocate for the text label. If less than zero, specifies a minimum width. If zero or unspecified, the natural width of the text label is used. +Note that some themes may specify a non-zero \fB\-width\fR +in the style. +.OP \-wraplength wrapLength WrapLength +Specifies the maximum line length. The value may have any of the forms +acceptable to \fBTk_GetPixels\fR. If this option is less than or equal +to zero, then automatic wrapping is not performed; otherwise +the text is split into lines such that no line is longer +than the specified value. +.SH "ENTRY OPTIONS" +The following option is supported by entry, spinbox and combobox: +.OP \-placeholder placeHolder PlaceHolder +Specifies a help text string to display if no text is otherwise displayed, +that is when the widget is empty. The placeholder text is displayed using +the values of the \fB\-font\fR and \fB\-justify\fR options. The foreground +color of the placeholder text can be changed using the +\fB\-placeholderforeground\fR style option. .SH "COMPATIBILITY OPTIONS" This option is only available for themed widgets that have .QW corresponding traditional Tk widgets. .OP \-state state State @@ -190,10 +222,90 @@ .CE will restore \fIpathName\fR to the original state. If \fIstateSpec\fR is not specified, returns a list of the currently-enabled state flags. .RE +.TP +\fIpathName \fBxview \fIargs\fR +This command is used to query and change the horizontal position of the +content in the widget's window. It can take any of the following +forms: +.RS +.TP +\fIpathName \fBxview\fR +Returns a list containing two elements. +Each element is a real fraction between 0 and 1; together they describe +the horizontal span that is visible in the window. +For example, if the first element is .2 and the second element is .6, +20% of the widget's content is off-screen to the left, the middle 40% is visible +in the window, and 40% of the content is off-screen to the right. +These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR +option. +.TP +\fIpathName \fBxview\fR \fIindex\fR +Adjusts the view in the window so that the content given by \fIindex\fR +is displayed at the left edge of the window. +.TP +\fIpathName \fBxview moveto\fI fraction\fR +Adjusts the view in the window so that the character \fIfraction\fR of the +way through the content appears at the left edge of the window. +\fIFraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fBxview scroll \fInumber what\fR +This command shifts the view in the window left or right according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR. +'\" or an abbreviation of one of these, but we don't document that. +If \fIwhat\fR is +\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then characters farther to the left +become visible; if it is positive then characters farther to the right +become visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR average-width characters on the display. +.RE +.TP +\fIpathName \fByview \fIargs\fR +This command is used to query and change the vertical position of the +content in the widget's window. It can take any of the following +forms: +.RS +.TP +\fIpathName \fByview\fR +Returns a list containing two elements. +Each element is a real fraction between 0 and 1; together they describe +the vertical span that is visible in the window. +For example, if the first element is .2 and the second element is .6, +20% of the widget's content is off-screen to the top, the middle 40% is visible +in the window, and 40% of the content is off-screen to the bottom. +These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR +option. +.TP +\fIpathName \fByview\fR \fIindex\fR +Adjusts the view in the window so that the content given by \fIindex\fR +is displayed at the top edge of the window. +.TP +\fIpathName \fByview moveto\fI fraction\fR +Adjusts the view in the window so that the item \fIfraction\fR of the +way through the content appears at the top edge of the window. +\fIFraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fByview scroll \fInumber what\fR +This command shifts the view in the window up or down according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBpages\fR or \fBunits\fR. +'\" or an abbreviation of one of these, but we don't document that. +If \fIwhat\fR is +\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then items farther to the top +become visible; if it is positive then items farther to the bottom +become visible. +If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by +\fInumber\fR average-width characters on the display. +.RE .SH "WIDGET STATES" The widget state is a bitmap of independent state flags. Widget state flags include: .TP \fBactive\fR Index: doc/winfo.n ================================================================== --- doc/winfo.n +++ doc/winfo.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH winfo n 4.3 Tk "Tk Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/wish.1 ================================================================== --- doc/wish.1 +++ doc/wish.1 @@ -2,11 +2,11 @@ '\" Copyright (c) 1991-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH wish 1 8.0 Tk "Tk Applications" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -75,11 +75,11 @@ If there exists a file .QW \fB.wishrc\fR in the home directory of the user, \fBwish\fR evaluates the file as a Tcl script just before reading the first command from standard input. .PP -If arguments to \fBwish\fR do specify a \fIfileName\fR, then +If arguments to \fBwish\fR do specify a \fIfileName\fR, then \fIfileName\fR is treated as the name of a script file. \fBWish\fR will evaluate the script in \fIfileName\fR (which presumably creates a user interface), then it will respond to events until all windows have been deleted. Commands will not be read from standard input. Index: doc/wm.n ================================================================== --- doc/wm.n +++ doc/wm.n @@ -492,11 +492,11 @@ format, and becomes the application icon in dialogs, the Dock, and other contexts. 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. +(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 @@ -708,24 +708,25 @@ specified then the command returns the current title for the \fIwindow\fR. The title for a window defaults to its name. .TP \fBwm transient \fIwindow\fR ?\fImaster\fR? . -If \fImaster\fR is specified, then the window manager is informed -that \fIwindow\fR is a transient window (e.g. pull-down menu) working -on behalf of \fImaster\fR (where \fImaster\fR is the -path name for a top-level window). If \fImaster\fR -is specified as an empty string then \fIwindow\fR is marked as not -being a transient window any more. Otherwise the command -returns the path name of \fIwindow\fR's current master, or an -empty string if \fIwindow\fR is not currently a transient window. -A transient window will mirror state changes in the master and -inherit the state of the master when initially mapped. It is an -error to attempt to make a window a transient of itself. -The window manager may also decorate a transient window differently, removing -some features normally present (e.g., minimize and maximize buttons) though -this is entirely at the discretion of the window manager. +If \fImaster\fR is specified, then the window manager is informed that +\fIwindow\fR is a transient window (e.g. pull-down menu) working on +behalf of \fImaster\fR (where \fImaster\fR is the path name for a +top-level window). If \fImaster\fR is specified as an empty string +then \fIwindow\fR is marked as not being a transient window any more. +Otherwise the command returns the path name of \fIwindow\fR's current +master, or an empty string if \fIwindow\fR is not currently a +transient window. A transient window will mirror state changes in the +master and inherit the state of the master when initially mapped. The +directed graph with an edge from each transient to its master must be +acyclic. In particular, it is an error to attempt to make a window a +transient of itself. The window manager may also decorate a transient +window differently, removing some features normally present (e.g., +minimize and maximize buttons) though this is entirely at the +discretion of the window manager. .TP \fBwm withdraw \fIwindow\fR . Arranges for \fIwindow\fR to be withdrawn from the screen. This causes the window to be unmapped and forgotten about by the window ADDED generic/nanosvg.h Index: generic/nanosvg.h ================================================================== --- /dev/null +++ generic/nanosvg.h @@ -0,0 +1,3084 @@ +/* + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example + * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/) + * + * Arc calculation code based on canvg (https://code.google.com/p/canvg/) + * + * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + * + */ + +#ifndef NANOSVG_H +#define NANOSVG_H + +#ifdef __cplusplus +extern "C" { +#endif + +// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. +// +// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game. +// +// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request! +// +// The shapes in the SVG images are transformed by the viewBox and converted to specified units. +// That is, you should get the same looking data as your designed in your favorite app. +// +// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose +// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. +// +// The units passed to NanoVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. +// DPI (dots-per-inch) controls how the unit conversion is done. +// +// If you don't know or care about the units stuff, "px" and 96 should get you going. + + +/* Example Usage: + // Load + NSVGImage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + printf("size: %f x %f\n", image->width, image->height); + // Use... + for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) { + for (NSVGpath *path = shape->paths; path != NULL; path = path->next) { + for (int i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]); + } + } + } + // Delete + nsvgDelete(image); +*/ + +#ifndef NANOSVG_SCOPE +#define NANOSVG_SCOPE +#endif + +#ifndef NANOSVG_malloc +#define NANOSVG_malloc malloc +#endif + +#ifndef NANOSVG_realloc +#define NANOSVG_realloc realloc +#endif + +#ifndef NANOSVG_free +#define NANOSVG_free free +#endif + +// float emulation for MS VC6++ compiler +#if (_MSC_VER == 1200) +#define tanf(a) (float)tan(a) +#define cosf(a) (float)cos(a) +#define sinf(a) (float)sin(a) +#define sqrtf(a) (float)sqrt(a) +#define fabsf(a) (float)abs(a) +#define acosf(a) (float)acos(a) +#define atan2f(a,b) (float)atan2(a,b) +#define ceilf(a) (float)ceil(a) +#define fmodf(a,b) (float)fmod(a,b) +#define floorf(a) (float)floor(a) +#endif + +enum NSVGpaintType { + NSVG_PAINT_NONE = 0, + NSVG_PAINT_COLOR = 1, + NSVG_PAINT_LINEAR_GRADIENT = 2, + NSVG_PAINT_RADIAL_GRADIENT = 3 +}; + +enum NSVGspreadType { + NSVG_SPREAD_PAD = 0, + NSVG_SPREAD_REFLECT = 1, + NSVG_SPREAD_REPEAT = 2 +}; + +enum NSVGlineJoin { + NSVG_JOIN_MITER = 0, + NSVG_JOIN_ROUND = 1, + NSVG_JOIN_BEVEL = 2 +}; + +enum NSVGlineCap { + NSVG_CAP_BUTT = 0, + NSVG_CAP_ROUND = 1, + NSVG_CAP_SQUARE = 2 +}; + +enum NSVGfillRule { + NSVG_FILLRULE_NONZERO = 0, + NSVG_FILLRULE_EVENODD = 1 +}; + +enum NSVGflags { + NSVG_FLAGS_VISIBLE = 0x01 +}; + +typedef struct NSVGgradientStop { + unsigned int color; + float offset; +} NSVGgradientStop; + +typedef struct NSVGgradient { + float xform[6]; + char spread; + float fx, fy; + int nstops; + NSVGgradientStop stops[1]; +} NSVGgradient; + +typedef struct NSVGpaint { + char type; + union { + unsigned int color; + NSVGgradient* gradient; + }; +} NSVGpaint; + +typedef struct NSVGpath +{ + float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... + int npts; // Total number of bezier points. + char closed; // Flag indicating if shapes should be treated as closed. + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + struct NSVGpath* next; // Pointer to next path, or NULL if last element. +} NSVGpath; + +typedef struct NSVGshape +{ + char id[64]; // Optional 'id' attr of the shape or its group + NSVGpaint fill; // Fill paint + NSVGpaint stroke; // Stroke paint + float opacity; // Opacity of the shape. + float strokeWidth; // Stroke width (scaled). + float strokeDashOffset; // Stroke dash offset (scaled). + float strokeDashArray[8]; // Stroke dash array (scaled). + char strokeDashCount; // Number of dash values in dash array. + char strokeLineJoin; // Stroke join type. + char strokeLineCap; // Stroke cap type. + float miterLimit; // Miter limit + char fillRule; // Fill rule, see NSVGfillRule. + unsigned char flags; // Logical or of NSVG_FLAGS_* flags + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + NSVGpath* paths; // Linked list of paths in the image. + struct NSVGshape* next; // Pointer to next shape, or NULL if last element. +} NSVGshape; + +typedef struct NSVGimage +{ + float width; // Width of the image. + float height; // Height of the image. + NSVGshape* shapes; // Linked list of shapes in the image. +} NSVGimage; + +// Parses SVG file from a file, returns SVG image as paths. +NANOSVG_SCOPE NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); + +// Parses SVG file from a null terminated string, returns SVG image as paths. +// Important note: changes the string. +NANOSVG_SCOPE NSVGimage* nsvgParse(char* input, const char* units, float dpi); + +// Deletes list of paths. +NANOSVG_SCOPE void nsvgDelete(NSVGimage* image); + +#ifdef __cplusplus +} +#endif + +#endif // NANOSVG_H + +#ifdef NANOSVG_IMPLEMENTATION + +#include +#include +#include + +#define NSVG_PI (3.14159265358979323846264338327f) +#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. + +#define NSVG_ALIGN_MIN 0 +#define NSVG_ALIGN_MID 1 +#define NSVG_ALIGN_MAX 2 +#define NSVG_ALIGN_NONE 0 +#define NSVG_ALIGN_MEET 1 +#define NSVG_ALIGN_SLICE 2 + +#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) +#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) + +#ifdef _MSC_VER + #pragma warning (disable: 4996) // Switch off security warnings + #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings + #ifdef __cplusplus + #define NSVG_INLINE inline + #else + #define NSVG_INLINE + #endif + #if !defined(strtoll) // old MSVC versions do not have strtoll() + #define strtoll _strtoi64 + #endif +#else + #define NSVG_INLINE inline +#endif + + +static int nsvg__isspace(char c) +{ + return strchr(" \t\n\v\f\r", c) != 0; +} + +static int nsvg__isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int nsvg__isnum(char c) +{ + return strchr("0123456789+-.eE", c) != 0; +} + +static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } +static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } + + +// Simple XML parser + +#define NSVG_XML_TAG 1 +#define NSVG_XML_CONTENT 2 +#define NSVG_XML_MAX_ATTRIBS 256 + +static void nsvg__parseContent(char* s, + void (*contentCb)(void* ud, const char* s), + void* ud) +{ + // Trim start white spaces + while (*s && nsvg__isspace(*s)) s++; + if (!*s) return; + + if (contentCb) + (*contentCb)(ud, s); +} + +static void nsvg__parseElement(char* s, + void (*startelCb)(void* ud, const char* el, const char** attr), + void (*endelCb)(void* ud, const char* el), + void* ud) +{ + const char* attr[NSVG_XML_MAX_ATTRIBS]; + int nattr = 0; + char* name; + int start = 0; + int end = 0; + char quote; + + // Skip white space after the '<' + while (*s && nsvg__isspace(*s)) s++; + + // Check if the tag is end tag + if (*s == '/') { + s++; + end = 1; + } else { + start = 1; + } + + // Skip comments, data and preprocessor stuff. + if (!*s || *s == '?' || *s == '!') + return; + + // Get tag name + name = s; + while (*s && !nsvg__isspace(*s)) s++; + if (*s) { *s++ = '\0'; } + + // Get attribs + while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) { + char* name = NULL; + char* value = NULL; + + // Skip white space before the attrib name + while (*s && nsvg__isspace(*s)) s++; + if (!*s) break; + if (*s == '/') { + end = 1; + break; + } + name = s; + // Find end of the attrib name. + while (*s && !nsvg__isspace(*s) && *s != '=') s++; + if (*s) { *s++ = '\0'; } + // Skip until the beginning of the value. + while (*s && *s != '\"' && *s != '\'') s++; + if (!*s) break; + quote = *s; + s++; + // Store value and find the end of it. + value = s; + while (*s && *s != quote) s++; + if (*s) { *s++ = '\0'; } + + // Store only well formed attributes + if (name && value) { + attr[nattr++] = name; + attr[nattr++] = value; + } + } + + // List terminator + attr[nattr++] = 0; + attr[nattr++] = 0; + + // Call callbacks. + if (start && startelCb) + (*startelCb)(ud, name, attr); + if (end && endelCb) + (*endelCb)(ud, name); +} + +NANOSVG_SCOPE +int nsvg__parseXML(char* input, + void (*startelCb)(void* ud, const char* el, const char** attr), + void (*endelCb)(void* ud, const char* el), + void (*contentCb)(void* ud, const char* s), + void* ud) +{ + char* s = input; + char* mark = s; + int state = NSVG_XML_CONTENT; + while (*s) { + if (*s == '<' && state == NSVG_XML_CONTENT) { + // Start of a tag + *s++ = '\0'; + nsvg__parseContent(mark, contentCb, ud); + mark = s; + state = NSVG_XML_TAG; + } else if (*s == '>' && state == NSVG_XML_TAG) { + // Start of a content or new tag. + *s++ = '\0'; + nsvg__parseContent(mark, contentCb, ud); + nsvg__parseElement(mark, startelCb, endelCb, ud); + mark = s; + state = NSVG_XML_CONTENT; + } else { + s++; + } + } + + return 1; +} + + +/* Simple SVG parser. */ + +#define NSVG_MAX_ATTR 128 + +enum NSVGgradientUnits { + NSVG_USER_SPACE = 0, + NSVG_OBJECT_SPACE = 1 +}; + +#define NSVG_MAX_DASHES 8 + +enum NSVGunits { + NSVG_UNITS_USER, + NSVG_UNITS_PX, + NSVG_UNITS_PT, + NSVG_UNITS_PC, + NSVG_UNITS_MM, + NSVG_UNITS_CM, + NSVG_UNITS_IN, + NSVG_UNITS_PERCENT, + NSVG_UNITS_EM, + NSVG_UNITS_EX +}; + +enum NSVGvisible { + NSVG_VIS_DISPLAY = 1, + NSVG_VIS_VISIBLE = 2 +}; + +typedef struct NSVGcoordinate { + float value; + int units; +} NSVGcoordinate; + +typedef struct NSVGlinearData { + NSVGcoordinate x1, y1, x2, y2; +} NSVGlinearData; + +typedef struct NSVGradialData { + NSVGcoordinate cx, cy, r, fx, fy; +} NSVGradialData; + +typedef struct NSVGgradientData +{ + char id[64]; + char ref[64]; + char type; + union { + NSVGlinearData linear; + NSVGradialData radial; + }; + char spread; + char units; + float xform[6]; + int nstops; + NSVGgradientStop* stops; + struct NSVGgradientData* next; +} NSVGgradientData; + +typedef struct NSVGattrib +{ + char id[64]; + float xform[6]; + unsigned int fillColor; + unsigned int strokeColor; + float opacity; + float fillOpacity; + float strokeOpacity; + char fillGradient[64]; + char strokeGradient[64]; + float strokeWidth; + float strokeDashOffset; + float strokeDashArray[NSVG_MAX_DASHES]; + int strokeDashCount; + char strokeLineJoin; + char strokeLineCap; + float miterLimit; + char fillRule; + float fontSize; + unsigned int stopColor; + float stopOpacity; + float stopOffset; + char hasFill; + char hasStroke; + char visible; +} NSVGattrib; + +typedef struct NSVGstyles +{ + char* name; + char* description; + struct NSVGstyles* next; +} NSVGstyles; + +typedef struct NSVGparser +{ + NSVGattrib attr[NSVG_MAX_ATTR]; + int attrHead; + float* pts; + int npts; + int cpts; + NSVGpath* plist; + NSVGimage* image; + NSVGstyles* styles; + NSVGgradientData* gradients; + NSVGshape* shapesTail; + float viewMinx, viewMiny, viewWidth, viewHeight; + int alignX, alignY, alignType; + float dpi; + char pathFlag; + char defsFlag; + char styleFlag; +} NSVGparser; + +static void nsvg__xformIdentity(float* t) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetTranslation(float* t, float tx, float ty) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = tx; t[5] = ty; +} + +static void nsvg__xformSetScale(float* t, float sx, float sy) +{ + t[0] = sx; t[1] = 0.0f; + t[2] = 0.0f; t[3] = sy; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetSkewX(float* t, float a) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = tanf(a); t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetSkewY(float* t, float a) +{ + t[0] = 1.0f; t[1] = tanf(a); + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformSetRotation(float* t, float a) +{ + float cs = cosf(a), sn = sinf(a); + t[0] = cs; t[1] = sn; + t[2] = -sn; t[3] = cs; + t[4] = 0.0f; t[5] = 0.0f; +} + +static void nsvg__xformMultiply(float* t, float* s) +{ + float t0 = t[0] * s[0] + t[1] * s[2]; + float t2 = t[2] * s[0] + t[3] * s[2]; + float t4 = t[4] * s[0] + t[5] * s[2] + s[4]; + t[1] = t[0] * s[1] + t[1] * s[3]; + t[3] = t[2] * s[1] + t[3] * s[3]; + t[5] = t[4] * s[1] + t[5] * s[3] + s[5]; + t[0] = t0; + t[2] = t2; + t[4] = t4; +} + +static void nsvg__xformInverse(float* inv, float* t) +{ + double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; + if (det > -1e-6 && det < 1e-6) { + nsvg__xformIdentity(t); + return; + } + invdet = 1.0 / det; + inv[0] = (float)(t[3] * invdet); + inv[2] = (float)(-t[2] * invdet); + inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet); + inv[1] = (float)(-t[1] * invdet); + inv[3] = (float)(t[0] * invdet); + inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet); +} + +static void nsvg__xformPremultiply(float* t, float* s) +{ + float s2[6]; + memcpy(s2, s, sizeof(float)*6); + nsvg__xformMultiply(s2, t); + memcpy(t, s2, sizeof(float)*6); +} + +static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t) +{ + *dx = x*t[0] + y*t[2] + t[4]; + *dy = x*t[1] + y*t[3] + t[5]; +} + +static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t) +{ + *dx = x*t[0] + y*t[2]; + *dy = x*t[1] + y*t[3]; +} + +#define NSVG_EPSILON (1e-12) + +static int nsvg__ptInBounds(float* pt, float* bounds) +{ + return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3]; +} + + +static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) +{ + double it = 1.0-t; + return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3; +} + +static void nsvg__curveBounds(float* bounds, float* curve) +{ + int i, j, count; + double roots[2], a, b, c, b2ac, t, v; + float* v0 = &curve[0]; + float* v1 = &curve[2]; + float* v2 = &curve[4]; + float* v3 = &curve[6]; + + // Start the bounding box by end points + bounds[0] = nsvg__minf(v0[0], v3[0]); + bounds[1] = nsvg__minf(v0[1], v3[1]); + bounds[2] = nsvg__maxf(v0[0], v3[0]); + bounds[3] = nsvg__maxf(v0[1], v3[1]); + + // Bezier curve fits inside the convex hull of it's control points. + // If control points are inside the bounds, we're done. + if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds)) + return; + + // Add bezier curve inflection points in X and Y. + for (i = 0; i < 2; i++) { + a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i]; + b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i]; + c = 3.0 * v1[i] - 3.0 * v0[i]; + count = 0; + if (fabs(a) < NSVG_EPSILON) { + if (fabs(b) > NSVG_EPSILON) { + t = -c / b; + if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) + roots[count++] = t; + } + } else { + b2ac = b*b - 4.0*c*a; + if (b2ac > NSVG_EPSILON) { + t = (-b + sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) + roots[count++] = t; + t = (-b - sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) + roots[count++] = t; + } + } + for (j = 0; j < count; j++) { + v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]); + bounds[0+i] = nsvg__minf(bounds[0+i], (float)v); + bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v); + } + } +} + +static NSVGparser* nsvg__createParser() +{ + NSVGparser* p; + p = (NSVGparser*)NANOSVG_malloc(sizeof(NSVGparser)); + if (p == NULL) goto error; + memset(p, 0, sizeof(NSVGparser)); + + p->image = (NSVGimage*)NANOSVG_malloc(sizeof(NSVGimage)); + if (p->image == NULL) goto error; + memset(p->image, 0, sizeof(NSVGimage)); + + // Init style + nsvg__xformIdentity(p->attr[0].xform); + memset(p->attr[0].id, 0, sizeof p->attr[0].id); + p->attr[0].fillColor = NSVG_RGB(0,0,0); + p->attr[0].strokeColor = NSVG_RGB(0,0,0); + p->attr[0].opacity = 1; + p->attr[0].fillOpacity = 1; + p->attr[0].strokeOpacity = 1; + p->attr[0].stopOpacity = 1; + p->attr[0].strokeWidth = 1; + p->attr[0].strokeLineJoin = NSVG_JOIN_MITER; + p->attr[0].strokeLineCap = NSVG_CAP_BUTT; + p->attr[0].miterLimit = 4; + p->attr[0].fillRule = NSVG_FILLRULE_NONZERO; + p->attr[0].hasFill = 1; + p->attr[0].visible = NSVG_VIS_DISPLAY | NSVG_VIS_VISIBLE; + + return p; + +error: + if (p) { + if (p->image) NANOSVG_free(p->image); + NANOSVG_free(p); + } + return NULL; +} + +static void nsvg__deleteStyles(NSVGstyles* style) { + while (style) { + NSVGstyles *next = style->next; + if (style->name!= NULL) + free(style->name); + if (style->description != NULL) + free(style->description); + free(style); + style = next; + } +} + +static void nsvg__deletePaths(NSVGpath* path) +{ + while (path) { + NSVGpath *next = path->next; + if (path->pts != NULL) + NANOSVG_free(path->pts); + NANOSVG_free(path); + path = next; + } +} + +static void nsvg__deletePaint(NSVGpaint* paint) +{ + if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT) + NANOSVG_free(paint->gradient); +} + +static void nsvg__deleteGradientData(NSVGgradientData* grad) +{ + NSVGgradientData* next; + while (grad != NULL) { + next = grad->next; + NANOSVG_free(grad->stops); + NANOSVG_free(grad); + grad = next; + } +} + +static void nsvg__deleteParser(NSVGparser* p) +{ + if (p != NULL) { + nsvg__deleteStyles(p->styles); + nsvg__deletePaths(p->plist); + nsvg__deleteGradientData(p->gradients); + nsvgDelete(p->image); + NANOSVG_free(p->pts); + NANOSVG_free(p); + } +} + +static void nsvg__resetPath(NSVGparser* p) +{ + p->npts = 0; +} + +static void nsvg__addPoint(NSVGparser* p, float x, float y) +{ + if (p->npts+1 > p->cpts) { + p->cpts = p->cpts ? p->cpts*2 : 8; + p->pts = (float*)NANOSVG_realloc(p->pts, p->cpts*2*sizeof(float)); + if (!p->pts) return; + } + p->pts[p->npts*2+0] = x; + p->pts[p->npts*2+1] = y; + p->npts++; +} + +static void nsvg__moveTo(NSVGparser* p, float x, float y) +{ + if (p->npts > 0) { + p->pts[(p->npts-1)*2+0] = x; + p->pts[(p->npts-1)*2+1] = y; + } else { + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__lineTo(NSVGparser* p, float x, float y) +{ + float px,py, dx,dy; + if (p->npts > 0) { + px = p->pts[(p->npts-1)*2+0]; + py = p->pts[(p->npts-1)*2+1]; + dx = x - px; + dy = y - py; + nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f); + nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f); + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) +{ + nsvg__addPoint(p, cpx1, cpy1); + nsvg__addPoint(p, cpx2, cpy2); + nsvg__addPoint(p, x, y); +} + +static NSVGattrib* nsvg__getAttr(NSVGparser* p) +{ + return &p->attr[p->attrHead]; +} + +static void nsvg__pushAttr(NSVGparser* p) +{ + if (p->attrHead < NSVG_MAX_ATTR-1) { + p->attrHead++; + memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib)); + } +} + +static void nsvg__popAttr(NSVGparser* p) +{ + if (p->attrHead > 0) + p->attrHead--; +} + +static float nsvg__actualOrigX(NSVGparser* p) +{ + return p->viewMinx; +} + +static float nsvg__actualOrigY(NSVGparser* p) +{ + return p->viewMiny; +} + +static float nsvg__actualWidth(NSVGparser* p) +{ + return p->viewWidth; +} + +static float nsvg__actualHeight(NSVGparser* p) +{ + return p->viewHeight; +} + +static float nsvg__actualLength(NSVGparser* p) +{ + float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p); + return sqrtf(w*w + h*h) / sqrtf(2.0f); +} + +static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length) +{ + NSVGattrib* attr = nsvg__getAttr(p); + switch (c.units) { + case NSVG_UNITS_USER: return c.value; + case NSVG_UNITS_PX: return c.value; + case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi; + case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi; + case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi; + case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi; + case NSVG_UNITS_IN: return c.value * p->dpi; + case NSVG_UNITS_EM: return c.value * attr->fontSize; + case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica. + case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length; + default: return c.value; + } + return c.value; +} + +static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) +{ + NSVGgradientData* grad = p->gradients; + while (grad) { + if (strcmp(grad->id, id) == 0) + return grad; + grad = grad->next; + } + return NULL; +} + +static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType) +{ + NSVGattrib* attr = nsvg__getAttr(p); + NSVGgradientData* data = NULL; + NSVGgradientData* ref = NULL; + NSVGgradientStop* stops = NULL; + NSVGgradient* grad; + float ox, oy, sw, sh, sl; + int nstops = 0; + + data = nsvg__findGradientData(p, id); + if (data == NULL) return NULL; + + // TODO: use ref to fill in all unset values too. + ref = data; + while (ref != NULL) { + if (stops == NULL && ref->stops != NULL) { + stops = ref->stops; + nstops = ref->nstops; + break; + } + ref = nsvg__findGradientData(p, ref->ref); + } + if (stops == NULL) return NULL; + + grad = (NSVGgradient*)NANOSVG_malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1)); + if (grad == NULL) return NULL; + + // The shape width and height. + if (data->units == NSVG_OBJECT_SPACE) { + ox = localBounds[0]; + oy = localBounds[1]; + sw = localBounds[2] - localBounds[0]; + sh = localBounds[3] - localBounds[1]; + } else { + ox = nsvg__actualOrigX(p); + oy = nsvg__actualOrigY(p); + sw = nsvg__actualWidth(p); + sh = nsvg__actualHeight(p); + } + sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f); + + if (data->type == NSVG_PAINT_LINEAR_GRADIENT) { + float x1, y1, x2, y2, dx, dy; + x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw); + y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh); + x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw); + y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh); + // Calculate transform aligned to the line + dx = x2 - x1; + dy = y2 - y1; + grad->xform[0] = dy; grad->xform[1] = -dx; + grad->xform[2] = dx; grad->xform[3] = dy; + grad->xform[4] = x1; grad->xform[5] = y1; + } else { + float cx, cy, fx, fy, r; + cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw); + cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh); + fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw); + fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh); + r = nsvg__convertToPixels(p, data->radial.r, 0, sl); + // Calculate transform aligned to the circle + grad->xform[0] = r; grad->xform[1] = 0; + grad->xform[2] = 0; grad->xform[3] = r; + grad->xform[4] = cx; grad->xform[5] = cy; + grad->fx = fx / r; + grad->fy = fy / r; + } + + nsvg__xformMultiply(grad->xform, data->xform); + nsvg__xformMultiply(grad->xform, attr->xform); + + grad->spread = data->spread; + memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop)); + grad->nstops = nstops; + + *paintType = data->type; + + return grad; +} + +static float nsvg__getAverageScale(float* t) +{ + float sx = sqrtf(t[0]*t[0] + t[2]*t[2]); + float sy = sqrtf(t[1]*t[1] + t[3]*t[3]); + return (sx + sy) * 0.5f; +} + +static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform) +{ + NSVGpath* path; + float curve[4*2], curveBounds[4]; + int i, first = 1; + for (path = shape->paths; path != NULL; path = path->next) { + nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform); + for (i = 0; i < path->npts-1; i += 3) { + nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform); + nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform); + nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform); + nsvg__curveBounds(curveBounds, curve); + if (first) { + bounds[0] = curveBounds[0]; + bounds[1] = curveBounds[1]; + bounds[2] = curveBounds[2]; + bounds[3] = curveBounds[3]; + first = 0; + } else { + bounds[0] = nsvg__minf(bounds[0], curveBounds[0]); + bounds[1] = nsvg__minf(bounds[1], curveBounds[1]); + bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]); + bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]); + } + curve[0] = curve[6]; + curve[1] = curve[7]; + } + } +} + +static void nsvg__addShape(NSVGparser* p) +{ + NSVGattrib* attr = nsvg__getAttr(p); + float scale = 1.0f; + NSVGshape* shape; + NSVGpath* path; + int i; + + if (p->plist == NULL) + return; + + shape = (NSVGshape*)NANOSVG_malloc(sizeof(NSVGshape)); + if (shape == NULL) goto error; + memset(shape, 0, sizeof(NSVGshape)); + + memcpy(shape->id, attr->id, sizeof shape->id); + scale = nsvg__getAverageScale(attr->xform); + shape->strokeWidth = attr->strokeWidth * scale; + shape->strokeDashOffset = attr->strokeDashOffset * scale; + shape->strokeDashCount = (char)attr->strokeDashCount; + for (i = 0; i < attr->strokeDashCount; i++) + shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; + shape->strokeLineJoin = attr->strokeLineJoin; + shape->strokeLineCap = attr->strokeLineCap; + shape->miterLimit = attr->miterLimit; + shape->fillRule = attr->fillRule; + shape->opacity = attr->opacity; + + shape->paths = p->plist; + p->plist = NULL; + + // Calculate shape bounds + shape->bounds[0] = shape->paths->bounds[0]; + shape->bounds[1] = shape->paths->bounds[1]; + shape->bounds[2] = shape->paths->bounds[2]; + shape->bounds[3] = shape->paths->bounds[3]; + for (path = shape->paths->next; path != NULL; path = path->next) { + shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]); + shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]); + shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]); + shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]); + } + + // Set fill + if (attr->hasFill == 0) { + shape->fill.type = NSVG_PAINT_NONE; + } else if (attr->hasFill == 1) { + shape->fill.type = NSVG_PAINT_COLOR; + shape->fill.color = attr->fillColor; + shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24; + } else if (attr->hasFill == 2) { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, attr->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type); + if (shape->fill.gradient == NULL) { + shape->fill.type = NSVG_PAINT_NONE; + } + } + + // Set stroke + if (attr->hasStroke == 0) { + shape->stroke.type = NSVG_PAINT_NONE; + } else if (attr->hasStroke == 1) { + shape->stroke.type = NSVG_PAINT_COLOR; + shape->stroke.color = attr->strokeColor; + shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24; + } else if (attr->hasStroke == 2) { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, attr->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type); + if (shape->stroke.gradient == NULL) + shape->stroke.type = NSVG_PAINT_NONE; + } + + // Set flags + shape->flags = ((attr->visible & NSVG_VIS_DISPLAY) && (attr->visible & NSVG_VIS_VISIBLE) ? NSVG_FLAGS_VISIBLE : 0x00); + + // Add to tail + if (p->image->shapes == NULL) + p->image->shapes = shape; + else + p->shapesTail->next = shape; + p->shapesTail = shape; + + return; + +error: + if (shape) NANOSVG_free(shape); +} + +static void nsvg__addPath(NSVGparser* p, char closed) +{ + NSVGattrib* attr = nsvg__getAttr(p); + NSVGpath* path = NULL; + float bounds[4]; + float* curve; + int i; + + if (p->npts < 4) + return; + + if (closed) + nsvg__lineTo(p, p->pts[0], p->pts[1]); + + path = (NSVGpath*)NANOSVG_malloc(sizeof(NSVGpath)); + if (path == NULL) goto error; + memset(path, 0, sizeof(NSVGpath)); + + path->pts = (float*)NANOSVG_malloc(p->npts*2*sizeof(float)); + if (path->pts == NULL) goto error; + path->closed = closed; + path->npts = p->npts; + + // Transform path. + for (i = 0; i < p->npts; ++i) + nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform); + + // Find bounds + for (i = 0; i < path->npts-1; i += 3) { + curve = &path->pts[i*2]; + nsvg__curveBounds(bounds, curve); + if (i == 0) { + path->bounds[0] = bounds[0]; + path->bounds[1] = bounds[1]; + path->bounds[2] = bounds[2]; + path->bounds[3] = bounds[3]; + } else { + path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]); + path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]); + path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]); + path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]); + } + } + + path->next = p->plist; + p->plist = path; + + return; + +error: + if (path != NULL) { + if (path->pts != NULL) NANOSVG_free(path->pts); + NANOSVG_free(path); + } +} + +// We roll our own string to float because the std library one uses locale and messes things up. +static double nsvg__atof(const char* s) +{ + char* cur = (char*)s; + char* end = NULL; + double res = 0.0, sign = 1.0; +#if (_MSC_VER == 1200) + __int64 intPart = 0, fracPart = 0; +#else + long long intPart = 0, fracPart = 0; +#endif + char hasIntPart = 0, hasFracPart = 0; + + // Parse optional sign + if (*cur == '+') { + cur++; + } else if (*cur == '-') { + sign = -1; + cur++; + } + + // Parse integer part + if (nsvg__isdigit(*cur)) { + // Parse digit sequence +#if (_MSC_VER == 1200) + intPart = strtol(cur, &end, 10); +#else + intPart = strtoll(cur, &end, 10); +#endif + if (cur != end) { + res = (double)intPart; + hasIntPart = 1; + cur = end; + } + } + + // Parse fractional part. + if (*cur == '.') { + cur++; // Skip '.' + if (nsvg__isdigit(*cur)) { + // Parse digit sequence +#if (_MSC_VER == 1200) + fracPart = strtol(cur, &end, 10); +#else + fracPart = strtoll(cur, &end, 10); +#endif + if (cur != end) { + res += (double)fracPart / pow(10.0, (double)(end - cur)); + hasFracPart = 1; + cur = end; + } + } + } + + // A valid number should have integer or fractional part. + if (!hasIntPart && !hasFracPart) + return 0.0; + + // Parse optional exponent + if (*cur == 'e' || *cur == 'E') { + int expPart = 0; + cur++; // skip 'E' + expPart = strtol(cur, &end, 10); // Parse digit sequence with sign + if (cur != end) { + res *= pow(10.0, (double)expPart); + } + } + + return res * sign; +} + + +static const char* nsvg__parseNumber(const char* s, char* it, const int size) +{ + const int last = size-1; + int i = 0; + + // sign + if (*s == '-' || *s == '+') { + if (i < last) it[i++] = *s; + s++; + } + // integer part + while (*s && nsvg__isdigit(*s)) { + if (i < last) it[i++] = *s; + s++; + } + if (*s == '.') { + // decimal point + if (i < last) it[i++] = *s; + s++; + // fraction part + while (*s && nsvg__isdigit(*s)) { + if (i < last) it[i++] = *s; + s++; + } + } + // exponent + if (*s == 'e' || *s == 'E') { + if (i < last) it[i++] = *s; + s++; + if (*s == '-' || *s == '+') { + if (i < last) it[i++] = *s; + s++; + } + while (*s && nsvg__isdigit(*s)) { + if (i < last) it[i++] = *s; + s++; + } + } + it[i] = '\0'; + + return s; +} + +static const char* nsvg__getNextPathItem(const char* s, char* it) +{ + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) s++; + if (!*s) return s; + if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { + s = nsvg__parseNumber(s, it, 64); + } else { + // Parse command + it[0] = *s++; + it[1] = '\0'; + return s; + } + + return s; +} + +static unsigned int nsvg__parseColorHex(const char* str) +{ + unsigned int c = 0, r = 0, g = 0, b = 0; + int n = 0; + str++; // skip # + // Calculate number of characters. + while(str[n] && !nsvg__isspace(str[n])) + n++; + if (n == 6) { + sscanf(str, "%x", &c); + } else if (n == 3) { + sscanf(str, "%x", &c); + c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8); + c |= c<<4; + } + r = (c >> 16) & 0xff; + g = (c >> 8) & 0xff; + b = c & 0xff; + return NSVG_RGB(r,g,b); +} + +static unsigned int nsvg__parseColorRGB(const char* str) +{ + int r = -1, g = -1, b = -1; + char s1[32]="", s2[32]=""; + sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b); + if (strchr(s1, '%')) { + return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100); + } else { + return NSVG_RGB(r,g,b); + } +} + +typedef struct NSVGNamedColor { + const char* name; + unsigned int color; +} NSVGNamedColor; + +NSVGNamedColor nsvg__colors[] = { + + { "red", NSVG_RGB(255, 0, 0) }, + { "green", NSVG_RGB( 0, 128, 0) }, + { "blue", NSVG_RGB( 0, 0, 255) }, + { "yellow", NSVG_RGB(255, 255, 0) }, + { "cyan", NSVG_RGB( 0, 255, 255) }, + { "magenta", NSVG_RGB(255, 0, 255) }, + { "black", NSVG_RGB( 0, 0, 0) }, + { "grey", NSVG_RGB(128, 128, 128) }, + { "gray", NSVG_RGB(128, 128, 128) }, + { "white", NSVG_RGB(255, 255, 255) }, + +#ifdef NANOSVG_ALL_COLOR_KEYWORDS + { "aliceblue", NSVG_RGB(240, 248, 255) }, + { "antiquewhite", NSVG_RGB(250, 235, 215) }, + { "aqua", NSVG_RGB( 0, 255, 255) }, + { "aquamarine", NSVG_RGB(127, 255, 212) }, + { "azure", NSVG_RGB(240, 255, 255) }, + { "beige", NSVG_RGB(245, 245, 220) }, + { "bisque", NSVG_RGB(255, 228, 196) }, + { "blanchedalmond", NSVG_RGB(255, 235, 205) }, + { "blueviolet", NSVG_RGB(138, 43, 226) }, + { "brown", NSVG_RGB(165, 42, 42) }, + { "burlywood", NSVG_RGB(222, 184, 135) }, + { "cadetblue", NSVG_RGB( 95, 158, 160) }, + { "chartreuse", NSVG_RGB(127, 255, 0) }, + { "chocolate", NSVG_RGB(210, 105, 30) }, + { "coral", NSVG_RGB(255, 127, 80) }, + { "cornflowerblue", NSVG_RGB(100, 149, 237) }, + { "cornsilk", NSVG_RGB(255, 248, 220) }, + { "crimson", NSVG_RGB(220, 20, 60) }, + { "darkblue", NSVG_RGB( 0, 0, 139) }, + { "darkcyan", NSVG_RGB( 0, 139, 139) }, + { "darkgoldenrod", NSVG_RGB(184, 134, 11) }, + { "darkgray", NSVG_RGB(169, 169, 169) }, + { "darkgreen", NSVG_RGB( 0, 100, 0) }, + { "darkgrey", NSVG_RGB(169, 169, 169) }, + { "darkkhaki", NSVG_RGB(189, 183, 107) }, + { "darkmagenta", NSVG_RGB(139, 0, 139) }, + { "darkolivegreen", NSVG_RGB( 85, 107, 47) }, + { "darkorange", NSVG_RGB(255, 140, 0) }, + { "darkorchid", NSVG_RGB(153, 50, 204) }, + { "darkred", NSVG_RGB(139, 0, 0) }, + { "darksalmon", NSVG_RGB(233, 150, 122) }, + { "darkseagreen", NSVG_RGB(143, 188, 143) }, + { "darkslateblue", NSVG_RGB( 72, 61, 139) }, + { "darkslategray", NSVG_RGB( 47, 79, 79) }, + { "darkslategrey", NSVG_RGB( 47, 79, 79) }, + { "darkturquoise", NSVG_RGB( 0, 206, 209) }, + { "darkviolet", NSVG_RGB(148, 0, 211) }, + { "deeppink", NSVG_RGB(255, 20, 147) }, + { "deepskyblue", NSVG_RGB( 0, 191, 255) }, + { "dimgray", NSVG_RGB(105, 105, 105) }, + { "dimgrey", NSVG_RGB(105, 105, 105) }, + { "dodgerblue", NSVG_RGB( 30, 144, 255) }, + { "firebrick", NSVG_RGB(178, 34, 34) }, + { "floralwhite", NSVG_RGB(255, 250, 240) }, + { "forestgreen", NSVG_RGB( 34, 139, 34) }, + { "fuchsia", NSVG_RGB(255, 0, 255) }, + { "gainsboro", NSVG_RGB(220, 220, 220) }, + { "ghostwhite", NSVG_RGB(248, 248, 255) }, + { "gold", NSVG_RGB(255, 215, 0) }, + { "goldenrod", NSVG_RGB(218, 165, 32) }, + { "greenyellow", NSVG_RGB(173, 255, 47) }, + { "honeydew", NSVG_RGB(240, 255, 240) }, + { "hotpink", NSVG_RGB(255, 105, 180) }, + { "indianred", NSVG_RGB(205, 92, 92) }, + { "indigo", NSVG_RGB( 75, 0, 130) }, + { "ivory", NSVG_RGB(255, 255, 240) }, + { "khaki", NSVG_RGB(240, 230, 140) }, + { "lavender", NSVG_RGB(230, 230, 250) }, + { "lavenderblush", NSVG_RGB(255, 240, 245) }, + { "lawngreen", NSVG_RGB(124, 252, 0) }, + { "lemonchiffon", NSVG_RGB(255, 250, 205) }, + { "lightblue", NSVG_RGB(173, 216, 230) }, + { "lightcoral", NSVG_RGB(240, 128, 128) }, + { "lightcyan", NSVG_RGB(224, 255, 255) }, + { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) }, + { "lightgray", NSVG_RGB(211, 211, 211) }, + { "lightgreen", NSVG_RGB(144, 238, 144) }, + { "lightgrey", NSVG_RGB(211, 211, 211) }, + { "lightpink", NSVG_RGB(255, 182, 193) }, + { "lightsalmon", NSVG_RGB(255, 160, 122) }, + { "lightseagreen", NSVG_RGB( 32, 178, 170) }, + { "lightskyblue", NSVG_RGB(135, 206, 250) }, + { "lightslategray", NSVG_RGB(119, 136, 153) }, + { "lightslategrey", NSVG_RGB(119, 136, 153) }, + { "lightsteelblue", NSVG_RGB(176, 196, 222) }, + { "lightyellow", NSVG_RGB(255, 255, 224) }, + { "lime", NSVG_RGB( 0, 255, 0) }, + { "limegreen", NSVG_RGB( 50, 205, 50) }, + { "linen", NSVG_RGB(250, 240, 230) }, + { "maroon", NSVG_RGB(128, 0, 0) }, + { "mediumaquamarine", NSVG_RGB(102, 205, 170) }, + { "mediumblue", NSVG_RGB( 0, 0, 205) }, + { "mediumorchid", NSVG_RGB(186, 85, 211) }, + { "mediumpurple", NSVG_RGB(147, 112, 219) }, + { "mediumseagreen", NSVG_RGB( 60, 179, 113) }, + { "mediumslateblue", NSVG_RGB(123, 104, 238) }, + { "mediumspringgreen", NSVG_RGB( 0, 250, 154) }, + { "mediumturquoise", NSVG_RGB( 72, 209, 204) }, + { "mediumvioletred", NSVG_RGB(199, 21, 133) }, + { "midnightblue", NSVG_RGB( 25, 25, 112) }, + { "mintcream", NSVG_RGB(245, 255, 250) }, + { "mistyrose", NSVG_RGB(255, 228, 225) }, + { "moccasin", NSVG_RGB(255, 228, 181) }, + { "navajowhite", NSVG_RGB(255, 222, 173) }, + { "navy", NSVG_RGB( 0, 0, 128) }, + { "oldlace", NSVG_RGB(253, 245, 230) }, + { "olive", NSVG_RGB(128, 128, 0) }, + { "olivedrab", NSVG_RGB(107, 142, 35) }, + { "orange", NSVG_RGB(255, 165, 0) }, + { "orangered", NSVG_RGB(255, 69, 0) }, + { "orchid", NSVG_RGB(218, 112, 214) }, + { "palegoldenrod", NSVG_RGB(238, 232, 170) }, + { "palegreen", NSVG_RGB(152, 251, 152) }, + { "paleturquoise", NSVG_RGB(175, 238, 238) }, + { "palevioletred", NSVG_RGB(219, 112, 147) }, + { "papayawhip", NSVG_RGB(255, 239, 213) }, + { "peachpuff", NSVG_RGB(255, 218, 185) }, + { "peru", NSVG_RGB(205, 133, 63) }, + { "pink", NSVG_RGB(255, 192, 203) }, + { "plum", NSVG_RGB(221, 160, 221) }, + { "powderblue", NSVG_RGB(176, 224, 230) }, + { "purple", NSVG_RGB(128, 0, 128) }, + { "rosybrown", NSVG_RGB(188, 143, 143) }, + { "royalblue", NSVG_RGB( 65, 105, 225) }, + { "saddlebrown", NSVG_RGB(139, 69, 19) }, + { "salmon", NSVG_RGB(250, 128, 114) }, + { "sandybrown", NSVG_RGB(244, 164, 96) }, + { "seagreen", NSVG_RGB( 46, 139, 87) }, + { "seashell", NSVG_RGB(255, 245, 238) }, + { "sienna", NSVG_RGB(160, 82, 45) }, + { "silver", NSVG_RGB(192, 192, 192) }, + { "skyblue", NSVG_RGB(135, 206, 235) }, + { "slateblue", NSVG_RGB(106, 90, 205) }, + { "slategray", NSVG_RGB(112, 128, 144) }, + { "slategrey", NSVG_RGB(112, 128, 144) }, + { "snow", NSVG_RGB(255, 250, 250) }, + { "springgreen", NSVG_RGB( 0, 255, 127) }, + { "steelblue", NSVG_RGB( 70, 130, 180) }, + { "tan", NSVG_RGB(210, 180, 140) }, + { "teal", NSVG_RGB( 0, 128, 128) }, + { "thistle", NSVG_RGB(216, 191, 216) }, + { "tomato", NSVG_RGB(255, 99, 71) }, + { "turquoise", NSVG_RGB( 64, 224, 208) }, + { "violet", NSVG_RGB(238, 130, 238) }, + { "wheat", NSVG_RGB(245, 222, 179) }, + { "whitesmoke", NSVG_RGB(245, 245, 245) }, + { "yellowgreen", NSVG_RGB(154, 205, 50) }, +#endif +}; + +static unsigned int nsvg__parseColorName(const char* str) +{ + int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor); + + for (i = 0; i < ncolors; i++) { + if (strcmp(nsvg__colors[i].name, str) == 0) { + return nsvg__colors[i].color; + } + } + + return NSVG_RGB(128, 128, 128); +} + +static unsigned int nsvg__parseColor(const char* str) +{ + size_t len = 0; + while(*str == ' ') ++str; + len = strlen(str); + if (len >= 1 && *str == '#') + return nsvg__parseColorHex(str); + else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(') + return nsvg__parseColorRGB(str); + return nsvg__parseColorName(str); +} + +static float nsvg__parseOpacity(const char* str) +{ + float val = 0; + sscanf(str, "%f", &val); + if (val < 0.0f) val = 0.0f; + if (val > 1.0f) val = 1.0f; + return val; +} + +static float nsvg__parseMiterLimit(const char* str) +{ + float val = 0; + sscanf(str, "%f", &val); + if (val < 0.0f) val = 0.0f; + return val; +} + +static int nsvg__parseUnits(const char* units) +{ + if (units[0] == 'p' && units[1] == 'x') + return NSVG_UNITS_PX; + else if (units[0] == 'p' && units[1] == 't') + return NSVG_UNITS_PT; + else if (units[0] == 'p' && units[1] == 'c') + return NSVG_UNITS_PC; + else if (units[0] == 'm' && units[1] == 'm') + return NSVG_UNITS_MM; + else if (units[0] == 'c' && units[1] == 'm') + return NSVG_UNITS_CM; + else if (units[0] == 'i' && units[1] == 'n') + return NSVG_UNITS_IN; + else if (units[0] == '%') + return NSVG_UNITS_PERCENT; + else if (units[0] == 'e' && units[1] == 'm') + return NSVG_UNITS_EM; + else if (units[0] == 'e' && units[1] == 'x') + return NSVG_UNITS_EX; + return NSVG_UNITS_USER; +} + +static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) +{ + NSVGcoordinate coord = {0, NSVG_UNITS_USER}; + char units[32]=""; + sscanf(str, "%f%s", &coord.value, units); + coord.units = nsvg__parseUnits(units); + return coord; +} + +static NSVGcoordinate nsvg__coord(float v, int units) +{ + NSVGcoordinate coord = {v, units}; + return coord; +} + +static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length) +{ + NSVGcoordinate coord = nsvg__parseCoordinateRaw(str); + return nsvg__convertToPixels(p, coord, orig, length); +} + +static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) +{ + const char* end; + const char* ptr; + char it[64]; + + *na = 0; + ptr = str; + while (*ptr && *ptr != '(') ++ptr; + if (*ptr == 0) + return 1; + end = ptr; + while (*end && *end != ')') ++end; + if (*end == 0) + return 1; + + while (ptr < end) { + if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) { + if (*na >= maxNa) return 0; + ptr = nsvg__parseNumber(ptr, it, 64); + args[(*na)++] = (float)nsvg__atof(it); + } else { + ++ptr; + } + } + return (int)(end - str); +} + + +static int nsvg__parseMatrix(float* xform, const char* str) +{ + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, t, 6, &na); + if (na != 6) return len; + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseTranslate(float* xform, const char* str) +{ + float args[2]; + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) args[1] = 0.0; + + nsvg__xformSetTranslation(t, args[0], args[1]); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseScale(float* xform, const char* str) +{ + float args[2]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) args[1] = args[0]; + nsvg__xformSetScale(t, args[0], args[1]); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseSkewX(float* xform, const char* str) +{ + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseSkewY(float* xform, const char* str) +{ + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI); + memcpy(xform, t, sizeof(float)*6); + return len; +} + +static int nsvg__parseRotate(float* xform, const char* str) +{ + float args[3]; + int na = 0; + float m[6]; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 3, &na); + if (na == 1) + args[1] = args[2] = 0.0f; + nsvg__xformIdentity(m); + + if (na > 1) { + nsvg__xformSetTranslation(t, -args[1], -args[2]); + nsvg__xformMultiply(m, t); + } + + nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI); + nsvg__xformMultiply(m, t); + + if (na > 1) { + nsvg__xformSetTranslation(t, args[1], args[2]); + nsvg__xformMultiply(m, t); + } + + memcpy(xform, m, sizeof(float)*6); + + return len; +} + +static void nsvg__parseTransform(float* xform, const char* str) +{ + float t[6]; + nsvg__xformIdentity(xform); + while (*str) + { + if (strncmp(str, "matrix", 6) == 0) + str += nsvg__parseMatrix(t, str); + else if (strncmp(str, "translate", 9) == 0) + str += nsvg__parseTranslate(t, str); + else if (strncmp(str, "scale", 5) == 0) + str += nsvg__parseScale(t, str); + else if (strncmp(str, "rotate", 6) == 0) + str += nsvg__parseRotate(t, str); + else if (strncmp(str, "skewX", 5) == 0) + str += nsvg__parseSkewX(t, str); + else if (strncmp(str, "skewY", 5) == 0) + str += nsvg__parseSkewY(t, str); + else{ + ++str; + continue; + } + + nsvg__xformPremultiply(xform, t); + } +} + +static void nsvg__parseUrl(char* id, const char* str) +{ + int i = 0; + str += 4; // "url("; + if (*str == '#') + str++; + while (i < 63 && *str != ')') { + id[i] = *str++; + i++; + } + id[i] = '\0'; +} + +static char nsvg__parseLineCap(const char* str) +{ + if (strcmp(str, "butt") == 0) + return NSVG_CAP_BUTT; + else if (strcmp(str, "round") == 0) + return NSVG_CAP_ROUND; + else if (strcmp(str, "square") == 0) + return NSVG_CAP_SQUARE; + // TODO: handle inherit. + return NSVG_CAP_BUTT; +} + +static char nsvg__parseLineJoin(const char* str) +{ + if (strcmp(str, "miter") == 0) + return NSVG_JOIN_MITER; + else if (strcmp(str, "round") == 0) + return NSVG_JOIN_ROUND; + else if (strcmp(str, "bevel") == 0) + return NSVG_JOIN_BEVEL; + // TODO: handle inherit. + return NSVG_JOIN_MITER; +} + +static char nsvg__parseFillRule(const char* str) +{ + if (strcmp(str, "nonzero") == 0) + return NSVG_FILLRULE_NONZERO; + else if (strcmp(str, "evenodd") == 0) + return NSVG_FILLRULE_EVENODD; + // TODO: handle inherit. + return NSVG_FILLRULE_NONZERO; +} + +static const char* nsvg__getNextDashItem(const char* s, char* it) +{ + int n = 0; + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) s++; + // Advance until whitespace, comma or end. + while (*s && (!nsvg__isspace(*s) && *s != ',')) { + if (n < 63) + it[n++] = *s; + s++; + } + it[n++] = '\0'; + return s; +} + +static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) +{ + char item[64]; + int count = 0, i; + float sum = 0.0f; + + // Handle "none" + if (str[0] == 'n') + return 0; + + // Parse dashes + while (*str) { + str = nsvg__getNextDashItem(str, item); + if (!*item) break; + if (count < NSVG_MAX_DASHES) + strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p))); + } + + for (i = 0; i < count; i++) + sum += strokeDashArray[i]; + if (sum <= 1e-6f) + count = 0; + + return count; +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str); + +static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) +{ + float xform[6]; + NSVGattrib* attr = nsvg__getAttr(p); + if (!attr) return 0; + + if (strcmp(name, "style") == 0) { + nsvg__parseStyle(p, value); + } else if (strcmp(name, "display") == 0) { + if (strcmp(value, "none") == 0) + attr->visible &= ~NSVG_VIS_DISPLAY; + // Don't reset ->visible on display:inline, one display:none hides the whole subtree + + } else if (strcmp(name, "visibility") == 0) { + if (strcmp(value, "hidden") == 0) { + attr->visible &= ~NSVG_VIS_VISIBLE; + } else if (strcmp(value, "visible") == 0) { + attr->visible |= NSVG_VIS_VISIBLE; + } + } else if (strcmp(name, "fill") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasFill = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasFill = 2; + nsvg__parseUrl(attr->fillGradient, value); + } else { + attr->hasFill = 1; + attr->fillColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "opacity") == 0) { + attr->opacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "fill-opacity") == 0) { + attr->fillOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasStroke = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasStroke = 2; + nsvg__parseUrl(attr->strokeGradient, value); + } else { + attr->hasStroke = 1; + attr->strokeColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "stroke-width") == 0) { + attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-dasharray") == 0) { + attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray); + } else if (strcmp(name, "stroke-dashoffset") == 0) { + attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-opacity") == 0) { + attr->strokeOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke-linecap") == 0) { + attr->strokeLineCap = nsvg__parseLineCap(value); + } else if (strcmp(name, "stroke-linejoin") == 0) { + attr->strokeLineJoin = nsvg__parseLineJoin(value); + } else if (strcmp(name, "stroke-miterlimit") == 0) { + attr->miterLimit = nsvg__parseMiterLimit(value); + } else if (strcmp(name, "fill-rule") == 0) { + attr->fillRule = nsvg__parseFillRule(value); + } else if (strcmp(name, "font-size") == 0) { + attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "transform") == 0) { + nsvg__parseTransform(xform, value); + nsvg__xformPremultiply(attr->xform, xform); + } else if (strcmp(name, "stop-color") == 0) { + attr->stopColor = nsvg__parseColor(value); + } else if (strcmp(name, "stop-opacity") == 0) { + attr->stopOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "offset") == 0) { + attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f); + } else if (strcmp(name, "id") == 0) { + strncpy(attr->id, value, 63); + attr->id[63] = '\0'; + } else if (strcmp(name, "class") == 0) { + NSVGstyles* style = p->styles; + while (style) { + if (strcmp(style->name + 1, value) == 0) { + break; + } + style = style->next; + } + if (style) { + nsvg__parseStyle(p, style->description); + } + } else { + return 0; + } + return 1; +} + +static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end) +{ + const char* str; + const char* val; + char name[512]; + char value[512]; + int n; + + str = start; + while (str < end && *str != ':') ++str; + + val = str; + + // Right Trim + while (str > start && (*str == ':' || nsvg__isspace(*str))) --str; + ++str; + + n = (int)(str - start); + if (n > 511) n = 511; + if (n) memcpy(name, start, n); + name[n] = 0; + + while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val; + + n = (int)(end - val); + if (n > 511) n = 511; + if (n) memcpy(value, val, n); + value[n] = 0; + + return nsvg__parseAttr(p, name, value); +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str) +{ + const char* start; + const char* end; + + while (*str) { + // Left Trim + while(*str && nsvg__isspace(*str)) ++str; + start = str; + while(*str && *str != ';') ++str; + end = str; + + // Right Trim + while (end > start && (*end == ';' || nsvg__isspace(*end))) --end; + ++end; + + nsvg__parseNameValue(p, start, end); + if (*str) ++str; + } +} + +static void nsvg__parseAttribs(NSVGparser* p, const char** attr) +{ + int i; + for (i = 0; attr[i]; i += 2) + { + if (strcmp(attr[i], "style") == 0) + nsvg__parseStyle(p, attr[i + 1]); + else + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } +} + +static int nsvg__getArgsPerElement(char cmd) +{ + switch (cmd) { + case 'v': + case 'V': + case 'h': + case 'H': + return 1; + case 'm': + case 'M': + case 'l': + case 'L': + case 't': + case 'T': + return 2; + case 'q': + case 'Q': + case 's': + case 'S': + return 4; + case 'c': + case 'C': + return 6; + case 'a': + case 'A': + return 7; + } + return 0; +} + +static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__moveTo(p, *cpx, *cpy); +} + +static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) + *cpx += args[0]; + else + *cpx = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + if (rel) + *cpy += args[0]; + else + *cpy = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x2, y2, cx1, cy1, cx2, cy2; + + if (rel) { + cx1 = *cpx + args[0]; + cy1 = *cpy + args[1]; + cx2 = *cpx + args[2]; + cy2 = *cpy + args[3]; + x2 = *cpx + args[4]; + y2 = *cpy + args[5]; + } else { + cx1 = args[0]; + cy1 = args[1]; + cx2 = args[2]; + cy2 = args[3]; + x2 = args[4]; + y2 = args[5]; + } + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x1, y1, x2, y2, cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx2 = *cpx + args[0]; + cy2 = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx2 = args[0]; + cy2 = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + cx1 = 2*x1 - *cpx2; + cy1 = 2*y1 - *cpy2; + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx = *cpx + args[0]; + cy = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx = args[0]; + cy = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + // Convert to cubic bezier + cx1 = x1 + 2.0f/3.0f*(cx - x1); + cy1 = y1 + 2.0f/3.0f*(cy - y1); + cx2 = x2 + 2.0f/3.0f*(cx - x2); + cy2 = y2 + 2.0f/3.0f*(cy - y2); + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy, + float* cpx2, float* cpy2, float* args, int rel) +{ + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + x2 = *cpx + args[0]; + y2 = *cpy + args[1]; + } else { + x2 = args[0]; + y2 = args[1]; + } + + cx = 2*x1 - *cpx2; + cy = 2*y1 - *cpy2; + + // Convert to cubix bezier + cx1 = x1 + 2.0f/3.0f*(cx - x1); + cy1 = y1 + 2.0f/3.0f*(cy - y1); + cx2 = x2 + 2.0f/3.0f*(cx - x2); + cy2 = y2 + 2.0f/3.0f*(cy - y2); + + nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static float nsvg__sqr(float x) { return x*x; } +static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); } + +static float nsvg__vecrat(float ux, float uy, float vx, float vy) +{ + return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy)); +} + +static float nsvg__vecang(float ux, float uy, float vx, float vy) +{ + float r = nsvg__vecrat(ux,uy, vx,vy); + if (r < -1.0f) r = -1.0f; + if (r > 1.0f) r = 1.0f; + return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r); +} + +static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) +{ + // Ported from canvg (https://code.google.com/p/canvg/) + float rx, ry, rotx; + float x1, y1, x2, y2, cx, cy, dx, dy, d; + float x1p, y1p, cxp, cyp, s, sa, sb; + float ux, uy, vx, vy, a1, da; + float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6]; + float sinrx, cosrx; + int fa, fs; + int i, ndivs; + float hda, kappa; + + rx = fabsf(args[0]); // y radius + ry = fabsf(args[1]); // x radius + rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle + fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc + fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction + x1 = *cpx; // start point + y1 = *cpy; + if (rel) { // end point + x2 = *cpx + args[5]; + y2 = *cpy + args[6]; + } else { + x2 = args[5]; + y2 = args[6]; + } + + dx = x1 - x2; + dy = y1 - y2; + d = sqrtf(dx*dx + dy*dy); + if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) { + // The arc degenerates to a line + nsvg__lineTo(p, x2, y2); + *cpx = x2; + *cpy = y2; + return; + } + + sinrx = sinf(rotx); + cosrx = cosf(rotx); + + // Convert to center point parameterization. + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // 1) Compute x1', y1' + x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f; + y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f; + d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry); + if (d > 1) { + d = sqrtf(d); + rx *= d; + ry *= d; + } + // 2) Compute cx', cy' + s = 0.0f; + sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p); + sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p); + if (sa < 0.0f) sa = 0.0f; + if (sb > 0.0f) + s = sqrtf(sa / sb); + if (fa == fs) + s = -s; + cxp = s * rx * y1p / ry; + cyp = s * -ry * x1p / rx; + + // 3) Compute cx,cy from cx',cy' + cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp; + cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp; + + // 4) Calculate theta1, and delta theta. + ux = (x1p - cxp) / rx; + uy = (y1p - cyp) / ry; + vx = (-x1p - cxp) / rx; + vy = (-y1p - cyp) / ry; + a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle + da = nsvg__vecang(ux,uy, vx,vy); // Delta angle + +// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; +// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; + + if (fs == 0 && da > 0) + da -= 2 * NSVG_PI; + else if (fs == 1 && da < 0) + da += 2 * NSVG_PI; + + // Approximate the arc using cubic spline segments. + t[0] = cosrx; t[1] = sinrx; + t[2] = -sinrx; t[3] = cosrx; + t[4] = cx; t[5] = cy; + + // Split arc into max 90 degree segments. + // The loop assumes an iteration per end point (including start and end), this +1. + ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f); + hda = (da / (float)ndivs) / 2.0f; + kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda)); + if (da < 0.0f) + kappa = -kappa; + + for (i = 0; i <= ndivs; i++) { + a = a1 + da * ((float)i/(float)ndivs); + dx = cosf(a); + dy = sinf(a); + nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position + nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent + if (i > 0) + nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y); + px = x; + py = y; + ptanx = tanx; + ptany = tany; + } + + *cpx = x2; + *cpy = y2; +} + +static void nsvg__parsePath(NSVGparser* p, const char** attr) +{ + const char* s = NULL; + char cmd = '\0'; + float args[10]; + int nargs; + int rargs = 0; + float cpx, cpy, cpx2, cpy2; + const char* tmp[4]; + char closedFlag; + int i; + char item[64]; + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "d") == 0) { + s = attr[i + 1]; + } else { + tmp[0] = attr[i]; + tmp[1] = attr[i + 1]; + tmp[2] = 0; + tmp[3] = 0; + nsvg__parseAttribs(p, tmp); + } + } + + if (s) { + nsvg__resetPath(p); + cpx = 0; cpy = 0; + cpx2 = 0; cpy2 = 0; + closedFlag = 0; + nargs = 0; + + while (*s) { + s = nsvg__getNextPathItem(s, item); + if (!*item) break; + if (nsvg__isnum(item[0])) { + if (nargs < 10) + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= rargs) { + switch (cmd) { + case 'm': + case 'M': + nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); + // Moveto can be followed by multiple coordinate pairs, + // which should be treated as linetos. + cmd = (cmd == 'm') ? 'l' : 'L'; + rargs = nsvg__getArgsPerElement(cmd); + cpx2 = cpx; cpy2 = cpy; + break; + case 'l': + case 'L': + nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + case 'H': + case 'h': + nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + case 'V': + case 'v': + nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + case 'C': + case 'c': + nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); + break; + case 'S': + case 's': + nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); + break; + case 'Q': + case 'q': + nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); + break; + case 'T': + case 't': + nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0); + break; + case 'A': + case 'a': + nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0); + cpx2 = cpx; cpy2 = cpy; + break; + default: + if (nargs >= 2) { + cpx = args[nargs-2]; + cpy = args[nargs-1]; + cpx2 = cpx; cpy2 = cpy; + } + break; + } + nargs = 0; + } + } else { + cmd = item[0]; + rargs = nsvg__getArgsPerElement(cmd); + if (cmd == 'M' || cmd == 'm') { + // Commit path. + if (p->npts > 0) + nsvg__addPath(p, closedFlag); + // Start new subpath. + nsvg__resetPath(p); + closedFlag = 0; + nargs = 0; + } else if (cmd == 'Z' || cmd == 'z') { + closedFlag = 1; + // Commit path. + if (p->npts > 0) { + // Move current point to first point + cpx = p->pts[0]; + cpy = p->pts[1]; + cpx2 = cpx; cpy2 = cpy; + nsvg__addPath(p, closedFlag); + } + // Start new subpath. + nsvg__resetPath(p); + nsvg__moveTo(p, cpx, cpy); + closedFlag = 0; + nargs = 0; + } + } + } + // Commit path. + if (p->npts) + nsvg__addPath(p, closedFlag); + } + + nsvg__addShape(p); +} + +static void nsvg__parseRect(NSVGparser* p, const char** attr) +{ + float x = 0.0f; + float y = 0.0f; + float w = 0.0f; + float h = 0.0f; + float rx = -1.0f; // marks not set + float ry = -1.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)); + if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx < 0.0f && ry > 0.0f) rx = ry; + if (ry < 0.0f && rx > 0.0f) ry = rx; + if (rx < 0.0f) rx = 0.0f; + if (ry < 0.0f) ry = 0.0f; + if (rx > w/2.0f) rx = w/2.0f; + if (ry > h/2.0f) ry = h/2.0f; + + if (w != 0.0f && h != 0.0f) { + nsvg__resetPath(p); + + if (rx < 0.00001f || ry < 0.0001f) { + nsvg__moveTo(p, x, y); + nsvg__lineTo(p, x+w, y); + nsvg__lineTo(p, x+w, y+h); + nsvg__lineTo(p, x, y+h); + } else { + // Rounded rectangle + nsvg__moveTo(p, x+rx, y); + nsvg__lineTo(p, x+w-rx, y); + nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry); + nsvg__lineTo(p, x+w, y+h-ry); + nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h); + nsvg__lineTo(p, x+rx, y+h); + nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry); + nsvg__lineTo(p, x, y+ry); + nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y); + } + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseCircle(NSVGparser* p, const char** attr) +{ + float cx = 0.0f; + float cy = 0.0f; + float r = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p))); + } + } + + if (r > 0.0f) { + nsvg__resetPath(p); + + nsvg__moveTo(p, cx+r, cy); + nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r); + nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy); + nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r); + nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseEllipse(NSVGparser* p, const char** attr) +{ + float cx = 0.0f; + float cy = 0.0f; + float rx = 0.0f; + float ry = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx > 0.0f && ry > 0.0f) { + + nsvg__resetPath(p); + + nsvg__moveTo(p, cx+rx, cy); + nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry); + nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy); + nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry); + nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseLine(NSVGparser* p, const char** attr) +{ + float x1 = 0.0; + float y1 = 0.0; + float x2 = 0.0; + float y2 = 0.0; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + } + } + + nsvg__resetPath(p); + + nsvg__moveTo(p, x1, y1); + nsvg__lineTo(p, x2, y2); + + nsvg__addPath(p, 0); + + nsvg__addShape(p); +} + +static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) +{ + int i; + const char* s; + float args[2]; + int nargs, npts = 0; + char item[64]; + + nsvg__resetPath(p); + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "points") == 0) { + s = attr[i + 1]; + nargs = 0; + while (*s) { + s = nsvg__getNextPathItem(s, item); + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= 2) { + if (npts == 0) + nsvg__moveTo(p, args[0], args[1]); + else + nsvg__lineTo(p, args[0], args[1]); + nargs = 0; + npts++; + } + } + } + } + } + + nsvg__addPath(p, (char)closeFlag); + + nsvg__addShape(p); +} + +static void nsvg__parseSVG(NSVGparser* p, const char** attr) +{ + int i; + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "width") == 0) { + p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "height") == 0) { + p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "viewBox") == 0) { + sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight); + } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { + if (strstr(attr[i + 1], "none") != 0) { + // No uniform scaling + p->alignType = NSVG_ALIGN_NONE; + } else { + // Parse X align + if (strstr(attr[i + 1], "xMin") != 0) + p->alignX = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "xMid") != 0) + p->alignX = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "xMax") != 0) + p->alignX = NSVG_ALIGN_MAX; + // Parse X align + if (strstr(attr[i + 1], "yMin") != 0) + p->alignY = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "yMid") != 0) + p->alignY = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "yMax") != 0) + p->alignY = NSVG_ALIGN_MAX; + // Parse meet/slice + p->alignType = NSVG_ALIGN_MEET; + if (strstr(attr[i + 1], "slice") != 0) + p->alignType = NSVG_ALIGN_SLICE; + } + } + } + } +} + +static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type) +{ + int i; + NSVGgradientData* grad = (NSVGgradientData*)NANOSVG_malloc(sizeof(NSVGgradientData)); + if (grad == NULL) return; + memset(grad, 0, sizeof(NSVGgradientData)); + grad->units = NSVG_OBJECT_SPACE; + grad->type = type; + if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) { + grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT); + grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) { + grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + } + + nsvg__xformIdentity(grad->xform); + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "id") == 0) { + strncpy(grad->id, attr[i+1], 63); + grad->id[63] = '\0'; + } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "gradientUnits") == 0) { + if (strcmp(attr[i+1], "objectBoundingBox") == 0) + grad->units = NSVG_OBJECT_SPACE; + else + grad->units = NSVG_USER_SPACE; + } else if (strcmp(attr[i], "gradientTransform") == 0) { + nsvg__parseTransform(grad->xform, attr[i + 1]); + } else if (strcmp(attr[i], "cx") == 0) { + grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "cy") == 0) { + grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "r") == 0) { + grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fx") == 0) { + grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fy") == 0) { + grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x1") == 0) { + grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y1") == 0) { + grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x2") == 0) { + grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y2") == 0) { + grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "spreadMethod") == 0) { + if (strcmp(attr[i+1], "pad") == 0) + grad->spread = NSVG_SPREAD_PAD; + else if (strcmp(attr[i+1], "reflect") == 0) + grad->spread = NSVG_SPREAD_REFLECT; + else if (strcmp(attr[i+1], "repeat") == 0) + grad->spread = NSVG_SPREAD_REPEAT; + } else if (strcmp(attr[i], "xlink:href") == 0) { + const char *href = attr[i+1]; + strncpy(grad->ref, href+1, 62); + grad->ref[62] = '\0'; + } + } + } + + grad->next = p->gradients; + p->gradients = grad; +} + +static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) +{ + NSVGattrib* curAttr = nsvg__getAttr(p); + NSVGgradientData* grad; + NSVGgradientStop* stop; + int i, idx; + + curAttr->stopOffset = 0; + curAttr->stopColor = 0; + curAttr->stopOpacity = 1.0f; + + for (i = 0; attr[i]; i += 2) { + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } + + // Add stop to the last gradient. + grad = p->gradients; + if (grad == NULL) return; + + grad->nstops++; + grad->stops = (NSVGgradientStop*)NANOSVG_realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops); + if (grad->stops == NULL) return; + + // Insert + idx = grad->nstops-1; + for (i = 0; i < grad->nstops-1; i++) { + if (curAttr->stopOffset < grad->stops[i].offset) { + idx = i; + break; + } + } + if (idx != grad->nstops-1) { + for (i = grad->nstops-1; i > idx; i--) + grad->stops[i] = grad->stops[i-1]; + } + + stop = &grad->stops[idx]; + stop->color = curAttr->stopColor; + stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24; + stop->offset = curAttr->stopOffset; +} + +static void nsvg__startElement(void* ud, const char* el, const char** attr) +{ + NSVGparser* p = (NSVGparser*)ud; + + if (p->defsFlag) { + // Skip everything but gradients in defs + if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } + return; + } + + if (strcmp(el, "g") == 0) { + nsvg__pushAttr(p); + nsvg__parseAttribs(p, attr); + } else if (strcmp(el, "path") == 0) { + if (p->pathFlag) // Do not allow nested paths. + return; + nsvg__pushAttr(p); + nsvg__parsePath(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "rect") == 0) { + nsvg__pushAttr(p); + nsvg__parseRect(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "circle") == 0) { + nsvg__pushAttr(p); + nsvg__parseCircle(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "ellipse") == 0) { + nsvg__pushAttr(p); + nsvg__parseEllipse(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "line") == 0) { + nsvg__pushAttr(p); + nsvg__parseLine(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "polyline") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 0); + nsvg__popAttr(p); + } else if (strcmp(el, "polygon") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 1); + nsvg__popAttr(p); + } else if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 1; + } else if (strcmp(el, "svg") == 0) { + nsvg__parseSVG(p, attr); + } else if (strcmp(el, "style") == 0) { + p->styleFlag = 1; + } +} + +static void nsvg__endElement(void* ud, const char* el) +{ + NSVGparser* p = (NSVGparser*)ud; + + if (strcmp(el, "g") == 0) { + nsvg__popAttr(p); + } else if (strcmp(el, "path") == 0) { + p->pathFlag = 0; + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 0; + } else if (strcmp(el, "style") == 0) { + p->styleFlag = 0; + } +} + +static char *nsvg__strndup(const char *s, size_t n) +{ + char *result; + size_t len = strlen(s); + + if (n < len) + len = n; + + result = (char*)NANOSVG_malloc(len+1); + if (!result) + return 0; + + result[len] = '\0'; + return (char *)memcpy(result, s, len); +} + +static void nsvg__content(void* ud, const char* s) +{ + NSVGparser* p = (NSVGparser*)ud; + if (p->styleFlag) { + + int state = 0; + const char* start = NULL; + while (*s) { + char c = *s; + if (nsvg__isspace(c) || c == '{') { + if (state == 1) { + NSVGstyles* next = p->styles; + + p->styles = (NSVGstyles*)malloc(sizeof(NSVGstyles)); + p->styles->next = next; + p->styles->name = nsvg__strndup(start, (size_t)(s - start)); + start = s + 1; + state = 2; + } + } else if (state == 2 && c == '}') { + p->styles->description = nsvg__strndup(start, (size_t)(s - start)); + state = 0; + } + else if (state == 0) { + start = s; + state = 1; + } + s++; + /* + if (*s == '{' && state == NSVG_XML_CONTENT) { + // Start of a tag + *s++ = '\0'; + nsvg__parseContent(mark, contentCb, ud); + mark = s; + state = NSVG_XML_TAG; + } + else if (*s == '>' && state == NSVG_XML_TAG) { + // Start of a content or new tag. + *s++ = '\0'; + nsvg__parseElement(mark, startelCb, endelCb, ud); + mark = s; + state = NSVG_XML_CONTENT; + } + else { + s++; + } + */ + } + + } +} + +static void nsvg__imageBounds(NSVGparser* p, float* bounds) +{ + NSVGshape* shape; + shape = p->image->shapes; + if (shape == NULL) { + bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0; + return; + } + bounds[0] = shape->bounds[0]; + bounds[1] = shape->bounds[1]; + bounds[2] = shape->bounds[2]; + bounds[3] = shape->bounds[3]; + for (shape = shape->next; shape != NULL; shape = shape->next) { + bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]); + bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]); + bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]); + bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]); + } +} + +static float nsvg__viewAlign(float content, float container, int type) +{ + if (type == NSVG_ALIGN_MIN) + return 0; + else if (type == NSVG_ALIGN_MAX) + return container - content; + // mid + return (container - content) * 0.5f; +} + +static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) +{ + float t[6]; + nsvg__xformSetTranslation(t, tx, ty); + nsvg__xformMultiply (grad->xform, t); + + nsvg__xformSetScale(t, sx, sy); + nsvg__xformMultiply (grad->xform, t); +} + +static void nsvg__scaleToViewbox(NSVGparser* p, const char* units) +{ + NSVGshape* shape; + NSVGpath* path; + float tx, ty, sx, sy, us, bounds[4], t[6], avgs; + int i; + float* pt; + + // Guess image size if not set completely. + nsvg__imageBounds(p, bounds); + + if (p->viewWidth == 0) { + if (p->image->width > 0) { + p->viewWidth = p->image->width; + } else { + p->viewMinx = bounds[0]; + p->viewWidth = bounds[2] - bounds[0]; + } + } + if (p->viewHeight == 0) { + if (p->image->height > 0) { + p->viewHeight = p->image->height; + } else { + p->viewMiny = bounds[1]; + p->viewHeight = bounds[3] - bounds[1]; + } + } + if (p->image->width == 0) + p->image->width = p->viewWidth; + if (p->image->height == 0) + p->image->height = p->viewHeight; + + tx = -p->viewMinx; + ty = -p->viewMiny; + sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0; + sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0; + // Unit scaling + us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f); + + // Fix aspect ratio + if (p->alignType == NSVG_ALIGN_MEET) { + // fit whole image into viewbox + sx = sy = nsvg__minf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; + } else if (p->alignType == NSVG_ALIGN_SLICE) { + // fill whole viewbox with image + sx = sy = nsvg__maxf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; + } + + // Transform + sx *= us; + sy *= us; + avgs = (sx+sy) / 2.0f; + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + shape->bounds[0] = (shape->bounds[0] + tx) * sx; + shape->bounds[1] = (shape->bounds[1] + ty) * sy; + shape->bounds[2] = (shape->bounds[2] + tx) * sx; + shape->bounds[3] = (shape->bounds[3] + ty) * sy; + for (path = shape->paths; path != NULL; path = path->next) { + path->bounds[0] = (path->bounds[0] + tx) * sx; + path->bounds[1] = (path->bounds[1] + ty) * sy; + path->bounds[2] = (path->bounds[2] + tx) * sx; + path->bounds[3] = (path->bounds[3] + ty) * sy; + for (i =0; i < path->npts; i++) { + pt = &path->pts[i*2]; + pt[0] = (pt[0] + tx) * sx; + pt[1] = (pt[1] + ty) * sy; + } + } + + if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy); + memcpy(t, shape->fill.gradient->xform, sizeof(float)*6); + nsvg__xformInverse(shape->fill.gradient->xform, t); + } + if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy); + memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6); + nsvg__xformInverse(shape->stroke.gradient->xform, t); + } + + shape->strokeWidth *= avgs; + shape->strokeDashOffset *= avgs; + for (i = 0; i < shape->strokeDashCount; i++) + shape->strokeDashArray[i] *= avgs; + } +} + +NANOSVG_SCOPE +NSVGimage* nsvgParse(char* input, const char* units, float dpi) +{ + NSVGparser* p; + NSVGimage* ret = 0; + + p = nsvg__createParser(); + if (p == NULL) { + return NULL; + } + p->dpi = dpi; + + nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); + + // Scale to viewBox + nsvg__scaleToViewbox(p, units); + + ret = p->image; + p->image = NULL; + + nsvg__deleteParser(p); + + return ret; +} + +NANOSVG_SCOPE +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) +{ + FILE* fp = NULL; + size_t size; + char* data = NULL; + NSVGimage* image = NULL; + + fp = fopen(filename, "rb"); + if (!fp) goto error; + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + data = (char*)NANOSVG_malloc(size+1); + if (data == NULL) goto error; + if (fread(data, 1, size, fp) != size) goto error; + data[size] = '\0'; // Must be null terminated. + fclose(fp); + image = nsvgParse(data, units, dpi); + NANOSVG_free(data); + + return image; + +error: + if (fp) fclose(fp); + if (data) NANOSVG_free(data); + if (image) nsvgDelete(image); + return NULL; +} + +NANOSVG_SCOPE +void nsvgDelete(NSVGimage* image) +{ + NSVGshape *snext, *shape; + if (image == NULL) return; + shape = image->shapes; + while (shape != NULL) { + snext = shape->next; + nsvg__deletePaths(shape->paths); + nsvg__deletePaint(&shape->fill); + nsvg__deletePaint(&shape->stroke); + NANOSVG_free(shape); + shape = snext; + } + NANOSVG_free(image); +} + +#endif ADDED generic/nanosvgrast.h Index: generic/nanosvgrast.h ================================================================== --- /dev/null +++ generic/nanosvgrast.h @@ -0,0 +1,1467 @@ +/* + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * The polygon rasterization is heavily based on stb_truetype rasterizer + * by Sean Barrett - http://nothings.org/ + * + */ + +#ifndef NANOSVGRAST_H +#define NANOSVGRAST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NANOSVG_SCOPE +#define NANOSVG_SCOPE +#endif + +#ifndef NANOSVG_malloc +#define NANOSVG_malloc malloc +#endif + +#ifndef NANOSVG_realloc +#define NANOSVG_realloc realloc +#endif + +#ifndef NANOSVG_free +#define NANOSVG_free free +#endif + +typedef struct NSVGrasterizer NSVGrasterizer; + +/* Example Usage: + // Load SVG + struct SNVGImage* image = nsvgParseFromFile("test.svg."); + + // Create rasterizer (can be used to render multiple images). + struct NSVGrasterizer* rast = nsvgCreateRasterizer(); + // Allocate memory for image + unsigned char* img = malloc(w*h*4); + // Rasterize + nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); +*/ + +// Allocated rasterizer context. +NANOSVG_SCOPE NSVGrasterizer* nsvgCreateRasterizer(); + +// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) +// r - pointer to rasterizer context +// image - pointer to image to rasterize +// tx,ty - image offset (applied after scaling) +// scale - image scale +// dst - pointer to destination image data, 4 bytes per pixel (RGBA) +// w - width of the image to render +// h - height of the image to render +// stride - number of bytes per scaleline in the destination buffer +NANOSVG_SCOPE void nsvgRasterize(NSVGrasterizer* r, + NSVGimage* image, float tx, float ty, float scale, + unsigned char* dst, int w, int h, int stride); + +// Deletes rasterizer context. +NANOSVG_SCOPE void nsvgDeleteRasterizer(NSVGrasterizer*); + + +#ifdef __cplusplus +} +#endif + +#endif // NANOSVGRAST_H + +#ifdef NANOSVGRAST_IMPLEMENTATION + +#include + +#define NSVG__SUBSAMPLES 5 +#define NSVG__FIXSHIFT 10 +#define NSVG__FIX (1 << NSVG__FIXSHIFT) +#define NSVG__FIXMASK (NSVG__FIX-1) +#define NSVG__MEMPAGE_SIZE 1024 + +typedef struct NSVGedge { + float x0,y0, x1,y1; + int dir; + struct NSVGedge* next; +} NSVGedge; + +typedef struct NSVGpoint { + float x, y; + float dx, dy; + float len; + float dmx, dmy; + unsigned char flags; +} NSVGpoint; + +typedef struct NSVGactiveEdge { + int x,dx; + float ey; + int dir; + struct NSVGactiveEdge *next; +} NSVGactiveEdge; + +typedef struct NSVGmemPage { + unsigned char mem[NSVG__MEMPAGE_SIZE]; + int size; + struct NSVGmemPage* next; +} NSVGmemPage; + +typedef struct NSVGcachedPaint { + char type; + char spread; + float xform[6]; + unsigned int colors[256]; +} NSVGcachedPaint; + +struct NSVGrasterizer +{ + float px, py; + + float tessTol; + float distTol; + + NSVGedge* edges; + int nedges; + int cedges; + + NSVGpoint* points; + int npoints; + int cpoints; + + NSVGpoint* points2; + int npoints2; + int cpoints2; + + NSVGactiveEdge* freelist; + NSVGmemPage* pages; + NSVGmemPage* curpage; + + unsigned char* scanline; + int cscanline; + + unsigned char* bitmap; + int width, height, stride; +}; + +NANOSVG_SCOPE +NSVGrasterizer* nsvgCreateRasterizer() +{ + NSVGrasterizer* r = (NSVGrasterizer*)NANOSVG_malloc(sizeof(NSVGrasterizer)); + if (r == NULL) goto error; + memset(r, 0, sizeof(NSVGrasterizer)); + + r->tessTol = 0.25f; + r->distTol = 0.01f; + + return r; + +error: + nsvgDeleteRasterizer(r); + return NULL; +} + +NANOSVG_SCOPE +void nsvgDeleteRasterizer(NSVGrasterizer* r) +{ + NSVGmemPage* p; + + if (r == NULL) return; + + p = r->pages; + while (p != NULL) { + NSVGmemPage* next = p->next; + NANOSVG_free(p); + p = next; + } + + if (r->edges) NANOSVG_free(r->edges); + if (r->points) NANOSVG_free(r->points); + if (r->points2) NANOSVG_free(r->points2); + if (r->scanline) NANOSVG_free(r->scanline); + + NANOSVG_free(r); +} + +static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) +{ + NSVGmemPage *newp; + + // If using existing chain, return the next page in chain + if (cur != NULL && cur->next != NULL) { + return cur->next; + } + + // Alloc new page + newp = (NSVGmemPage*)NANOSVG_malloc(sizeof(NSVGmemPage)); + if (newp == NULL) return NULL; + memset(newp, 0, sizeof(NSVGmemPage)); + + // Add to linked list + if (cur != NULL) + cur->next = newp; + else + r->pages = newp; + + return newp; +} + +static void nsvg__resetPool(NSVGrasterizer* r) +{ + NSVGmemPage* p = r->pages; + while (p != NULL) { + p->size = 0; + p = p->next; + } + r->curpage = r->pages; +} + +static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size) +{ + unsigned char* buf; + if (size > NSVG__MEMPAGE_SIZE) return NULL; + if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) { + r->curpage = nsvg__nextPage(r, r->curpage); + } + buf = &r->curpage->mem[r->curpage->size]; + r->curpage->size += size; + return buf; +} + +static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol) +{ + float dx = x2 - x1; + float dy = y2 - y1; + return dx*dx + dy*dy < tol*tol; +} + +static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags) +{ + NSVGpoint* pt; + + if (r->npoints > 0) { + pt = &r->points[r->npoints-1]; + if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) { + pt->flags = (unsigned char)(pt->flags | flags); + return; + } + } + + if (r->npoints+1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)NANOSVG_realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) return; + } + + pt = &r->points[r->npoints]; + pt->x = x; + pt->y = y; + pt->flags = (unsigned char)flags; + r->npoints++; +} + +static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt) +{ + if (r->npoints+1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)NANOSVG_realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) return; + } + r->points[r->npoints] = pt; + r->npoints++; +} + +static void nsvg__duplicatePoints(NSVGrasterizer* r) +{ + if (r->npoints > r->cpoints2) { + r->cpoints2 = r->npoints; + r->points2 = (NSVGpoint*)NANOSVG_realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2); + if (r->points2 == NULL) return; + } + + memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints); + r->npoints2 = r->npoints; +} + +static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1) +{ + NSVGedge* e; + + // Skip horizontal edges + if (y0 == y1) + return; + + if (r->nedges+1 > r->cedges) { + r->cedges = r->cedges > 0 ? r->cedges * 2 : 64; + r->edges = (NSVGedge*)NANOSVG_realloc(r->edges, sizeof(NSVGedge) * r->cedges); + if (r->edges == NULL) return; + } + + e = &r->edges[r->nedges]; + r->nedges++; + + if (y0 < y1) { + e->x0 = x0; + e->y0 = y0; + e->x1 = x1; + e->y1 = y1; + e->dir = 1; + } else { + e->x0 = x1; + e->y0 = y1; + e->x1 = x0; + e->y1 = y0; + e->dir = -1; + } +} + +static float nsvg__normalize(float *x, float* y) +{ + float d = sqrtf((*x)*(*x) + (*y)*(*y)); + if (d > 1e-6f) { + float id = 1.0f / d; + *x *= id; + *y *= id; + } + return d; +} + +static float nsvg__absf(float x) { return x < 0 ? -x : x; } + +static void nsvg__flattenCubicBez(NSVGrasterizer* r, + float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4, + int level, int type) +{ + float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234; + float dx,dy,d2,d3; + + if (level > 10) return; + + x12 = (x1+x2)*0.5f; + y12 = (y1+y2)*0.5f; + x23 = (x2+x3)*0.5f; + y23 = (y2+y3)*0.5f; + x34 = (x3+x4)*0.5f; + y34 = (y3+y4)*0.5f; + x123 = (x12+x23)*0.5f; + y123 = (y12+y23)*0.5f; + + dx = x4 - x1; + dy = y4 - y1; + d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx)); + d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx)); + + if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) { + nsvg__addPathPoint(r, x4, y4, type); + return; + } + + x234 = (x23+x34)*0.5f; + y234 = (y23+y34)*0.5f; + x1234 = (x123+x234)*0.5f; + y1234 = (y123+y234)*0.5f; + + nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0); + nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type); +} + +static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale) +{ + int i, j; + NSVGpath* path; + + for (path = shape->paths; path != NULL; path = path->next) { + r->npoints = 0; + // Flatten path + nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); + for (i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0); + } + // Close path + nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); + // Build edges + for (i = 0, j = r->npoints-1; i < r->npoints; j = i++) + nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); + } +} + +enum NSVGpointFlags +{ + NSVG_PT_CORNER = 0x01, + NSVG_PT_BEVEL = 0x02, + NSVG_PT_LEFT = 0x04 +}; + +static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + float len = nsvg__normalize(&dx, &dy); + float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f; + float dlx = dy, dly = -dx; + float lx = px - dlx*w, ly = py - dly*w; + float rx = px + dlx*w, ry = py + dly*w; + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) +{ + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = px - dlx*w, ly = py - dly*w; + float rx = px + dlx*w, ry = py + dly*w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) +{ + float w = lineWidth * 0.5f; + float px = p->x - dx*w, py = p->y - dy*w; + float dlx = dy, dly = -dx; + float lx = px - dlx*w, ly = py - dly*w; + float rx = px + dlx*w, ry = py + dly*w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +#ifndef NSVG_PI +#define NSVG_PI (3.14159265358979323846264338327f) +#endif + +static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect) +{ + int i; + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0; + + for (i = 0; i < ncap; i++) { + float a = (float)i/(float)(ncap-1)*NSVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + float x = px - dlx*ax - dx*ay; + float y = py - dly*ax - dy*ay; + + if (i > 0) + nsvg__addEdge(r, prevx, prevy, x, y); + + prevx = x; + prevy = y; + + if (i == 0) { + lx = x; ly = y; + } else if (i == ncap-1) { + rx = x; ry = y; + } + } + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w); + float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w); + float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w); + float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w); + + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + + left->x = lx1; left->y = ly1; + right->x = rx1; right->y = ry1; +} + +static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0, rx0, lx1, rx1; + float ly0, ry0, ly1, ry1; + + if (p1->flags & NSVG_PT_LEFT) { + lx0 = lx1 = p1->x - p1->dmx * w; + ly0 = ly1 = p1->y - p1->dmy * w; + nsvg__addEdge(r, lx1, ly1, left->x, left->y); + + rx0 = p1->x + (dlx0 * w); + ry0 = p1->y + (dly0 * w); + rx1 = p1->x + (dlx1 * w); + ry1 = p1->y + (dly1 * w); + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + } else { + lx0 = p1->x - (dlx0 * w); + ly0 = p1->y - (dly0 * w); + lx1 = p1->x - (dlx1 * w); + ly1 = p1->y - (dly1 * w); + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + rx0 = rx1 = p1->x + p1->dmx * w; + ry0 = ry1 = p1->y + p1->dmy * w; + nsvg__addEdge(r, right->x, right->y, rx1, ry1); + } + + left->x = lx1; left->y = ly1; + right->x = rx1; right->y = ry1; +} + +static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap) +{ + int i, n; + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float a0 = atan2f(dly0, dlx0); + float a1 = atan2f(dly1, dlx1); + float da = a1 - a0; + float lx, ly, rx, ry; + + if (da < NSVG_PI) da += NSVG_PI*2; + if (da > NSVG_PI) da -= NSVG_PI*2; + + n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap); + if (n < 2) n = 2; + if (n > ncap) n = ncap; + + lx = left->x; + ly = left->y; + rx = right->x; + ry = right->y; + + for (i = 0; i < n; i++) { + float u = (float)i/(float)(n-1); + float a = a0 + u*da; + float ax = cosf(a) * w, ay = sinf(a) * w; + float lx1 = p1->x - ax, ly1 = p1->y - ay; + float rx1 = p1->x + ax, ry1 = p1->y + ay; + + nsvg__addEdge(r, lx1, ly1, lx, ly); + nsvg__addEdge(r, rx, ry, rx1, ry1); + + lx = lx1; ly = ly1; + rx = rx1; ry = ry1; + } + + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth) +{ + float w = lineWidth * 0.5f; + float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w); + float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w); + + nsvg__addEdge(r, lx, ly, left->x, left->y); + nsvg__addEdge(r, right->x, right->y, rx, ry); + + left->x = lx; left->y = ly; + right->x = rx; right->y = ry; +} + +static int nsvg__curveDivs(float r, float arc, float tol) +{ + float da = acosf(r / (r + tol)) * 2.0f; + int divs = (int)ceilf(arc / da); + if (divs < 2) divs = 2; + return divs; +} + +static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) +{ + int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. + NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0}; + NSVGpoint* p0, *p1; + int j, s, e; + + // Build stroke edges + if (closed) { + // Looping + p0 = &points[npoints-1]; + p1 = &points[0]; + s = 0; + e = npoints; + } else { + // Add cap + p0 = &points[0]; + p1 = &points[1]; + s = 1; + e = npoints-1; + } + + if (closed) { + nsvg__initClosed(&left, &right, p0, p1, lineWidth); + firstLeft = left; + firstRight = right; + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0); + } + + for (j = s; j < e; ++j) { + if (p1->flags & NSVG_PT_CORNER) { + if (lineJoin == NSVG_JOIN_ROUND) + nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap); + else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL)) + nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth); + else + nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth); + } else { + nsvg__straightJoin(r, &left, &right, p1, lineWidth); + } + p0 = p1++; + } + + if (closed) { + // Loop it + nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); + nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1); + } +} + +static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin) +{ + int i, j; + NSVGpoint* p0, *p1; + + p0 = &r->points[r->npoints-1]; + p1 = &r->points[0]; + for (i = 0; i < r->npoints; i++) { + // Calculate segment direction and length + p0->dx = p1->x - p0->x; + p0->dy = p1->y - p0->y; + p0->len = nsvg__normalize(&p0->dx, &p0->dy); + // Advance + p0 = p1++; + } + + // calculate joins + p0 = &r->points[r->npoints-1]; + p1 = &r->points[0]; + for (j = 0; j < r->npoints; j++) { + float dlx0, dly0, dlx1, dly1, dmr2, cross; + dlx0 = p0->dy; + dly0 = -p0->dx; + dlx1 = p1->dy; + dly1 = -p1->dx; + // Calculate extrusions + p1->dmx = (dlx0 + dlx1) * 0.5f; + p1->dmy = (dly0 + dly1) * 0.5f; + dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; + if (dmr2 > 0.000001f) { + float s2 = 1.0f / dmr2; + if (s2 > 600.0f) { + s2 = 600.0f; + } + p1->dmx *= s2; + p1->dmy *= s2; + } + + // Clear flags, but keep the corner. + p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; + + // Keep track of left turns. + cross = p1->dx * p0->dy - p0->dx * p1->dy; + if (cross > 0.0f) + p1->flags |= NSVG_PT_LEFT; + + // Check to see if the corner needs to be beveled. + if (p1->flags & NSVG_PT_CORNER) { + if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { + p1->flags |= NSVG_PT_BEVEL; + } + } + + p0 = p1++; + } +} + +static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale) +{ + int i, j, closed; + NSVGpath* path; + NSVGpoint* p0, *p1; + float miterLimit = shape->miterLimit; + int lineJoin = shape->strokeLineJoin; + int lineCap = shape->strokeLineCap; + float lineWidth = shape->strokeWidth * scale; + + for (path = shape->paths; path != NULL; path = path->next) { + // Flatten path + r->npoints = 0; + nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER); + for (i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER); + } + if (r->npoints < 2) + continue; + + closed = path->closed; + + // If the first and last points are the same, remove the last, mark as closed path. + p0 = &r->points[r->npoints-1]; + p1 = &r->points[0]; + if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) { + r->npoints--; + p0 = &r->points[r->npoints-1]; + closed = 1; + } + + if (shape->strokeDashCount > 0) { + int idash = 0, dashState = 1; + float totalDist = 0, dashLen, allDashLen, dashOffset; + NSVGpoint cur; + + if (closed) + nsvg__appendPathPoint(r, r->points[0]); + + // Duplicate points -> points2. + nsvg__duplicatePoints(r); + + r->npoints = 0; + cur = r->points2[0]; + nsvg__appendPathPoint(r, cur); + + // Figure out dash offset. + allDashLen = 0; + for (j = 0; j < shape->strokeDashCount; j++) + allDashLen += shape->strokeDashArray[j]; + if (shape->strokeDashCount & 1) + allDashLen *= 2.0f; + // Find location inside pattern + dashOffset = fmodf(shape->strokeDashOffset, allDashLen); + if (dashOffset < 0.0f) + dashOffset += allDashLen; + + while (dashOffset > shape->strokeDashArray[idash]) { + dashOffset -= shape->strokeDashArray[idash]; + idash = (idash + 1) % shape->strokeDashCount; + } + dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale; + + for (j = 1; j < r->npoints2; ) { + float dx = r->points2[j].x - cur.x; + float dy = r->points2[j].y - cur.y; + float dist = sqrtf(dx*dx + dy*dy); + + if ((totalDist + dist) > dashLen) { + // Calculate intermediate point + float d = (dashLen - totalDist) / dist; + float x = cur.x + dx * d; + float y = cur.y + dy * d; + nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); + + // Stroke + if (r->npoints > 1 && dashState) { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } + // Advance dash pattern + dashState = !dashState; + idash = (idash+1) % shape->strokeDashCount; + dashLen = shape->strokeDashArray[idash] * scale; + // Restart + cur.x = x; + cur.y = y; + cur.flags = NSVG_PT_CORNER; + totalDist = 0.0f; + r->npoints = 0; + nsvg__appendPathPoint(r, cur); + } else { + totalDist += dist; + cur = r->points2[j]; + nsvg__appendPathPoint(r, cur); + j++; + } + } + // Stroke any leftover path + if (r->npoints > 1 && dashState) + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } else { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth); + } + } +} + +static int nsvg__cmpEdge(const void *p, const void *q) +{ + const NSVGedge* a = (const NSVGedge*)p; + const NSVGedge* b = (const NSVGedge*)q; + + if (a->y0 < b->y0) return -1; + if (a->y0 > b->y0) return 1; + return 0; +} + + +static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint) +{ + NSVGactiveEdge* z; + float dxdy; + + if (r->freelist != NULL) { + // Restore from freelist. + z = r->freelist; + r->freelist = z->next; + } else { + // Alloc new edge. + z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); + if (z == NULL) return NULL; + } + + dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); +// STBTT_assert(e->y0 <= start_point); + // round dx down to avoid going too far + if (dxdy < 0) + z->dx = (int)(-floorf(NSVG__FIX * -dxdy)); + else + z->dx = (int)floorf(NSVG__FIX * dxdy); + z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); +// z->x -= off_x * FIX; + z->ey = e->y1; + z->next = 0; + z->dir = e->dir; + + return z; +} + +static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z) +{ + z->next = r->freelist; + r->freelist = z; +} + +static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax) +{ + int i = x0 >> NSVG__FIXSHIFT; + int j = x1 >> NSVG__FIXSHIFT; + if (i < *xmin) *xmin = i; + if (j > *xmax) *xmax = j; + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = (unsigned char)(scanline[i] + maxWeight); + } + } +} + +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) +{ + // non-zero winding fill + int x0 = 0, w = 0; + + if (fillRule == NSVG_FILLRULE_NONZERO) { + // Non-zero + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->dir; + } else { + int x1 = e->x; w += e->dir; + // if we went to zero, we need to draw + if (w == 0) + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } else if (fillRule == NSVG_FILLRULE_EVENODD) { + // Even-odd + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w = 1; + } else { + int x1 = e->x; w = 0; + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } +} + +static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } + +static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + return (r) | (g << 8) | (b << 16) | (a << 24); +} + +static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u) +{ + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8; + int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8; + int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8; + int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static unsigned int nsvg__applyOpacity(unsigned int c, float u) +{ + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (c) & 0xff; + int g = (c>>8) & 0xff; + int b = (c>>16) & 0xff; + int a = (((c>>24) & 0xff)*iu) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static inline int nsvg__div255(int x) +{ + return ((x+1) * 257) >> 16; +} + +static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y, + float tx, float ty, float scale, NSVGcachedPaint* cache) +{ + + if (cache->type == NSVG_PAINT_COLOR) { + int i, cr, cg, cb, ca; + cr = cache->colors[0] & 0xff; + cg = (cache->colors[0] >> 8) & 0xff; + cb = (cache->colors[0] >> 16) & 0xff; + ca = (cache->colors[0] >> 24) & 0xff; + + for (i = 0; i < count; i++) { + int r,g,b; + int a = nsvg__div255((int)cover[0] * ca); + int ia = 255 - a; + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + } + } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + float fx, fy, dx, gy; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r,g,b,a,ia; + gy = fx*t[1] + fy*t[3] + t[5]; + c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + // TODO: focus (fx,fy) + float fx, fy, dx, gx, gy, gd; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r,g,b,a,ia; + gx = fx*t[0] + fy*t[2] + t[4]; + gy = fx*t[1] + fy*t[3] + t[5]; + gd = sqrtf(gx*gx + gy*gy); + c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } +} + +static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule) +{ + NSVGactiveEdge *active = NULL; + int y, s; + int e = 0; + int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline + int xmin, xmax; + + for (y = 0; y < r->height; y++) { + memset(r->scanline, 0, r->width); + xmin = r->width; + xmax = 0; + for (s = 0; s < NSVG__SUBSAMPLES; ++s) { + // find center of pixel for this scanline + float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f; + NSVGactiveEdge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + NSVGactiveEdge *z = *step; + if (z->ey <= scany) { + *step = z->next; // delete from list +// NSVG__assert(z->valid); + nsvg__freeActive(r, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for (;;) { + int changed = 0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + NSVGactiveEdge* t = *step; + NSVGactiveEdge* q = t->next; + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e < r->nedges && r->edges[e].y0 <= scany) { + if (r->edges[e].y1 > scany) { + NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); + if (z == NULL) break; + // find insertion point + if (active == NULL) { + active = z; + } else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + NSVGactiveEdge* p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + e++; + } + + // now process all active edges in non-zero fashion + if (active != NULL) + nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); + } + // Blit + if (xmin < 0) xmin = 0; + if (xmax > r->width-1) xmax = r->width-1; + if (xmin <= xmax) { + nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache); + } + } + +} + +static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) +{ + int x,y; + + // Unpremultiply + for (y = 0; y < h; y++) { + unsigned char *row = &image[y*stride]; + for (x = 0; x < w; x++) { + int r = row[0], g = row[1], b = row[2], a = row[3]; + if (a != 0) { + row[0] = (unsigned char)(r*255/a); + row[1] = (unsigned char)(g*255/a); + row[2] = (unsigned char)(b*255/a); + } + row += 4; + } + } + + // Defringe + for (y = 0; y < h; y++) { + unsigned char *row = &image[y*stride]; + for (x = 0; x < w; x++) { + int r = 0, g = 0, b = 0, a = row[3], n = 0; + if (a == 0) { + if (x-1 > 0 && row[-1] != 0) { + r += row[-4]; + g += row[-3]; + b += row[-2]; + n++; + } + if (x+1 < w && row[7] != 0) { + r += row[4]; + g += row[5]; + b += row[6]; + n++; + } + if (y-1 > 0 && row[-stride+3] != 0) { + r += row[-stride]; + g += row[-stride+1]; + b += row[-stride+2]; + n++; + } + if (y+1 < h && row[stride+3] != 0) { + r += row[stride]; + g += row[stride+1]; + b += row[stride+2]; + n++; + } + if (n > 0) { + row[0] = (unsigned char)(r/n); + row[1] = (unsigned char)(g/n); + row[2] = (unsigned char)(b/n); + } + } + row += 4; + } + } +} + + +static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity) +{ + int i, j; + NSVGgradient* grad; + + cache->type = paint->type; + + if (paint->type == NSVG_PAINT_COLOR) { + cache->colors[0] = nsvg__applyOpacity(paint->color, opacity); + return; + } + + grad = paint->gradient; + + cache->spread = grad->spread; + memcpy(cache->xform, grad->xform, sizeof(float)*6); + + if (grad->nstops == 0) { + for (i = 0; i < 256; i++) + cache->colors[i] = 0; + } if (grad->nstops == 1) { + for (i = 0; i < 256; i++) + cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity); + } else { + unsigned int ca, cb = 0; + float ua, ub, du, u; + int ia, ib, count; + + ca = nsvg__applyOpacity(grad->stops[0].color, opacity); + ua = nsvg__clampf(grad->stops[0].offset, 0, 1); + ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + for (i = 0; i < ia; i++) { + cache->colors[i] = ca; + } + + for (i = 0; i < grad->nstops-1; i++) { + ca = nsvg__applyOpacity(grad->stops[i].color, opacity); + cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity); + ua = nsvg__clampf(grad->stops[i].offset, 0, 1); + ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + count = ib - ia; + if (count <= 0) continue; + u = 0; + du = 1.0f / (float)count; + for (j = 0; j < count; j++) { + cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u); + u += du; + } + } + + for (i = ib; i < 256; i++) + cache->colors[i] = cb; + } + +} + +/* +static void dumpEdges(NSVGrasterizer* r, const char* name) +{ + float xmin = 0, xmax = 0, ymin = 0, ymax = 0; + NSVGedge *e = NULL; + int i; + if (r->nedges == 0) return; + FILE* fp = fopen(name, "w"); + if (fp == NULL) return; + + xmin = xmax = r->edges[0].x0; + ymin = ymax = r->edges[0].y0; + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + xmin = nsvg__minf(xmin, e->x0); + xmin = nsvg__minf(xmin, e->x1); + xmax = nsvg__maxf(xmax, e->x0); + xmax = nsvg__maxf(xmax, e->x1); + ymin = nsvg__minf(ymin, e->y0); + ymin = nsvg__minf(ymin, e->y1); + ymax = nsvg__maxf(ymax, e->y0); + ymax = nsvg__maxf(ymax, e->y1); + } + + fprintf(fp, "", xmin, ymin, (xmax - xmin), (ymax - ymin)); + + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + fprintf(fp ,"", e->x0,e->y0, e->x1,e->y1); + } + + for (i = 0; i < r->npoints; i++) { + if (i+1 < r->npoints) + fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y); + fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0"); + } + + fprintf(fp, ""); + fclose(fp); +} +*/ + +NANOSVG_SCOPE +void nsvgRasterize(NSVGrasterizer* r, + NSVGimage* image, float tx, float ty, float scale, + unsigned char* dst, int w, int h, int stride) +{ + NSVGshape *shape = NULL; + NSVGedge *e = NULL; + NSVGcachedPaint cache; + int i; + + r->bitmap = dst; + r->width = w; + r->height = h; + r->stride = stride; + + if (w > r->cscanline) { + r->cscanline = w; + r->scanline = (unsigned char*)NANOSVG_realloc(r->scanline, w); + if (r->scanline == NULL) return; + } + + for (i = 0; i < h; i++) + memset(&dst[i*stride], 0, w*4); + + for (shape = image->shapes; shape != NULL; shape = shape->next) { + if (!(shape->flags & NSVG_FLAGS_VISIBLE)) + continue; + + if (shape->fill.type != NSVG_PAINT_NONE) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShape(r, shape, scale); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->fill, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule); + } + if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShapeStroke(r, shape, scale); + +// dumpEdges(r, "edge.svg"); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->stroke, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO); + } + } + + nsvg__unpremultiplyAlpha(dst, w, h, stride); + + r->bitmap = NULL; + r->width = 0; + r->height = 0; + r->stride = 0; +} + +#endif Index: generic/tk.decls ================================================================== --- generic/tk.decls +++ generic/tk.decls @@ -103,11 +103,11 @@ declare 18 { int Tk_CanvasTagsParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 19 { - CONST86 char *Tk_CanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin, + const char *Tk_CanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } declare 20 { Tk_Window Tk_CanvasTkwin(Tk_Canvas canvas) } @@ -144,11 +144,11 @@ char *widgRec, const char *argvName, int flags) } declare 29 { int Tk_ConfigureWidget(Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, - int argc, CONST84 char **argv, char *widgRec, + int argc, const char **argv, char *widgRec, int flags) } declare 30 { void Tk_ConfigureWindow(Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr) @@ -243,11 +243,11 @@ } declare 54 { void Tk_DestroyWindow(Tk_Window tkwin) } declare 55 { - CONST84_RETURN char *Tk_DisplayName(Tk_Window tkwin) + const char *Tk_DisplayName(Tk_Window tkwin) } declare 56 { int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x, int y) } declare 57 { @@ -324,11 +324,11 @@ void Tk_FreePixmap(Display *display, Pixmap pixmap) } declare 76 { void Tk_FreeTextLayout(Tk_TextLayout textLayout) } -declare 77 { +declare 77 {deprecated {function does nothing, call can be removed}} { void Tk_FreeXId(Display *display, XID xid) } declare 78 { GC Tk_GCForColor(XColor *colorPtr, Drawable drawable) } @@ -346,14 +346,14 @@ declare 82 { int Tk_GetAnchor(Tcl_Interp *interp, const char *str, Tk_Anchor *anchorPtr) } declare 83 { - CONST84_RETURN char *Tk_GetAtomName(Tk_Window tkwin, Atom atom) + const char *Tk_GetAtomName(Tk_Window tkwin, Atom atom) } declare 84 { - CONST84_RETURN char *Tk_GetBinding(Tcl_Interp *interp, + const char *Tk_GetBinding(Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr) } declare 85 { Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, const char *str) @@ -402,11 +402,11 @@ Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin, const char *name, Tk_ImageChangedProc *changeProc, ClientData clientData) } declare 98 { ClientData Tk_GetImageMasterData(Tcl_Interp *interp, - const char *name, CONST86 Tk_ImageType **typePtrPtr) + const char *name, const Tk_ImageType **typePtrPtr) } declare 99 { Tk_ItemType *Tk_GetItemTypes(void) } declare 100 { @@ -437,11 +437,11 @@ declare 107 { void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr, int *yPtr) } declare 108 { int Tk_GetScrollInfo(Tcl_Interp *interp, - int argc, CONST84 char **argv, double *dblPtr, int *intPtr) + int argc, const char **argv, double *dblPtr, int *intPtr) } declare 109 { int Tk_GetScreenMM(Tcl_Interp *interp, Tk_Window tkwin, const char *str, double *doublePtr) } @@ -516,41 +516,41 @@ } declare 129 { void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y) } declare 130 { - CONST84_RETURN char *Tk_NameOf3DBorder(Tk_3DBorder border) + const char *Tk_NameOf3DBorder(Tk_3DBorder border) } declare 131 { - CONST84_RETURN char *Tk_NameOfAnchor(Tk_Anchor anchor) + const char *Tk_NameOfAnchor(Tk_Anchor anchor) } declare 132 { - CONST84_RETURN char *Tk_NameOfBitmap(Display *display, Pixmap bitmap) + const char *Tk_NameOfBitmap(Display *display, Pixmap bitmap) } declare 133 { - CONST84_RETURN char *Tk_NameOfCapStyle(int cap) + const char *Tk_NameOfCapStyle(int cap) } declare 134 { - CONST84_RETURN char *Tk_NameOfColor(XColor *colorPtr) + const char *Tk_NameOfColor(XColor *colorPtr) } declare 135 { - CONST84_RETURN char *Tk_NameOfCursor(Display *display, Tk_Cursor cursor) + const char *Tk_NameOfCursor(Display *display, Tk_Cursor cursor) } declare 136 { - CONST84_RETURN char *Tk_NameOfFont(Tk_Font font) + const char *Tk_NameOfFont(Tk_Font font) } declare 137 { - CONST84_RETURN char *Tk_NameOfImage(Tk_ImageMaster imageMaster) + const char *Tk_NameOfImage(Tk_ImageMaster imageMaster) } declare 138 { - CONST84_RETURN char *Tk_NameOfJoinStyle(int join) + const char *Tk_NameOfJoinStyle(int join) } declare 139 { - CONST84_RETURN char *Tk_NameOfJustify(Tk_Justify justify) + const char *Tk_NameOfJustify(Tk_Justify justify) } declare 140 { - CONST84_RETURN char *Tk_NameOfRelief(int relief) + const char *Tk_NameOfRelief(int relief) } declare 141 { Tk_Window Tk_NameToWindow(Tcl_Interp *interp, const char *pathName, Tk_Window tkwin) } @@ -559,19 +559,19 @@ Atom selection, Tk_LostSelProc *proc, ClientData clientData) } declare 143 { int Tk_ParseArgv(Tcl_Interp *interp, - Tk_Window tkwin, int *argcPtr, CONST84 char **argv, + Tk_Window tkwin, int *argcPtr, const char **argv, const Tk_ArgvInfo *argTable, int flags) } -declare 144 { +declare 144 {deprecated {function signature changed}} { void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height) } -declare 145 { +declare 145 {deprecated {function signature changed}} { void Tk_PhotoPutZoomedBlock_NoComposite(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY) } @@ -579,17 +579,17 @@ int Tk_PhotoGetImage(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr) } declare 147 { void Tk_PhotoBlank(Tk_PhotoHandle handle) } -declare 148 { +declare 148 {deprecated {function signature changed}} { void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle, int width, int height ) } declare 149 { void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr, int *heightPtr) } -declare 150 { +declare 150 {deprecated {function signature changed}} { void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, int width, int height) } declare 151 { int Tk_PointToChar(Tk_TextLayout layout, int x, int y) } @@ -742,11 +742,11 @@ } declare 194 { void Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr) } declare 195 { - void Tk_FreeConfigOptions(char *recordPtr, Tk_OptionTable optionToken, + void Tk_FreeConfigOptions(void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin) } declare 196 { void Tk_FreeSavedOptions(Tk_SavedOptions *savePtr) } @@ -772,15 +772,15 @@ declare 203 { Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr) } declare 204 { Tcl_Obj *Tk_GetOptionInfo(Tcl_Interp *interp, - char *recordPtr, Tk_OptionTable optionTable, + void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin) } declare 205 { - Tcl_Obj *Tk_GetOptionValue(Tcl_Interp *interp, char *recordPtr, + Tcl_Obj *Tk_GetOptionValue(Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin) } declare 206 { int Tk_GetJustifyFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr) @@ -800,22 +800,22 @@ declare 210 { int Tk_GetScrollInfoObj(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr) } declare 211 { - int Tk_InitOptions(Tcl_Interp *interp, char *recordPtr, + int Tk_InitOptions(Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin) } -declare 212 { +declare 212 {nostub {Don't use this function in a stub-enabled extension}} { void Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp) } declare 213 { void Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr) } declare 214 { - int Tk_SetOptions(Tcl_Interp *interp, char *recordPtr, + int Tk_SetOptions(Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr) } declare 215 { @@ -941,16 +941,16 @@ # New in 8.4a5 # declare 245 { void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height) } -declare 246 { +declare 246 {deprecated {function signature changed}} { void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule) } -declare 247 { +declare 247 {deprecated {function signature changed}} { void Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule) } @@ -999,26 +999,26 @@ Tk_StyledElement Tk_GetStyledElement(Tk_Style style, int elementId, Tk_OptionTable optionTable) } declare 261 { void Tk_GetElementSize(Tk_Style style, Tk_StyledElement element, - char *recordPtr, Tk_Window tkwin, int width, int height, + void *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr) } declare 262 { void Tk_GetElementBox(Tk_Style style, Tk_StyledElement element, - char *recordPtr, Tk_Window tkwin, int x, int y, int width, + void *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr) } declare 263 { int Tk_GetElementBorderWidth(Tk_Style style, Tk_StyledElement element, - char *recordPtr, Tk_Window tkwin) + void *recordPtr, Tk_Window tkwin) } declare 264 { void Tk_DrawElement(Tk_Style style, Tk_StyledElement element, - char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, + void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state) } # TIP#116 declare 265 { @@ -1146,9 +1146,17 @@ export { const char *Tk_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact) } +export { + void Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, + Tcl_Interp *interp) +} +export { + void Tk_MainExW(int argc, wchar_t **argv, + Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); +} # Local Variables: # mode: tcl # End: Index: generic/tk.h ================================================================== --- generic/tk.h +++ generic/tk.h @@ -15,21 +15,14 @@ #ifndef _TK #define _TK #include -#if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION < 6) -# error Tk 8.6 must be compiled with tcl.h from Tcl 8.6 or better +#if (TCL_MAJOR_VERSION < 8) || (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6) +# error Tk 8.7 must be compiled with tcl.h from Tcl 8.6 or better #endif -#ifndef CONST84 -# define CONST84 const -# define CONST84_RETURN const -#endif -#ifndef CONST86 -# define CONST86 CONST84 -#endif #ifndef EXTERN # define EXTERN extern TCL_STORAGE_CLASS #endif /* @@ -57,12 +50,12 @@ /* * When version numbers change here, you must also go into the following files * and update the version numbers: * * library/tk.tcl (1 LOC patch) - * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch) - * win/configure.in (as above) + * unix/configure.ac (2 LOC Major, 2 LOC minor, 1 LOC patch) + * win/configure.ac (as above) * README (sections 0 and 1) * macosx/Tk-Common.xcconfig (not patchlevel) 1 LOC * win/README (not patchlevel) * unix/README (not patchlevel) * unix/tk.spec (1 LOC patch) @@ -71,16 +64,16 @@ * You may also need to update some of these files when the numbers change for * the version of Tcl that this release of Tk is compiled against. */ #define TK_MAJOR_VERSION 8 -#define TK_MINOR_VERSION 6 -#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE -#define TK_RELEASE_SERIAL 9 +#define TK_MINOR_VERSION 7 +#define TK_RELEASE_LEVEL TCL_ALPHA_RELEASE +#define TK_RELEASE_SERIAL 2 -#define TK_VERSION "8.6" -#define TK_PATCH_LEVEL "8.6.9" +#define TK_VERSION "8.7" +#define TK_PATCH_LEVEL "8.7a2" /* * A special definition used to allow this header file to be included from * windows or mac resource files so that they can obtain version information. * RC_INVOKED is defined by default by the windows RC tool and manually set @@ -103,10 +96,14 @@ #endif #ifdef BUILD_tk #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifndef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT +# endif #endif /* *---------------------------------------------------------------------- * @@ -188,24 +185,29 @@ const char *dbName; /* Name for option in option database. */ const char *dbClass; /* Class for option in database. */ const char *defValue; /* Default value for option if not specified * in command line, the option database, or * the system. */ - int objOffset; /* Where in record to store a Tcl_Obj * that +#if TCL_MAJOR_VERSION > 8 + size_t objOffset; /* Where in record to store a Tcl_Obj * that * holds the value of this option, specified * as an offset in bytes from the start of the - * record. Use the Tk_Offset macro to generate + * record. Use the offsetof macro to generate * values for this. -1 means don't store the * Tcl_Obj in the record. */ - int internalOffset; /* Where in record to store the internal + size_t internalOffset; /* Where in record to store the internal * representation of the value of this option, * such as an int or XColor *. This field is * specified as an offset in bytes from the - * start of the record. Use the Tk_Offset + * start of the record. Use the offsetof * macro to generate values for it. -1 means * don't store the internal representation in * the record. */ +#else + int objOffset; + int internalOffset; +#endif int flags; /* Any combination of the values defined * below. */ const void *clientData; /* An alternate place to put option-specific * data. Used for the monochrome default value * for colors, etc. */ @@ -264,14 +266,16 @@ /* * Macro to use to fill in "offset" fields of the Tk_OptionSpec structure. * Computes number of bytes from beginning of structure to a given field. */ -#ifdef offsetof -#define Tk_Offset(type, field) ((int) offsetof(type, field)) -#else -#define Tk_Offset(type, field) ((int) ((char *) &((type *) 0)->field)) +#ifndef TK_NO_DEPRECATED +# define Tk_Offset(type, field) ((int) offsetof(type, field)) +#endif +/* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */ +#ifndef offsetof +# define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field)) #endif /* * The following two structures are used for error handling. When config * options are being modified, the old values are saved in a Tk_SavedOptions @@ -288,11 +292,11 @@ * a Tcl object; may be NULL if the value was * not saved as an object. */ double internalForm; /* The old value of the option, in some * internal representation such as an int or * (XColor *). Valid only if the field - * optionPtr->specPtr->objOffset is < 0. The + * optionPtr->specPtr->objOffset is -1. The * space must be large enough to accommodate a * double, a long, or a pointer; right now it * looks like a double (i.e., 8 bytes) is big * enough. Also, using a double guarantees * that the field is properly aligned for @@ -304,15 +308,19 @@ #else # define TK_NUM_SAVED_OPTIONS 20 #endif typedef struct Tk_SavedOptions { - char *recordPtr; /* The data structure in which to restore + void *recordPtr; /* The data structure in which to restore * configuration options. */ Tk_Window tkwin; /* Window associated with recordPtr; needed to * restore certain options. */ - int numItems; /* The number of valid items in items field. */ +#if TCL_MAJOR_VERSION > 8 + size_t numItems; /* The number of valid items in items field. */ +#else + int numItems; +#endif Tk_SavedOption items[TK_NUM_SAVED_OPTIONS]; /* Items used to hold old values. */ struct Tk_SavedOptions *nextPtr; /* Points to next structure in list; needed if * too many options changed to hold all the @@ -333,12 +341,12 @@ */ #ifndef __NO_OLD_CONFIG typedef int (Tk_OptionParseProc) (ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST84 char *value, char *widgRec, int offset); -typedef CONST86 char *(Tk_OptionPrintProc) (ClientData clientData, + Tk_Window tkwin, const char *value, char *widgRec, int offset); +typedef const char *(Tk_OptionPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); typedef struct Tk_CustomOption { Tk_OptionParseProc *parseProc; /* Procedure to call to parse an option and @@ -360,23 +368,27 @@ typedef struct Tk_ConfigSpec { int type; /* Type of option, such as TK_CONFIG_COLOR; * see definitions below. Last option in table * must have type TK_CONFIG_END. */ - CONST86 char *argvName; /* Switch used to specify option in argv. NULL + const char *argvName; /* Switch used to specify option in argv. NULL * means this spec is part of a group. */ Tk_Uid dbName; /* Name for option in option database. */ Tk_Uid dbClass; /* Class for option in database. */ Tk_Uid defValue; /* Default value for option if not specified * in command line or database. */ - int offset; /* Where in widget record to store value; use - * Tk_Offset macro to generate values for +#if TCL_MAJOR_VERSION > 8 + size_t offset; /* Where in widget record to store value; use + * offsetof macro to generate values for * this. */ +#else + int offset; +#endif int specFlags; /* Any combination of the values defined * below; other bits are used internally by * tkConfig.c. */ - CONST86 Tk_CustomOption *customPtr; + const Tk_CustomOption *customPtr; /* If type is TK_CONFIG_CUSTOM then this is a * pointer to info about how to parse and * print the option. Otherwise it is * irrelevant. */ } Tk_ConfigSpec; @@ -412,27 +424,29 @@ #define TK_CONFIG_NULL_OK (1 << 0) #define TK_CONFIG_COLOR_ONLY (1 << 1) #define TK_CONFIG_MONO_ONLY (1 << 2) #define TK_CONFIG_DONT_SET_DEFAULT (1 << 3) -#define TK_CONFIG_OPTION_SPECIFIED (1 << 4) +#ifndef TK_NO_DEPRECATED +# define TK_CONFIG_OPTION_SPECIFIED (1 << 4) +#endif /* !TK_NO_DEPRECATED */ #define TK_CONFIG_USER_BIT 0x100 #endif /* __NO_OLD_CONFIG */ /* * Structure used to specify how to handle argv options. */ typedef struct { - CONST86 char *key; /* The key string that flags the option in the + const char *key; /* The key string that flags the option in the * argv array. */ int type; /* Indicates option type; see below. */ - char *src; /* Value to be used in setting dst; usage + void *src; /* Value to be used in setting dst; usage * depends on type. */ - char *dst; /* Address of value to be modified; usage + void *dst; /* Address of value to be modified; usage * depends on type. */ - CONST86 char *help; /* Documentation message describing this + const char *help; /* Documentation message describing this * option. */ } Tk_ArgvInfo; /* * Legal values for the type field of a Tk_ArgvInfo: see the user @@ -573,11 +587,15 @@ ClientData instanceData); typedef void (Tk_ClassWorldChangedProc) (ClientData instanceData); typedef void (Tk_ClassModalProc) (Tk_Window tkwin, XEvent *eventPtr); typedef struct Tk_ClassProcs { +#if TCL_MAJOR_VERSION > 8 + size_t size; +#else unsigned int size; +#endif Tk_ClassWorldChangedProc *worldChangedProc; /* Procedure to invoke when the widget needs * to respond in some way to a change in the * world (font changes, etc.) */ Tk_ClassCreateProc *createProc; @@ -598,16 +616,16 @@ * A more general version of this function may be useful if other * size-versioned structure pop up in the future: * * #define Tk_GetField(name, who, which) \ * (((who) == NULL) ? NULL : - * (((who)->size <= Tk_Offset(name, which)) ? NULL :(name)->which)) + * (((who)->size <= offsetof(name, which)) ? NULL :(name)->which)) */ #define Tk_GetClassProc(procs, which) \ (((procs) == NULL) ? NULL : \ - (((procs)->size <= Tk_Offset(Tk_ClassProcs, which)) ? NULL:(procs)->which)) + (((procs)->size <= offsetof(Tk_ClassProcs, which)) ? NULL:(procs)->which)) /* * Each geometry manager (the packer, the placer, etc.) is represented by a * structure of the following form, which indicates procedures to invoke in * the geometry manager to carry out certain functions. @@ -674,11 +692,11 @@ unsigned long serial; /* # of last request processed by server. */ Bool send_event; /* True if this came from a SendEvent * request. */ Display *display; /* Display the event was read from. */ Window event; /* Window on which event was requested. */ - Window root; /* Root window that the event occured on. */ + Window root; /* Root window that the event occurred on. */ Window subwindow; /* Child window. */ Time time; /* Milliseconds. */ int x, y; /* Pointer x, y coordinates in event * window. */ int x_root, y_root; /* Coordinates relative to root. */ @@ -744,13 +762,14 @@ (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY) #define Tk_IsManageable(tkwin) \ (((Tk_FakeWin *) (tkwin))->flags & TK_WM_MANAGEABLE) #define Tk_ReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->reqWidth) #define Tk_ReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->reqHeight) -/* Tk_InternalBorderWidth is deprecated */ +#ifndef TK_NO_DEPRECATED #define Tk_InternalBorderWidth(tkwin) \ (((Tk_FakeWin *) (tkwin))->internalBorderLeft) +#endif /* !TK_NO_DEPRECATED */ #define Tk_InternalBorderLeft(tkwin) \ (((Tk_FakeWin *) (tkwin))->internalBorderLeft) #define Tk_InternalBorderRight(tkwin) \ (((Tk_FakeWin *) (tkwin))->internalBorderRight) #define Tk_InternalBorderTop(tkwin) \ @@ -811,14 +830,15 @@ int internalBorderRight; int internalBorderTop; int internalBorderBottom; int minReqWidth; int minReqHeight; - char *dummy20; /* geometryMaster */ #ifdef TK_USE_INPUT_METHODS - int dummy21; + int dummy20; #endif /* TK_USE_INPUT_METHODS */ + char *dummy21; /* geomMgrName */ + Tk_Window dummy22; /* maintainerPtr */ } Tk_FakeWin; /* * Flag values for TkWindow (and Tk_FakeWin) structures are: * @@ -916,11 +936,11 @@ TK_STATE_NULL = -1, TK_STATE_ACTIVE, TK_STATE_DISABLED, TK_STATE_NORMAL, TK_STATE_HIDDEN } Tk_State; typedef struct Tk_SmoothMethod { - CONST86 char *name; + const char *name; int (*coordProc) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); void (*postscriptProc) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, int numPoints, int numSteps); } Tk_SmoothMethod; @@ -1015,10 +1035,12 @@ double *pointPtr); typedef int (Tk_ItemAreaProc)(Tk_Canvas canvas, Tk_Item *itemPtr, double *rectPtr); typedef int (Tk_ItemPostscriptProc)(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +typedef void (Tk_ItemRotateProc)(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRadians); typedef void (Tk_ItemScaleProc)(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); typedef void (Tk_ItemTranslateProc)(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -1044,18 +1066,22 @@ int first, int last); #ifndef __NO_OLD_CONFIG typedef struct Tk_ItemType { - CONST86 char *name; /* The name of this type of item, such as + const char *name; /* The name of this type of item, such as * "line". */ - int itemSize; /* Total amount of space needed for item's +#if TCL_MAJOR_VERSION > 8 + size_t itemSize; /* Total amount of space needed for item's * record. */ +#else + int itemSize; +#endif Tk_ItemCreateProc *createProc; /* Procedure to create a new item of this * type. */ - CONST86 Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for + const Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for * this type. Used for returning configuration * info. */ Tk_ItemConfigureProc *configProc; /* Procedure to call to change configuration * options. */ @@ -1094,11 +1120,13 @@ * item. */ Tk_ItemDCharsProc *dCharsProc; /* Procedure to delete characters from an * item. */ struct Tk_ItemType *nextPtr;/* Used to link types together into a list. */ - char *reserved1; /* Reserved for future extension. */ + Tk_ItemRotateProc *rotateProc; + /* Procedure to rotate an item's coordinates + * about a point. */ int reserved2; /* Carefully compatible with */ char *reserved3; /* Jan Nijtmans dash patch */ char *reserved4; } Tk_ItemType; @@ -1221,12 +1249,12 @@ #ifdef USE_OLD_IMAGE typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, char *name, int argc, char **argv, Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *masterDataPtr); #else -typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, CONST86 char *name, int objc, - Tcl_Obj *const objv[], CONST86 Tk_ImageType *typePtr, Tk_ImageMaster master, +typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, const char *name, int objc, + Tcl_Obj *const objv[], const Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *masterDataPtr); #endif /* USE_OLD_IMAGE */ typedef ClientData (Tk_ImageGetProc) (Tk_Window tkwin, ClientData masterData); typedef void (Tk_ImageDisplayProc) (ClientData instanceData, Display *display, Drawable drawable, int imageX, int imageY, int width, int height, @@ -1246,11 +1274,11 @@ * that respond to various events. Each image manager is represented by one of * these structures. */ struct Tk_ImageType { - CONST86 char *name; /* Name of image type. */ + const char *name; /* Name of image type. */ Tk_ImageCreateProc *createProc; /* Procedure to call to create a new image of * this type. */ Tk_ImageGetProc *getProc; /* Procedure to call the first time * Tk_GetImage is called in a new way (new @@ -1358,11 +1386,11 @@ * images (e.g., PPM, GIF, JPEG, etc.). It provides information to allow image * files of that format to be recognized and read into a photo image. */ struct Tk_PhotoImageFormat { - CONST86 char *name; /* Name of image file format */ + const char *name; /* Name of image file format */ Tk_ImageFileMatchProc *fileMatchProc; /* Procedure to call to determine whether an * image file matches this format. */ Tk_ImageStringMatchProc *stringMatchProc; /* Procedure to call to determine whether the @@ -1462,10 +1490,11 @@ * Tcl. * *---------------------------------------------------------------------- */ +#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 #define TK_READABLE TCL_READABLE #define TK_WRITABLE TCL_WRITABLE #define TK_EXCEPTION TCL_EXCEPTION #define TK_DONT_WAIT TCL_DONT_WAIT @@ -1495,10 +1524,11 @@ #define Tk_EventuallyFree Tcl_EventuallyFree #define Tk_FreeProc Tcl_FreeProc #define Tk_Preserve Tcl_Preserve #define Tk_Release Tcl_Release +#endif /* Removed Tk_Main, use macro instead */ #if defined(_WIN32) || defined(__CYGWIN__) #define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \ (Tcl_FindExecutable(0), (Tcl_CreateInterp)())) @@ -1529,11 +1559,11 @@ typedef int (Tk_ErrorProc) (ClientData clientData, XErrorEvent *errEventPtr); typedef void (Tk_EventProc) (ClientData clientData, XEvent *eventPtr); typedef int (Tk_GenericProc) (ClientData clientData, XEvent *eventPtr); typedef int (Tk_ClientMessageProc) (Tk_Window tkwin, XEvent *eventPtr); typedef int (Tk_GetSelProc) (ClientData clientData, Tcl_Interp *interp, - CONST86 char *portion); + const char *portion); typedef void (Tk_LostSelProc) (ClientData clientData); typedef Tk_RestrictAction (Tk_RestrictProc) (ClientData clientData, XEvent *eventPtr); typedef int (Tk_SelectionProc) (ClientData clientData, int offset, char *buffer, int maxBytes); @@ -1557,16 +1587,17 @@ /* *---------------------------------------------------------------------- * * Allow users to say that they don't want to alter their source to add extra - * arguments to Tk_PhotoPutBlock() et al; DO NOT DEFINE THIS WHEN BUILDING TK. + * arguments to Tk_PhotoPutBlock() et al. * * This goes after the inclusion of the stubbed-decls so that the declarations * of what is actually there can be correct. */ +#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 #ifdef USE_COMPOSITELESS_PHOTO_PUT_BLOCK # ifdef Tk_PhotoPutBlock # undef Tk_PhotoPutBlock # endif # define Tk_PhotoPutBlock Tk_PhotoPutBlock_NoComposite @@ -1595,10 +1626,11 @@ # ifdef Tk_PhotoSetSize # undef Tk_PhotoSetSize # endif # define Tk_PhotoSetSize Tk_PhotoSetSize_Panic #endif /* USE_PANIC_ON_PHOTO_ALLOC_FAILURE */ +#endif /* !TK_NO_DEPRECATED */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #endif /* RC_INVOKED */ Index: generic/tk3d.c ================================================================== --- generic/tk3d.c +++ generic/tk3d.c @@ -1313,11 +1313,11 @@ * conversion, an error message is left in the interpreter's result * unless "interp" is NULL. * * Side effects: * If no error occurs, a blank internal format for a border value is - * intialized. The final form cannot be done without a Tk_Window. + * initialized. The final form cannot be done without a Tk_Window. * *---------------------------------------------------------------------- */ static void @@ -1378,13 +1378,13 @@ } for ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) { Tcl_Obj *objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(borderPtr->resourceRefCount)); + Tcl_NewWideIntObj(borderPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(borderPtr->objRefCount)); + Tcl_NewWideIntObj(borderPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } Index: generic/tk3d.h ================================================================== --- generic/tk3d.h +++ generic/tk3d.h @@ -26,20 +26,20 @@ * the border. */ int depth; /* Number of bits per pixel of drawables where * the border will be used. */ Colormap colormap; /* Colormap out of which pixels are * allocated. */ - int resourceRefCount; /* Number of active uses of this color (each + TkSizeT resourceRefCount; /* Number of active uses of this color (each * active use corresponds to a call to * Tk_Alloc3DBorderFromObj or Tk_Get3DBorder). * If this count is 0, then this structure is * no longer valid and it isn't present in * borderTable: it is being kept around only * because there are objects referring to it. * The structure is freed when objRefCount and * resourceRefCount are both 0. */ - int objRefCount; /* The number of Tcl objects that reference + TkSizeT objRefCount; /* The number of Tcl objects that reference * this structure. */ XColor *bgColorPtr; /* Background color (intensity between * lightColorPtr and darkColorPtr). */ XColor *darkColorPtr; /* Color for darker areas (must free when * deleting structure). NULL means shadows Index: generic/tkArgv.c ================================================================== --- generic/tkArgv.c +++ generic/tkArgv.c @@ -226,11 +226,11 @@ srcIndex++; argc--; break; case TK_ARGV_FUNC: { typedef int (ArgvFunc)(char *, const char *, const char *); - ArgvFunc *handlerProc = (ArgvFunc *) infoPtr->src; + ArgvFunc *handlerProc = infoPtr->src; if (handlerProc(infoPtr->dst, infoPtr->key, argv[srcIndex])) { srcIndex++; argc--; } @@ -237,11 +237,11 @@ break; } case TK_ARGV_GENFUNC: { typedef int (ArgvGenFunc)(char *, Tcl_Interp *, const char *, int, const char **); - ArgvGenFunc *handlerProc = (ArgvGenFunc *) infoPtr->src; + ArgvGenFunc *handlerProc = infoPtr->src; argc = handlerProc(infoPtr->dst, interp, infoPtr->key, argc, argv+srcIndex); if (argc < 0) { return TCL_ERROR; Index: generic/tkArray.h ================================================================== --- generic/tkArray.h +++ generic/tkArray.h @@ -159,13 +159,11 @@ /*************************************************************************/ #ifndef TK_ARRAY_DEFINED #define TK_ARRAY_DEFINED -#include -#include -#include +#include "tkInt.h" #if defined(__GNUC__) || defined(__clang__) # define __TK_ARRAY_UNUSED __attribute__((unused)) #else # define __TK_ARRAY_UNUSED Index: generic/tkAtom.c ================================================================== --- generic/tkAtom.c +++ generic/tkAtom.c @@ -154,11 +154,11 @@ if (mustFree) { XFree(mustFree); } name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr); hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew); - Tcl_SetHashValue(hPtr, name); + Tcl_SetHashValue(hPtr, (char *)name); } return Tcl_GetHashValue(hPtr); } /* @@ -200,11 +200,11 @@ name = atomNameArray[atom - 1]; hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew); Tcl_SetHashValue(hPtr, INT2PTR(atom)); name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr); hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew); - Tcl_SetHashValue(hPtr, name); + Tcl_SetHashValue(hPtr, (char *)name); } } /* * Local Variables: Index: generic/tkBind.c ================================================================== --- generic/tkBind.c +++ generic/tkBind.c @@ -23,12 +23,10 @@ #include "tkMacOSXInt.h" #else /* if defined(__unix__) */ #include "tkUnixInt.h" #endif -#include - #if NDEBUG # define DEBUG(expr) #else # define DEBUG(expr) expr #endif @@ -41,22 +39,10 @@ # define snprintf _snprintf #endif #define SIZE_OF_ARRAY(arr) (sizeof(arr)/sizeof(arr[0])) -/* - * Simple boolean type support. - */ - -#ifdef bool -# undef bool /* needed for Mac */ -#endif -#define bool int -#ifndef MAC_OSX_TK /* Mac provides 'true' and 'false' */ -enum { true = (bool) 1, false = (bool) 0 }; -#endif - /* * File structure: * * Structure definitions and static variables. * @@ -72,25 +58,25 @@ */ /* * In old implementation (the one that used an event ring), and <1><1> were * equivalent sequences. However it is logical to give higher precedence. - * This can be achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1. + * This is achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1. */ #ifndef PREFER_MOST_SPECIALIZED_EVENT -# define PREFER_MOST_SPECIALIZED_EVENT 0 +# define PREFER_MOST_SPECIALIZED_EVENT 1 #endif /* * Traditionally motion events can be combined with buttons in this way: . - * However it should be allowed to express this as in addition. This can be - * achieved by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1. + * However it should be allowed to express this as in addition. This is achieved + * by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1. */ #ifndef SUPPORT_ADDITIONAL_MOTION_SYNTAX -# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 0 /* set to 1 if wanted */ +# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 1 #endif /* * The output for motion events is of the type . This can be changed to become * instead by setting PRINT_SHORT_MOTION_SYNTAX to 1, however this would be a @@ -168,11 +154,11 @@ PSModMaskArr *lastModMaskArr; /* Last matching modifier mask per pattern (except last pattern). * Only needed if pattern sequence is not single (more than one * pattern), and if one of these patterns contains a non-zero * modifier mask. */ - unsigned count:30; /* Only promote to next level if this count has reached count of + unsigned count; /* Only promote to next level if this count has reached count of * pattern. */ unsigned expired:1; /* Whether this entry is expired, this means it has to be removed * from promotion list. */ unsigned keepIt:1; /* Whether to keep this entry, even if expired. */ } PSEntry; @@ -355,16 +341,10 @@ */ #define NEARBY_PIXELS 5 #define NEARBY_MS 500 -/* - * Constant for any (non-zero) button. - */ - -#define ALL_BUTTONS_MASK (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask) - /* * Needed as "no-number" constant for integers. The value of this constant is * outside of integer range (type "int"). (Unfortunatly current version of * Tcl/Tk does not provide C99 integer support.) */ @@ -400,11 +380,11 @@ typedef struct TkBindInfo_ { VirtualEventTable virtualEventTable; /* The virtual events that exist in this interpreter. */ ScreenInfo screenInfo; /* Keeps track of the current display and screen, so it can be * restored after a binding has executed. */ - bool deleted; /* True if the application has been deleted but the structure has been + int deleted; /* 1 if the application has been deleted but the structure has been * preserved. */ Time lastEventTime; /* Needed for time measurement. */ Time lastCurrentTime; /* Needed for time measurement. */ } BindInfo; @@ -440,11 +420,11 @@ * below. */ typedef struct { const char *name; /* Name of modifier. */ - unsigned mask; /* Button/modifier mask value, such as Button1Mask. */ + ModMask mask; /* Button/modifier mask value, such as Button1Mask. */ unsigned flags; /* Various flags; see below for definitions. */ } ModInfo; /* * Flags for ModInfo structures: @@ -709,20 +689,20 @@ /* * Prototypes for local functions defined in this file: */ static void ChangeScreen(Tcl_Interp *interp, char *dispName, int screenIndex); -static bool CreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, +static int CreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, char *virtString, const char *eventString); static int DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, char *virtString, const char *eventString); static void DeleteVirtualEventTable(VirtualEventTable *vetPtr); static void ExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr, unsigned scriptCount, Tcl_DString *dsPtr); static PatSeq * FindSequence(Tcl_Interp *interp, LookupTables *lookupTables, - ClientData object, const char *eventString, bool create, - bool allowVirtual, EventMask *maskPtr); + ClientData object, const char *eventString, int create, + int allowVirtual, EventMask *maskPtr); static void GetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr); static const char * GetField(const char *p, char *copy, unsigned size); static Tcl_Obj * GetPatternObj(const PatSeq *psPtr); static int GetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, Tcl_Obj *virtName); @@ -731,20 +711,20 @@ int objc, Tcl_Obj *const objv[]); static void InitVirtualEventTable(VirtualEventTable *vetPtr); static PatSeq * MatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList, PSList *psSuccList, unsigned patIndex, const Event *eventPtr, ClientData object, PatSeq **physPtrPtr); -static bool NameToWindow(Tcl_Interp *interp, Tk_Window main, +static int NameToWindow(Tcl_Interp *interp, Tk_Window main, Tcl_Obj *objPtr, Tk_Window *tkwinPtr); static unsigned ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr, TkPattern *patPtr, EventMask *eventMaskPtr); static void DoWarp(ClientData clientData); static PSList * GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr, - Tcl_Obj *object, bool onlyConsiderDetailedEvents); + Tcl_Obj *object, int onlyConsiderDetailedEvents); static void ClearLookupTable(LookupTables *lookupTables, ClientData object); static void ClearPromotionLists(Tk_BindingTable bindPtr, ClientData object); -static PSEntry * MakeListEntry(PSList *pool, PatSeq *psPtr, bool needModMasks); +static PSEntry * MakeListEntry(PSList *pool, PatSeq *psPtr, int needModMasks); static void RemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr); static void RemovePatSeqFromPromotionLists(Tk_BindingTable bindPtr, PatSeq *psPtr); static PatSeq * DeletePatSeq(PatSeq *psPtr); static void InsertPatSeq(LookupTables *lookupTables, PatSeq *psPtr); #if SUPPORT_DEBUGGING @@ -759,16 +739,16 @@ static int BindCount = 0; #endif static unsigned Max(unsigned a, unsigned b) { return a < b ? b : a; } static int Abs(int n) { return n < 0 ? -n : n; } -static bool IsOdd(int n) { return n & 1; } +static int IsOdd(int n) { return n & 1; } -static bool TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; } -static bool TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; } +static int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; } +static int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; } -static bool +static int IsSubsetOf( ModMask lhsMask, /* this is a subset */ ModMask rhsMask) /* of this bit field? */ { return (lhsMask & rhsMask) == lhsMask; @@ -853,11 +833,11 @@ } return sndCount - fstCount; } -static bool +static int MatchEventNearby( const XEvent *lhs, /* previous button event */ const XEvent *rhs) /* current button event */ { assert(lhs); @@ -870,11 +850,11 @@ return TestNearbyTime(rhs->xbutton.time, lhs->xbutton.time) && TestNearbyCoords(rhs->xbutton.x_root, lhs->xbutton.x_root) && TestNearbyCoords(rhs->xbutton.y_root, lhs->xbutton.y_root); } -static bool +static int MatchEventRepeat( const XEvent *lhs, /* previous key event */ const XEvent *rhs) /* current key event */ { assert(lhs); @@ -958,45 +938,39 @@ { assert(dispPtr); if (dispPtr->metaModMask) { if (modMask & META_MASK) { - modMask &= ~META_MASK; + modMask &= ~(ModMask)META_MASK; modMask |= dispPtr->metaModMask; } } if (dispPtr->altModMask) { if (modMask & ALT_MASK) { - modMask &= ~ALT_MASK; + modMask &= ~(ModMask)ALT_MASK; modMask |= dispPtr->altModMask; } } return modMask; } -static unsigned +static int ButtonNumberFromState( - unsigned state) + ModMask state) { - if (!(state & ALL_BUTTONS_MASK)) { return 0; } + if (!(state & ALL_BUTTONS)) { return 0; } if (state & Button1Mask) { return 1; } if (state & Button2Mask) { return 2; } if (state & Button3Mask) { return 3; } if (state & Button4Mask) { return 4; } - return 5; -} - -#if SUPPORT_ADDITIONAL_MOTION_SYNTAX -static unsigned -ButtonNumberToMask( - unsigned button) -{ - assert(button > 0); - return Button1Mask << (button - 1); -} -#endif + if (state & Button5Mask) { return 5; } + if (state & Button6Mask) { return 6; } + if (state & Button7Mask) { return 7; } + if (state & Button8Mask) { return 8; } + return 9; +} static void SetupPatternKey( PatternTableKey *key, const PatSeq *psPtr) @@ -1041,11 +1015,11 @@ static PSEntry * MakeListEntry( PSList *pool, PatSeq *psPtr, - bool needModMasks) + int needModMasks) { PSEntry *newEntry = NULL; assert(pool); assert(psPtr); @@ -1070,14 +1044,14 @@ PSModMaskArr_SetSize(newEntry->lastModMaskArr, psPtr->numPats - 1); } newEntry->psPtr = psPtr; newEntry->window = None; - newEntry->expired = false; - newEntry->keepIt = true; + newEntry->expired = 0; + newEntry->keepIt = 1; newEntry->count = 1; - DEBUG(psPtr->owned = false); + DEBUG(psPtr->owned = 0); return newEntry; } /* @@ -1099,11 +1073,11 @@ static PSList * GetLookupForEvent( LookupTables* lookupTables, const Event *eventPtr, Tcl_Obj *object, - bool onlyConsiderDetailedEvents) + int onlyConsiderDetailedEvents) { PatternTableKey key; Tcl_HashEntry *hPtr; assert(lookupTables); @@ -1242,11 +1216,11 @@ /* * Windoze compiler does not allow the definition of these static variables inside a function, * otherwise this should belong to function TkBindInit(). */ TCL_DECLARE_MUTEX(bindMutex); -static bool initialized = false; +static int initialized = 0; void TkBindInit( TkMainInfo *mainPtr) /* The newly created application. */ { @@ -1262,13 +1236,10 @@ assert(sizeof(Info) >= sizeof(unsigned)); /* ensure that our matching algorithm is working (when testing detail) */ assert(sizeof(Detail) == sizeof(Tk_Uid)); - /* test boolean support for safety, because used for 1 bit fields */ - assert(false == 0 && true == 1); - /* test that constant NO_NUMBER is indeed out of integer range */ assert(sizeof(NO_NUMBER) > sizeof(int)); assert(((int) NO_NUMBER) == 0 && NO_NUMBER != 0); /* test expected indices of Button1..Button5, otherwise our button handling is not working */ @@ -1287,53 +1258,53 @@ /* because we expect zero if keySym is empty */ assert(NoSymbol == 0L); /* this must be a union, not a struct, otherwise comparison with NULL will not work */ - assert(Tk_Offset(Detail, name) == Tk_Offset(Detail, info)); + assert(offsetof(Detail, name) == offsetof(Detail, info)); /* we use some constraints about X*Event */ - assert(Tk_Offset(XButtonEvent, time) == Tk_Offset(XMotionEvent, time)); - assert(Tk_Offset(XButtonEvent, x_root) == Tk_Offset(XMotionEvent, x_root)); - assert(Tk_Offset(XButtonEvent, y_root) == Tk_Offset(XMotionEvent, y_root)); - assert(Tk_Offset(XCreateWindowEvent, border_width) == Tk_Offset(XConfigureEvent, border_width)); - assert(Tk_Offset(XCreateWindowEvent, width) == Tk_Offset(XConfigureEvent, width)); - assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XCirculateRequestEvent, window)); - assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XConfigureEvent, window)); - assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XGravityEvent, window)); - assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XMapEvent, window)); - assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XReparentEvent, window)); - assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XUnmapEvent, window)); - assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XConfigureEvent, x)); - assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XGravityEvent, x)); - assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XConfigureEvent, y)); - assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XGravityEvent, y)); - assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XEnterWindowEvent, time)); - assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XLeaveWindowEvent, time)); - assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XKeyEvent, time)); - assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XButtonEvent, root)); - assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XCrossingEvent, root)); - assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XMotionEvent, root)); - assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XButtonEvent, state)); - assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XMotionEvent, state)); - assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XButtonEvent, subwindow)); - assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XCrossingEvent, subwindow)); - assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XMotionEvent, subwindow)); - assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XButtonEvent, time)); - assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XMotionEvent, time)); - assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XButtonEvent, x)); - assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XCrossingEvent, x)); - assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XMotionEvent, x)); - assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XButtonEvent, x_root)); - assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XCrossingEvent, x_root)); - assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XMotionEvent, x_root)); - assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XButtonEvent, y)); - assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XCrossingEvent, y)); - assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XMotionEvent, y)); - assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XButtonEvent, y_root)); - assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XCrossingEvent, y_root)); - assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XMotionEvent, y_root)); + assert(offsetof(XButtonEvent, time) == offsetof(XMotionEvent, time)); + assert(offsetof(XButtonEvent, x_root) == offsetof(XMotionEvent, x_root)); + assert(offsetof(XButtonEvent, y_root) == offsetof(XMotionEvent, y_root)); + assert(offsetof(XCreateWindowEvent, border_width) == offsetof(XConfigureEvent, border_width)); + assert(offsetof(XCreateWindowEvent, width) == offsetof(XConfigureEvent, width)); + assert(offsetof(XCreateWindowEvent, window) == offsetof(XCirculateRequestEvent, window)); + assert(offsetof(XCreateWindowEvent, window) == offsetof(XConfigureEvent, window)); + assert(offsetof(XCreateWindowEvent, window) == offsetof(XGravityEvent, window)); + assert(offsetof(XCreateWindowEvent, window) == offsetof(XMapEvent, window)); + assert(offsetof(XCreateWindowEvent, window) == offsetof(XReparentEvent, window)); + assert(offsetof(XCreateWindowEvent, window) == offsetof(XUnmapEvent, window)); + assert(offsetof(XCreateWindowEvent, x) == offsetof(XConfigureEvent, x)); + assert(offsetof(XCreateWindowEvent, x) == offsetof(XGravityEvent, x)); + assert(offsetof(XCreateWindowEvent, y) == offsetof(XConfigureEvent, y)); + assert(offsetof(XCreateWindowEvent, y) == offsetof(XGravityEvent, y)); + assert(offsetof(XCrossingEvent, time) == offsetof(XEnterWindowEvent, time)); + assert(offsetof(XCrossingEvent, time) == offsetof(XLeaveWindowEvent, time)); + assert(offsetof(XCrossingEvent, time) == offsetof(XKeyEvent, time)); + assert(offsetof(XKeyEvent, root) == offsetof(XButtonEvent, root)); + assert(offsetof(XKeyEvent, root) == offsetof(XCrossingEvent, root)); + assert(offsetof(XKeyEvent, root) == offsetof(XMotionEvent, root)); + assert(offsetof(XKeyEvent, state) == offsetof(XButtonEvent, state)); + assert(offsetof(XKeyEvent, state) == offsetof(XMotionEvent, state)); + assert(offsetof(XKeyEvent, subwindow) == offsetof(XButtonEvent, subwindow)); + assert(offsetof(XKeyEvent, subwindow) == offsetof(XCrossingEvent, subwindow)); + assert(offsetof(XKeyEvent, subwindow) == offsetof(XMotionEvent, subwindow)); + assert(offsetof(XKeyEvent, time) == offsetof(XButtonEvent, time)); + assert(offsetof(XKeyEvent, time) == offsetof(XMotionEvent, time)); + assert(offsetof(XKeyEvent, x) == offsetof(XButtonEvent, x)); + assert(offsetof(XKeyEvent, x) == offsetof(XCrossingEvent, x)); + assert(offsetof(XKeyEvent, x) == offsetof(XMotionEvent, x)); + assert(offsetof(XKeyEvent, x_root) == offsetof(XButtonEvent, x_root)); + assert(offsetof(XKeyEvent, x_root) == offsetof(XCrossingEvent, x_root)); + assert(offsetof(XKeyEvent, x_root) == offsetof(XMotionEvent, x_root)); + assert(offsetof(XKeyEvent, y) == offsetof(XButtonEvent, y)); + assert(offsetof(XKeyEvent, y) == offsetof(XCrossingEvent, y)); + assert(offsetof(XKeyEvent, y) == offsetof(XMotionEvent, y)); + assert(offsetof(XKeyEvent, y_root) == offsetof(XButtonEvent, y_root)); + assert(offsetof(XKeyEvent, y_root) == offsetof(XCrossingEvent, y_root)); + assert(offsetof(XKeyEvent, y_root) == offsetof(XMotionEvent, y_root)); /* * Initialize the static data structures used by the binding package. They * are only initialized once, no matter how many interps are created. */ @@ -1342,11 +1313,11 @@ Tcl_MutexLock(&bindMutex); if (!initialized) { Tcl_HashEntry *hPtr; const ModInfo *modPtr; const EventInfo *eiPtr; - bool newEntry; + int newEntry; unsigned i; #ifdef REDO_KEYSYM_LOOKUP const KeySymInfo *kPtr; Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS); @@ -1383,11 +1354,11 @@ for (eiPtr = eventArray; eiPtr->name; ++eiPtr) { hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry); Tcl_SetHashValue(hPtr, eiPtr); } - initialized = true; + initialized = 1; } Tcl_MutexUnlock(&bindMutex); } mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp); @@ -1395,11 +1366,11 @@ bindInfoPtr = ckalloc(sizeof(BindInfo)); InitVirtualEventTable(&bindInfoPtr->virtualEventTable); bindInfoPtr->screenInfo.curDispPtr = NULL; bindInfoPtr->screenInfo.curScreenIndex = -1; bindInfoPtr->screenInfo.bindingDepth = 0; - bindInfoPtr->deleted = false; + bindInfoPtr->deleted = 0; bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); bindInfoPtr->lastEventTime = 0; mainPtr->bindInfo = bindInfoPtr; DEBUG(countBindItems += 1); @@ -1433,11 +1404,11 @@ Tk_DeleteBindingTable(mainPtr->bindingTable); mainPtr->bindingTable = NULL; bindInfoPtr = mainPtr->bindInfo; DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable); - bindInfoPtr->deleted = true; + bindInfoPtr->deleted = 1; Tcl_EventuallyFree(bindInfoPtr, TCL_DYNAMIC); mainPtr->bindInfo = NULL; DEBUG(countBindItems -= 1); assert(countBindItems > 0 || countTableItems == 0); @@ -1584,11 +1555,11 @@ assert(psPtr->numPats >= 1u); if (!(psPtr->added)) { PatternTableKey key; Tcl_HashEntry *hPtr; - bool isNew; + int isNew; PSList *psList; PSEntry *psEntry; SetupPatternKey(&key, psPtr); hPtr = Tcl_CreateHashEntry(&lookupTables->listTable, (char *) &key, &isNew); @@ -1600,13 +1571,13 @@ DEBUG(countListItems += 1); } else { psList = Tcl_GetHashValue(hPtr); } - psEntry = MakeListEntry(&lookupTables->entryPool, psPtr, false); + psEntry = MakeListEntry(&lookupTables->entryPool, psPtr, 0); PSList_Append(psList, psEntry); - psPtr->added = true; + psPtr->added = 1; } } /* *-------------------------------------------------------------- * @@ -1636,12 +1607,12 @@ Tcl_Interp *interp, /* Used for error reporting. */ Tk_BindingTable bindPtr, /* Table in which to create binding. */ ClientData object, /* Token for object with which binding is associated. */ const char *eventString, /* String describing event sequence that triggers binding. */ const char *script, /* Contains Tcl script to execute when binding triggers. */ - bool append) /* False means replace any existing binding for eventString; - * True means append to that binding. If the existing binding is + int append) /* 0 means replace any existing binding for eventString; + * 1 means append to that binding. If the existing binding is * for a callback function and not a Tcl command string, the * existing binding will always be replaced. */ { PatSeq *psPtr; EventMask eventMask; @@ -1652,11 +1623,11 @@ assert(object); assert(eventString); assert(script); psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, - !!*script, true, &eventMask); + !!*script, 1, &eventMask); if (!*script) { assert(!psPtr || psPtr->added); /* Silently ignore empty scripts -- see SF#3006842 */ return eventMask; @@ -1676,11 +1647,11 @@ PromArr_ResizeAndClear(&bindPtr->promArr, psPtr->numPats); } if (!psPtr->script) { Tcl_HashEntry *hPtr; - bool isNew; + int isNew; /* * This pattern sequence was just created. Link the pattern into the * list associated with the object, so that if the object goes away, * these bindings will all automatically be deleted. @@ -1741,11 +1712,11 @@ assert(bindPtr); assert(object); assert(eventString); - psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, false, true, NULL); + psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL); if (!psPtr) { Tcl_ResetResult(interp); } else { Tcl_HashEntry *hPtr; PatSeq *prevPtr; @@ -1814,11 +1785,11 @@ assert(bindPtr); assert(object); assert(eventString); - psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, false, true, NULL); + psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL); assert(!psPtr || TEST_PSENTRY(psPtr)); return psPtr ? psPtr->script : NULL; } /* @@ -1902,11 +1873,11 @@ PSList *psList = Tcl_GetHashValue(hPtr); PSEntry *psEntry; TK_DLIST_FOREACH(psEntry, psList) { if (psEntry->psPtr == psPtr) { - psPtr->added = false; + psPtr->added = 0; RemoveListEntry(&lookupTables->entryPool, psEntry); return; } } } @@ -2054,11 +2025,11 @@ ClearLookupTable(&bindPtr->lookupTables, object); ClearPromotionLists(bindPtr, object); for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) { assert(TEST_PSENTRY(psPtr)); - DEBUG(psPtr->added = false); + DEBUG(psPtr->added = 0); nextPtr = DeletePatSeq(psPtr); } Tcl_DeleteHashEntry(hPtr); } @@ -2106,23 +2077,23 @@ eventInfo[eventType].countDetailed = 0; } } /* helper function */ -static bool +static int IsBetterMatch( const PatSeq *fstMatchPtr, const PatSeq *sndMatchPtr) /* this is a better match? */ { int diff; - if (!sndMatchPtr) { return false; } - if (!fstMatchPtr) { return true; } + if (!sndMatchPtr) { return 0; } + if (!fstMatchPtr) { return 1; } diff = CountSpecialized(fstMatchPtr, sndMatchPtr); - if (diff > 0) { return true; } - if (diff < 0) { return false; } + if (diff > 0) { return 1; } + if (diff < 0) { return 0; } #if PREFER_MOST_SPECIALIZED_EVENT { /* local scope */ #define M (Tcl_WideUInt)1000000 static const Tcl_WideUInt weight[5] = { 0, 1, M, M*M, M*M*M }; @@ -2145,12 +2116,12 @@ } for (i = 0; i < sndMatchPtr->numPats; ++i) { assert(GetCount(sndMatchPtr, i) < SIZE_OF_ARRAY(weight)); sndCount += weight[GetCount(sndMatchPtr, i)]; } - if (sndCount > fstCount) { return true; } - if (sndCount < fstCount) { return false; } + if (sndCount > fstCount) { return 1; } + if (sndCount < fstCount) { return 0; } } #endif return sndMatchPtr->number > fstMatchPtr->number; } @@ -2188,11 +2159,11 @@ unsigned i, k; assert(bindPtr); assert(eventPtr); assert(tkwin); - assert(numObjects > 0); + assert(numObjects >= 0); /* * Ignore events on windows that don't have names: these are windows like * wrapper windows that shouldn't be visible to the application. */ @@ -2249,20 +2220,20 @@ return; } break; case KeyPress: case KeyRelease: { - bool reset = true; + int reset = 1; if (eventPtr->xkey.time) { bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); bindInfoPtr->lastEventTime = eventPtr->xkey.time; } /* modifier keys should not influence button events */ for (i = 0; i < (unsigned) dispPtr->numModKeyCodes; ++i) { if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) { - reset = false; + reset = 0; } } if (reset) { /* reset repetition count for button events */ bindPtr->eventInfo[ButtonPress].countAny = 0; @@ -2418,12 +2389,12 @@ for (k = 0; k < (unsigned) numObjects; ++k) { PSList *psSuccList = PromArr_First(bindPtr->promArr); PatSeq *bestPtr; - psl[0] = GetLookupForEvent(physTables, curEvent, objArr[k], true); - psl[1] = GetLookupForEvent(physTables, curEvent, objArr[k], false); + psl[0] = GetLookupForEvent(physTables, curEvent, objArr[k], 1); + psl[1] = GetLookupForEvent(physTables, curEvent, objArr[k], 0); assert(psl[0] == NULL || psl[0] != psl[1]); psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL); psPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL); @@ -2463,12 +2434,12 @@ /* * Note that virtual events cannot promote. */ - psl[0] = GetLookupForEvent(virtTables, curEvent, NULL, true); - psl[1] = GetLookupForEvent(virtTables, curEvent, NULL, false); + psl[0] = GetLookupForEvent(virtTables, curEvent, NULL, 1); + psl[1] = GetLookupForEvent(virtTables, curEvent, NULL, 0); assert(psl[0] == NULL || psl[0] != psl[1]); mPtr = MatchPatterns(dispPtr, bindPtr, psl[0], NULL, 0, curEvent, objArr[k], &matchPtr); if (mPtr) { @@ -2519,11 +2490,11 @@ * 5) Current entry has been matched with a different window. */ if (psEntry->keepIt) { assert(!psEntry->expired); - psEntry->keepIt = false; + psEntry->keepIt = 0; } else if (psEntry->expired || psEntry->window != curEvent->xev.xany.window || (patPtr->info && curEvent->detail.info && patPtr->eventType == (unsigned) curEvent->xev.type @@ -2666,11 +2637,11 @@ * *---------------------------------------------------------------------- */ /* helper function */ -static bool +static int VirtPatIsBound( Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ PatSeq *psPtr, /* Test this pattern. */ ClientData object, /* Check for this binding tag. */ PatSeq **physPtrPtr) /* Input: the best physical event. @@ -2689,11 +2660,11 @@ const TkPattern *physPatPtr = (*physPtrPtr)->pats; const TkPattern *virtPatPtr = psPtr->pats; if (physPatPtr->info || !virtPatPtr->info) { if (IsSubsetOf(virtPatPtr->modMask, physPatPtr->modMask)) { - return false; /* we cannot surpass this match */ + return 0; /* we cannot surpass this match */ } } } /* otherwise on some systems the key contains uninitialized bytes */ @@ -2709,15 +2680,15 @@ key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, hPtr); if ((hPtr = Tcl_FindHashEntry(&bindPtr->lookupTables.patternTable, (char *) &key))) { /* The physical event matches this virtual event's definition. */ *physPtrPtr = (PatSeq *) Tcl_GetHashValue(hPtr); - return true; + return 1; } } - return false; + return 0; } /* helper function */ static int Compare( @@ -2731,11 +2702,11 @@ diff = CountSpecialized(fstMatchPtr, sndMatchPtr); return diff ? diff : (int) sndMatchPtr->count - (int) fstMatchPtr->count; } /* helper function */ -static bool +static int CompareModMasks( const PSModMaskArr *fstModMaskArr, const PSModMaskArr *sndModMaskArr, ModMask fstModMask, ModMask sndModMask) @@ -2795,11 +2766,11 @@ Window window; PSEntry *psEntry; PatSeq *bestPtr; PatSeq *bestPhysPtr; ModMask bestModMask; - const PSModMaskArr *bestModMaskArr; + const PSModMaskArr *bestModMaskArr = NULL; assert(dispPtr); assert(bindPtr); assert(curEvent); @@ -2820,11 +2791,11 @@ assert((psPtr->object == NULL) == (physPtrPtr != NULL)); assert(psPtr->object || patIndex == 0); assert(psPtr->numPats > patIndex); if (psPtr->object - ? psPtr->object == object + ? psPtr->object == object : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) { TkPattern *patPtr = psPtr->pats + patIndex; if (patPtr->eventType == (unsigned) curEvent->xev.type && (curEvent->xev.type != CreateNotify @@ -2837,11 +2808,11 @@ * be the better place. */ ModMask modMask = ResolveModifiers(dispPtr, patPtr->modMask); ModMask curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask); - psEntry->expired = true; /* remove it from promotion list */ + psEntry->expired = 1; /* remove it from promotion list */ if ((modMask & ~curModMask) == 0) { unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny; if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) { @@ -2874,12 +2845,12 @@ if (physPtrPtr) { bestPhysPtr = *physPtrPtr; } } } else { - DEBUG(psEntry->expired = false); - psEntry->keepIt = true; /* don't remove it from promotion list */ + DEBUG(psEntry->expired = 0); + psEntry->keepIt = 1; /* don't remove it from promotion list */ } } else if (psSuccList) { /* * Not a final pattern, but matching, so promote it to next level. * But do not promote if count of current pattern is not yet reached. @@ -2897,13 +2868,13 @@ assert(psNewEntry->count == 1u); PSList_Append(psSuccList, psNewEntry); psNewEntry->window = window; /* bind to current window */ } else { assert(psEntry->count < patPtr->count); - DEBUG(psEntry->expired = false); + DEBUG(psEntry->expired = 0); psEntry->count += 1; - psEntry->keepIt = true; /* don't remove it from promotion list */ + psEntry->keepIt = 1; /* don't remove it from promotion list */ } } } } } @@ -2955,11 +2926,11 @@ Tcl_DStringInit(&buf); evPtr = &eventPtr->xev; flags = (evPtr->type < TK_LASTEVENT) ? flagArray[evPtr->type] : 0; - while (true) { + while (1) { char numStorage[TCL_INTEGER_SPACE]; const char *string; Tcl_WideInt number; /* @@ -3464,11 +3435,11 @@ PatSeq *psPtr; for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) { assert(TEST_PSENTRY(psPtr)); nextPtr = psPtr->nextSeqPtr; - DEBUG(psPtr->owned = false); + DEBUG(psPtr->owned = 0); FreePatSeq(psPtr); } } Tcl_DeleteHashTable(&vetPtr->lookupTables.patternTable); @@ -3502,11 +3473,11 @@ * differently than they did previously. * *---------------------------------------------------------------------- */ -static bool +static int CreateVirtualEvent( Tcl_Interp *interp, /* Used for error reporting. */ VirtualEventTable *vetPtr, /* Table in which to augment virtual event. */ char *virtString, /* Name of new virtual event. */ const char *eventString) /* String describing physical event that triggers virtual event. */ @@ -3520,19 +3491,19 @@ assert(vetPtr); assert(virtString); assert(eventString); if (!(virtUid = GetVirtualEventUid(interp, virtString))) { - return false; + return 0; } /* * Find/create physical event */ - if (!(psPtr = FindSequence(interp, &vetPtr->lookupTables, NULL, eventString, true, false, NULL))) { - return false; + if (!(psPtr = FindSequence(interp, &vetPtr->lookupTables, NULL, eventString, 1, 0, NULL))) { + return 0; } assert(TEST_PSENTRY(psPtr)); /* * Find/create virtual event. @@ -3547,17 +3518,17 @@ owned = Tcl_GetHashValue(vhPtr); if (!PhysOwned_Contains(owned, psPtr)) { PhysOwned_Append(&owned, psPtr); Tcl_SetHashValue(vhPtr, owned); - DEBUG(psPtr->owned = true); + DEBUG(psPtr->owned = 1); InsertPatSeq(&vetPtr->lookupTables, psPtr); /* Make physical event so it can trigger the virtual event. */ VirtOwners_Append(&psPtr->ptr.owners, vhPtr); } - return true; + return 1; } /* *-------------------------------------------------------------- * @@ -3616,11 +3587,11 @@ * Delete only the specific physical event associated with the virtual * event. If the physical event doesn't already exist, or the virtual * event doesn't own that physical event, return w/o doing anything. */ - eventPSPtr = FindSequence(interp, lookupTables, NULL, eventString, false, false, NULL); + eventPSPtr = FindSequence(interp, lookupTables, NULL, eventString, 0, 0, NULL); if (!eventPSPtr) { const char *string = Tcl_GetString(Tcl_GetObjResult(interp)); return string[0] ? TCL_ERROR : TCL_OK; } } @@ -3653,11 +3624,11 @@ } else { /* * Removed last reference to this physical event, so remove it * from lookup table. */ - DEBUG(psPtr->owned = false); + DEBUG(psPtr->owned = 0); RemovePatSeqFromLookup(&vetPtr->lookupTables, psPtr); DeletePatSeq(psPtr); } /* @@ -3837,12 +3808,12 @@ Tk_Window tkwin; Tk_Window tkwin2; TkWindow *mainPtr; EventMask eventMask; Tcl_Obj *userDataObj; - bool synch; - bool warp; + int synch; + int warp; unsigned count; unsigned flags; int number; unsigned i; @@ -3905,11 +3876,11 @@ } memset(&event, 0, sizeof(event)); event.general.xany.type = pat.eventType; event.general.xany.serial = NextRequest(Tk_Display(tkwin)); - event.general.xany.send_event = False; + event.general.xany.send_event = 0; if (windowName[0]) { event.general.xany.window = Tk_WindowId(tkwin); } else { event.general.xany.window = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)); } @@ -3948,17 +3919,17 @@ /* * Process the remaining arguments to fill in additional fields of the event. */ - synch = true; + synch = 1; warp = 0; pos = TCL_QUEUE_TAIL; for (i = 2; i < (unsigned) objc; i += 2) { Tcl_Obj *optionPtr, *valuePtr; - bool badOpt = false; + int badOpt = 0; int index; optionPtr = objv[i]; valuePtr = objv[i + 1]; @@ -3984,11 +3955,11 @@ case EVENT_WARP: if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) { return TCL_ERROR; } if (!(flags & KEY_BUTTON_MOTION_VIRTUAL)) { - badOpt = true; + badOpt = 1; } break; case EVENT_WHEN: pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr, queuePosition, valuePtr); if ((int) pos < -1) { @@ -4001,41 +3972,41 @@ return TCL_ERROR; } if (flags & CONFIG) { event.general.xconfigure.above = Tk_WindowId(tkwin2); } else { - badOpt = true; + badOpt = 1; } break; case EVENT_BORDER: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (flags & (CREATE|CONFIG)) { event.general.xcreatewindow.border_width = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_BUTTON: if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (flags & BUTTON) { event.general.xbutton.button = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_COUNT: if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (flags & EXPOSE) { event.general.xexpose.count = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_DATA: if (flags & VIRTUAL) { /* @@ -4043,21 +4014,21 @@ * completes and we know that the event generation is really * going to happen. */ userDataObj = valuePtr; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_DELTA: if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if ((flags & KEY) && event.general.xkey.type == MouseWheelEvent) { event.general.xkey.keycode = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_DETAIL: number = TkFindStateNumObj(interp, optionPtr, notifyDetail, valuePtr); if (number < 0) { @@ -4066,21 +4037,21 @@ if (flags & FOCUS) { event.general.xfocus.detail = number; } else if (flags & CROSSING) { event.general.xcrossing.detail = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_FOCUS: if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (flags & CROSSING) { event.general.xcrossing.focus = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_HEIGHT: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { return TCL_ERROR; @@ -4088,21 +4059,21 @@ if (flags & EXPOSE) { event.general.xexpose.height = number; } else if (flags & CONFIG) { event.general.xconfigure.height = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_KEYCODE: if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if ((flags & KEY) && event.general.xkey.type != MouseWheelEvent) { event.general.xkey.keycode = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_KEYSYM: { KeySym keysym; const char *value; @@ -4120,11 +4091,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf("no keycode for keysym \"%s\"", value)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYCODE", value, NULL); return TCL_ERROR; } if (!(flags & KEY) || (event.general.xkey.type == MouseWheelEvent)) { - badOpt = true; + badOpt = 1; } break; } case EVENT_MODE: if ((number = TkFindStateNumObj(interp, optionPtr, notifyMode, valuePtr)) < 0) { @@ -4133,11 +4104,11 @@ if (flags & CROSSING) { event.general.xcrossing.mode = number; } else if (flags & FOCUS) { event.general.xfocus.mode = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_OVERRIDE: if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; @@ -4149,51 +4120,51 @@ } else if (flags & REPARENT) { event.general.xreparent.override_redirect = number; } else if (flags & CONFIG) { event.general.xconfigure.override_redirect = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_PLACE: if ((number = TkFindStateNumObj(interp, optionPtr, circPlace, valuePtr)) < 0) { return TCL_ERROR; } if (flags & CIRC) { event.general.xcirculate.place = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_ROOT: if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) { return TCL_ERROR; } if (flags & KEY_BUTTON_MOTION_CROSSING) { event.general.xkey.root = Tk_WindowId(tkwin2); } else { - badOpt = true; + badOpt = 1; } break; case EVENT_ROOTX: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (flags & KEY_BUTTON_MOTION_CROSSING) { event.general.xkey.x_root = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_ROOTY: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (flags & KEY_BUTTON_MOTION_CROSSING) { event.general.xkey.y_root = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_SEND: { const char *value; @@ -4206,15 +4177,15 @@ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } if (number) { /* - * send_event only expects True or False. We cannot allow arbitrary non-zero + * send_event only expects 1 or 0. We cannot allow arbitrary non-zero * values, otherwise the thing with GENERATED_FOCUS_EVENT_MAGIC will not * work. */ - number = True; + number = 1; } } else if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } event.general.xany.send_event |= number; @@ -4240,21 +4211,21 @@ if ((number = TkFindStateNumObj(interp, optionPtr, visNotify, valuePtr)) < 0) { return TCL_ERROR; } event.general.xvisibility.state = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_SUBWINDOW: if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) { return TCL_ERROR; } if (flags & KEY_BUTTON_MOTION_CROSSING) { event.general.xkey.subwindow = Tk_WindowId(tkwin2); } else { - badOpt = true; + badOpt = 1; } break; case EVENT_TIME: { if (strcmp(Tcl_GetString(valuePtr), "current") == 0) { TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -4266,11 +4237,11 @@ if (flags & KEY_BUTTON_MOTION_CROSSING) { event.general.xkey.time = number; } else if (flags & PROP) { event.general.xproperty.time = number; } else { - badOpt = true; + badOpt = 1; } break; } case EVENT_WIDTH: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { @@ -4279,21 +4250,21 @@ if (flags & EXPOSE) { event.general.xexpose.width = number; } else if (flags & (CREATE|CONFIG)) { event.general.xcreatewindow.width = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_WINDOW: if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) { return TCL_ERROR; } if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) { event.general.xcreatewindow.window = Tk_WindowId(tkwin2); } else { - badOpt = true; + badOpt = 1; } break; case EVENT_X: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { return TCL_ERROR; @@ -4316,11 +4287,11 @@ } else if (flags & (CREATE|CONFIG|GRAVITY)) { event.general.xcreatewindow.x = number; } else if (flags & REPARENT) { event.general.xreparent.x = number; } else { - badOpt = true; + badOpt = 1; } break; case EVENT_Y: if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { return TCL_ERROR; @@ -4343,11 +4314,11 @@ } else if (flags & (CREATE|CONFIG|GRAVITY)) { event.general.xcreatewindow.y = number; } else if (flags & REPARENT) { event.general.xreparent.y = number; } else { - badOpt = true; + badOpt = 1; } break; } if (badOpt) { @@ -4432,11 +4403,11 @@ * None. * *--------------------------------------------------------------------------- */ -static bool +static int NameToWindow( Tcl_Interp *interp, /* Interp for error return and name lookup. */ Tk_Window mainWin, /* Main window of application. */ Tcl_Obj *objPtr, /* Contains name or id string of window. */ Tk_Window *tkwinPtr) /* Filled with token for window. */ @@ -4450,11 +4421,11 @@ name = Tcl_GetString(objPtr); if (name[0] == '.') { if (!(tkwin = Tk_NameToWindow(interp, name, mainWin))) { - return false; + return 0; } } else { Window id; tkwin = NULL; @@ -4469,17 +4440,17 @@ } if (!tkwin) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad window name/identifier \"%s\"", name)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW_ID", name, NULL); - return false; + return 0; } } assert(tkwin); *tkwinPtr = tkwin; - return true; + return 1; } /* *------------------------------------------------------------------------- * @@ -4603,26 +4574,26 @@ LookupTables *lookupTables, /* Tables used for lookup. */ ClientData object, /* For binding table, token for object with which binding is * associated. For virtual event table, NULL. */ const char *eventString, /* String description of pattern to match on. See user * documentation for details. */ - bool create, /* False means don't create the entry if it doesn't already exist. - * True means create. */ - bool allowVirtual, /* False means that virtual events are not allowed in the sequence. - * True otherwise. */ + int create, /* 0 means don't create the entry if it doesn't already exist. + * 1 means create. */ + int allowVirtual, /* 0 means that virtual events are not allowed in the sequence. + * 1 otherwise. */ EventMask *maskPtr) /* *maskPtr is filled in with the event types on which this * pattern sequence depends. */ { unsigned patsBufSize = 1; unsigned numPats; unsigned totalCount = 0; - bool virtualFound = false; + int virtualFound = 0; const char *p = eventString; TkPattern *patPtr; PatSeq *psPtr; Tcl_HashEntry *hPtr; - bool isNew; + int isNew; unsigned count; unsigned maxCount = 0; EventMask eventMask = 0; ModMask modMask = 0; PatternTableKey key; @@ -4658,11 +4629,11 @@ "virtual event not allowed in definition of another virtual event", -1)); Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "INNER", NULL); ckfree(psPtr); return NULL; } - virtualFound = true; + virtualFound = 1; } if (count > 1u) { maxCount = Max(count, maxCount); } @@ -4733,18 +4704,18 @@ DEBUG(countSeqItems += 1); psPtr->numPats = numPats; psPtr->count = totalCount; psPtr->number = lookupTables->number++; - psPtr->added = false; + psPtr->added = 0; psPtr->modMaskUsed = (modMask != 0); psPtr->script = NULL; psPtr->nextSeqPtr = Tcl_GetHashValue(hPtr); psPtr->hPtr = hPtr; psPtr->ptr.nextObj = NULL; assert(psPtr->ptr.owners == NULL); - DEBUG(psPtr->owned = false); + DEBUG(psPtr->owned = 0); Tcl_SetHashValue(hPtr, psPtr); if (maskPtr) { *maskPtr = eventMask; } @@ -4894,11 +4865,11 @@ } else { unsigned eventFlags; char field[512]; Tcl_HashEntry *hPtr; - while (true) { + while (1) { ModInfo *modPtr; p = GetField(p, field, sizeof(field)); if (*p == '>') { /* @@ -4972,21 +4943,21 @@ patPtr, 0, Tcl_ObjPrintf("specified button \"%s\" for non-button event", field), "NON_BUTTON"); } #if SUPPORT_ADDITIONAL_MOTION_SYNTAX - patPtr->modMask |= ButtonNumberToMask(button); + patPtr->modMask |= TkGetButtonMask(button); p = SkipFieldDelims(p); while (*p && *p != '>') { p = SkipFieldDelims(GetField(p, field, sizeof(field))); if ((button = GetButtonNumber(field)) == 0) { return FinalizeParseEventDescription( interp, patPtr, 0, Tcl_ObjPrintf("bad button number \"%s\"", field), "BUTTON"); } - patPtr->modMask |= ButtonNumberToMask(button); + patPtr->modMask |= TkGetButtonMask(button); } patPtr->info = ButtonNumberFromState(patPtr->modMask); #endif } else { return FinalizeParseEventDescription( @@ -5112,11 +5083,11 @@ Tcl_AppendToObj(patternObj, &c, 1); } else if (patPtr->eventType == VirtualEvent) { assert(patPtr->name); Tcl_AppendPrintfToObj(patternObj, "<<%s>>", patPtr->name); } else { - unsigned modMask; + ModMask modMask; const ModInfo *modPtr; /* * It's a more general event specification. First check for "Double", * "Triple", "Quadruple", then modifiers, then event type, then keysym @@ -5132,11 +5103,11 @@ } modMask = patPtr->modMask; #if PRINT_SHORT_MOTION_SYNTAX if (patPtr->eventType == MotionNotify) { - modMask &= ~ALL_BUTTONS_MASK; + modMask &= ~(ModMask)ALL_BUTTONS; } #endif for (modPtr = modArray; modMask; ++modPtr) { if (modPtr->mask & modMask) { @@ -5160,20 +5131,20 @@ } break; } case ButtonPress: case ButtonRelease: - assert(patPtr->info <= Button5); + assert(patPtr->info <= Button9); Tcl_AppendPrintfToObj(patternObj, "-%d", (int) patPtr->info); break; #if PRINT_SHORT_MOTION_SYNTAX case MotionNotify: { - unsigned mask = patPtr->modMask; - while (mask & ALL_BUTTONS_MASK) { - unsigned button = ButtonNumberFromState(mask); - Tcl_AppendPrintfToObj(patternObj, "-%u", button); - mask &= ~ButtonNumberToMask(button); + ModMask mask = patPtr->modMask; + while (mask & ALL_BUTTONS) { + int button = ButtonNumberFromState(mask); + Tcl_AppendPrintfToObj(patternObj, "-%d", button); + mask &= ~TkGetButtonMask(button); } break; } #endif } Index: generic/tkBitmap.c ================================================================== --- generic/tkBitmap.c +++ generic/tkBitmap.c @@ -86,11 +86,11 @@ typedef struct { const char *source; /* Bitmap bits. */ int width, height; /* Dimensions of bitmap. */ } DataKey; -typedef struct ThreadSpecificData { +typedef struct { int initialized; /* 0 means table below needs initializing. */ Tcl_HashTable predefBitmapTable; /* Hash table created by Tk_DefineBitmap to * map from a name to a collection of in-core * data about a bitmap. The table is indexed @@ -534,11 +534,11 @@ if (dispPtr == NULL || !dispPtr->bitmapInit) { unknown: Tcl_Panic("Tk_NameOfBitmap received unknown bitmap argument"); } - idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); + idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap); if (idHashPtr == NULL) { goto unknown; } bitmapPtr = Tcl_GetHashValue(idHashPtr); return bitmapPtr->nameHashPtr->key.string; @@ -576,11 +576,11 @@ if (!dispPtr->bitmapInit) { unknownBitmap: Tcl_Panic("Tk_SizeOfBitmap received unknown bitmap argument"); } - idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); + idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap); if (idHashPtr == NULL) { goto unknownBitmap; } bitmapPtr = Tcl_GetHashValue(idHashPtr); *widthPtr = bitmapPtr->width; @@ -665,11 +665,11 @@ if (!dispPtr->bitmapInit) { Tcl_Panic("Tk_FreeBitmap called before Tk_GetBitmap"); } - idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); + idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap); if (idHashPtr == NULL) { Tcl_Panic("Tk_FreeBitmap received unknown bitmap argument"); } FreeBitmap(Tcl_GetHashValue(idHashPtr)); } @@ -1155,13 +1155,13 @@ Tcl_Panic("TkDebugBitmap found empty hash table entry"); } for ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(bitmapPtr->resourceRefCount)); + Tcl_NewWideIntObj(bitmapPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(bitmapPtr->objRefCount)); + Tcl_NewWideIntObj(bitmapPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } Index: generic/tkBusy.c ================================================================== --- generic/tkBusy.c +++ generic/tkBusy.c @@ -21,11 +21,11 @@ * platforms this may or may not have an effect. */ static const Tk_OptionSpec busyOptionSpecs[] = { {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_BUSY_CURSOR, -1, Tk_Offset(Busy, cursor), + DEF_BUSY_CURSOR, -1, offsetof(Busy, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /* @@ -570,11 +570,11 @@ busyPtr->x = Tk_X(tkRef); busyPtr->y = Tk_Y(tkRef); busyPtr->cursor = NULL; Tk_SetClass(tkBusy, "Busy"); busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs); - if (Tk_InitOptions(interp, (char *) busyPtr, busyPtr->optionTable, + if (Tk_InitOptions(interp, busyPtr, busyPtr->optionTable, tkBusy) != TCL_OK) { Tk_DestroyWindow(tkBusy); return NULL; } SetWindowInstanceData(tkBusy, busyPtr); @@ -637,11 +637,11 @@ int objc, Tcl_Obj *const objv[]) { Tk_Cursor oldCursor = busyPtr->cursor; - if (Tk_SetOptions(interp, (char *) busyPtr, busyPtr->optionTable, objc, + if (Tk_SetOptions(interp, busyPtr, busyPtr->optionTable, objc, objv, busyPtr->tkBusy, NULL, NULL) != TCL_OK) { return TCL_ERROR; } if (busyPtr->cursor != oldCursor) { if (busyPtr->cursor == NULL) { @@ -686,11 +686,11 @@ if (TkGetWindowFromObj(interp, Tk_MainWindow(interp), windowObj, &tkwin) != TCL_OK) { return NULL; } - hPtr = Tcl_FindHashEntry(busyTablePtr, (char *) tkwin); + hPtr = Tcl_FindHashEntry(busyTablePtr, tkwin); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't find busy window \"%s\"", Tcl_GetString(windowObj))); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "BUSY", Tcl_GetString(windowObj), NULL); @@ -760,10 +760,13 @@ if (Tk_IsMapped(busyPtr->tkRef)) { TkpShowBusyWindow(busyPtr); } else { TkpHideBusyWindow(busyPtr); } + if (result == TCL_OK) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), -1)); + } return result; } /* *---------------------------------------------------------------------- @@ -793,15 +796,16 @@ Tcl_HashTable *busyTablePtr = &((TkWindow *) tkwin)->mainPtr->busyTable; Busy *busyPtr; Tcl_Obj *objPtr; int index, result = TCL_OK; static const char *const optionStrings[] = { - "cget", "configure", "current", "forget", "hold", "status", NULL + "busywindow", "cget", "configure", "current", "forget", "hold", + "status", NULL }; enum options { - BUSY_CGET, BUSY_CONFIGURE, BUSY_CURRENT, BUSY_FORGET, BUSY_HOLD, - BUSY_STATUS + BUSY_BUSYWINDOW, BUSY_CGET, BUSY_CONFIGURE, BUSY_CURRENT, BUSY_FORGET, + BUSY_HOLD, BUSY_STATUS }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "options ?arg arg ...?"); return TCL_ERROR; @@ -822,10 +826,23 @@ if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { + case BUSY_BUSYWINDOW: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + busyPtr = GetBusy(interp, busyTablePtr, objv[2]); + if (busyPtr == NULL) { + Tcl_ResetResult(interp); + return TCL_OK; + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), -1)); + return TCL_OK; + case BUSY_CGET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "window option"); return TCL_ERROR; } @@ -832,11 +849,11 @@ busyPtr = GetBusy(interp, busyTablePtr, objv[2]); if (busyPtr == NULL) { return TCL_ERROR; } Tcl_Preserve(busyPtr); - objPtr = Tk_GetOptionValue(interp, (char *) busyPtr, + objPtr = Tk_GetOptionValue(interp, busyPtr, busyPtr->optionTable, objv[3], busyPtr->tkBusy); if (objPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, objPtr); @@ -853,11 +870,11 @@ if (busyPtr == NULL) { return TCL_ERROR; } Tcl_Preserve(busyPtr); if (objc <= 4) { - objPtr = Tk_GetOptionInfo(interp, (char *) busyPtr, + objPtr = Tk_GetOptionInfo(interp, busyPtr, busyPtr->optionTable, (objc == 4) ? objv[3] : NULL, busyPtr->tkBusy); if (objPtr == NULL) { result = TCL_ERROR; } else { Index: generic/tkButton.c ================================================================== --- generic/tkButton.c +++ generic/tkButton.c @@ -14,11 +14,11 @@ #include "tkInt.h" #include "tkButton.h" #include "default.h" -typedef struct ThreadSpecificData { +typedef struct { int defaultsInitialized; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* @@ -68,416 +68,416 @@ * separate table for each of the four widget classes. */ static const Tk_OptionSpec labelOptionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder), + DEF_BUTTON_ACTIVE_BG_COLOR, -1, offsetof(TkButton, activeBorder), 0, DEF_BUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", - DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg), + DEF_BUTTON_ACTIVE_FG_COLOR, -1, offsetof(TkButton, activeFg), TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0}, + DEF_BUTTON_ANCHOR, -1, offsetof(TkButton, anchor), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), + DEF_BUTTON_BG_COLOR, -1, offsetof(TkButton, normalBorder), 0, DEF_BUTTON_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", - DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), + DEF_BUTTON_BITMAP, -1, offsetof(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr), - Tk_Offset(TkButton, borderWidth), 0, 0, 0}, + tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr), + offsetof(TkButton, borderWidth), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0, + DEF_BUTTON_COMPOUND, -1, offsetof(TkButton, compound), 0, compoundStrings, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor), + DEF_BUTTON_CURSOR, -1, offsetof(TkButton, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, - -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, + -1, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, + DEF_BUTTON_FONT, -1, offsetof(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0}, + DEF_BUTTON_FG, -1, offsetof(TkButton, normalFg), 0, 0, 0}, {TK_OPTION_STRING, "-height", "height", "Height", - DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0}, + DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), -1, 0, 0, 0}, {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkButton, highlightBorder), 0, + -1, offsetof(TkButton, highlightBorder), 0, (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr), + DEF_BUTTON_HIGHLIGHT, -1, offsetof(TkButton, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", tkDefLabelHighlightWidth, - Tk_Offset(TkButton, highlightWidthPtr), - Tk_Offset(TkButton, highlightWidth), 0, 0, 0}, + offsetof(TkButton, highlightWidthPtr), + offsetof(TkButton, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-image", "image", "Image", - DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1, + DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0}, + DEF_BUTTON_JUSTIFY, -1, offsetof(TkButton, justify), 0, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - tkDefLabelPadx, Tk_Offset(TkButton, padXPtr), - Tk_Offset(TkButton, padX), 0, 0, 0}, + tkDefLabelPadx, offsetof(TkButton, padXPtr), + offsetof(TkButton, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - tkDefLabelPady, Tk_Offset(TkButton, padYPtr), - Tk_Offset(TkButton, padY), 0, 0, 0}, + tkDefLabelPady, offsetof(TkButton, padYPtr), + offsetof(TkButton, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0}, + DEF_LABCHKRAD_RELIEF, -1, offsetof(TkButton, relief), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state), + DEF_BUTTON_STATE, -1, offsetof(TkButton, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1, + DEF_LABEL_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0}, + DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1, + DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0}, + DEF_BUTTON_UNDERLINE, -1, offsetof(TkButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", - DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0}, + DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), -1, 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", - DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), - Tk_Offset(TkButton, wrapLength), 0, 0, 0}, + DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr), + offsetof(TkButton, wrapLength), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; static const Tk_OptionSpec buttonOptionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder), + DEF_BUTTON_ACTIVE_BG_COLOR, -1, offsetof(TkButton, activeBorder), 0, DEF_BUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", - DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg), + DEF_BUTTON_ACTIVE_FG_COLOR, -1, offsetof(TkButton, activeFg), TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0}, + DEF_BUTTON_ANCHOR, -1, offsetof(TkButton, anchor), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), + DEF_BUTTON_BG_COLOR, -1, offsetof(TkButton, normalBorder), 0, DEF_BUTTON_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", - DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), + DEF_BUTTON_BITMAP, -1, offsetof(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr), - Tk_Offset(TkButton, borderWidth), 0, 0, 0}, + tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr), + offsetof(TkButton, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", - DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1, + DEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0, + DEF_BUTTON_COMPOUND, -1, offsetof(TkButton, compound), 0, compoundStrings, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor), + DEF_BUTTON_CURSOR, -1, offsetof(TkButton, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-default", "default", "Default", - DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState), + DEF_BUTTON_DEFAULT, -1, offsetof(TkButton, defaultState), 0, defaultStrings, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, - -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, + -1, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, + DEF_BUTTON_FONT, -1, offsetof(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0}, + DEF_BUTTON_FG, -1, offsetof(TkButton, normalFg), 0, 0, 0}, {TK_OPTION_STRING, "-height", "height", "Height", - DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0}, + DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), -1, 0, 0, 0}, {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkButton, highlightBorder), 0, + -1, offsetof(TkButton, highlightBorder), 0, (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr), + DEF_BUTTON_HIGHLIGHT, -1, offsetof(TkButton, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", tkDefButtonHighlightWidth, - Tk_Offset(TkButton, highlightWidthPtr), - Tk_Offset(TkButton, highlightWidth), 0, 0, 0}, + offsetof(TkButton, highlightWidthPtr), + offsetof(TkButton, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-image", "image", "Image", - DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1, + DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0}, + DEF_BUTTON_JUSTIFY, -1, offsetof(TkButton, justify), 0, 0, 0}, {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief", - DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief), + DEF_BUTTON_OVER_RELIEF, -1, offsetof(TkButton, overRelief), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - tkDefButtonPadx, Tk_Offset(TkButton, padXPtr), - Tk_Offset(TkButton, padX), 0, 0, 0}, + tkDefButtonPadx, offsetof(TkButton, padXPtr), + offsetof(TkButton, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - tkDefButtonPady, Tk_Offset(TkButton, padYPtr), - Tk_Offset(TkButton, padY), 0, 0, 0}, + tkDefButtonPady, offsetof(TkButton, padYPtr), + offsetof(TkButton, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief), + DEF_BUTTON_RELIEF, -1, offsetof(TkButton, relief), 0, 0, 0}, {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay", - DEF_BUTTON_REPEAT_DELAY, -1, Tk_Offset(TkButton, repeatDelay), + DEF_BUTTON_REPEAT_DELAY, -1, offsetof(TkButton, repeatDelay), 0, 0, 0}, {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval", - DEF_BUTTON_REPEAT_INTERVAL, -1, Tk_Offset(TkButton, repeatInterval), + DEF_BUTTON_REPEAT_INTERVAL, -1, offsetof(TkButton, repeatInterval), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state), + DEF_BUTTON_STATE, -1, offsetof(TkButton, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1, + DEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0}, + DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1, + DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0}, + DEF_BUTTON_UNDERLINE, -1, offsetof(TkButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", - DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0}, + DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), -1, 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", - DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), - Tk_Offset(TkButton, wrapLength), 0, 0, 0}, + DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr), + offsetof(TkButton, wrapLength), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; static const Tk_OptionSpec checkbuttonOptionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder), + DEF_BUTTON_ACTIVE_BG_COLOR, -1, offsetof(TkButton, activeBorder), 0, DEF_BUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", - DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg), + DEF_CHKRAD_ACTIVE_FG_COLOR, -1, offsetof(TkButton, activeFg), TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0}, + DEF_BUTTON_ANCHOR, -1, offsetof(TkButton, anchor), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), + DEF_BUTTON_BG_COLOR, -1, offsetof(TkButton, normalBorder), 0, DEF_BUTTON_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", - DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), + DEF_BUTTON_BITMAP, -1, offsetof(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr), - Tk_Offset(TkButton, borderWidth), 0, 0, 0}, + tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr), + offsetof(TkButton, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", - DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1, + DEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0, + DEF_BUTTON_COMPOUND, -1, offsetof(TkButton, compound), 0, compoundStrings, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor), + DEF_BUTTON_CURSOR, -1, offsetof(TkButton, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, - -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, + -1, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, + DEF_BUTTON_FONT, -1, offsetof(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0}, + DEF_CHKRAD_FG, -1, offsetof(TkButton, normalFg), 0, 0, 0}, {TK_OPTION_STRING, "-height", "height", "Height", - DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0}, + DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), -1, 0, 0, 0}, {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkButton, highlightBorder), 0, + -1, offsetof(TkButton, highlightBorder), 0, (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr), + DEF_BUTTON_HIGHLIGHT, -1, offsetof(TkButton, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", tkDefButtonHighlightWidth, - Tk_Offset(TkButton, highlightWidthPtr), - Tk_Offset(TkButton, highlightWidth), 0, 0, 0}, + offsetof(TkButton, highlightWidthPtr), + offsetof(TkButton, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-image", "image", "Image", - DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1, + DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn", - DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0}, + DEF_BUTTON_INDICATOR, -1, offsetof(TkButton, indicatorOn), 0, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0}, + DEF_BUTTON_JUSTIFY, -1, offsetof(TkButton, justify), 0, 0, 0}, {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0}, + DEF_BUTTON_RELIEF, -1, offsetof(TkButton, offRelief), 0, 0, 0}, {TK_OPTION_STRING, "-offvalue", "offValue", "Value", - DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0}, + DEF_BUTTON_OFF_VALUE, offsetof(TkButton, offValuePtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-onvalue", "onValue", "Value", - DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0}, + DEF_BUTTON_ON_VALUE, offsetof(TkButton, onValuePtr), -1, 0, 0, 0}, {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief", - DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief), + DEF_BUTTON_OVER_RELIEF, -1, offsetof(TkButton, overRelief), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - tkDefLabelPadx, Tk_Offset(TkButton, padXPtr), - Tk_Offset(TkButton, padX), 0, 0, 0}, + tkDefLabelPadx, offsetof(TkButton, padXPtr), + offsetof(TkButton, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - tkDefLabelPady, Tk_Offset(TkButton, padYPtr), - Tk_Offset(TkButton, padY), 0, 0, 0}, + tkDefLabelPady, offsetof(TkButton, padYPtr), + offsetof(TkButton, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0}, + DEF_LABCHKRAD_RELIEF, -1, offsetof(TkButton, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background", - DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder), + DEF_BUTTON_SELECT_COLOR, -1, offsetof(TkButton, selectBorder), TK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0}, {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage", - DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1, + DEF_BUTTON_SELECT_IMAGE, offsetof(TkButton, selectImagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state), + DEF_BUTTON_STATE, -1, offsetof(TkButton, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1, + DEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0}, + DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1, + DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage", - DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1, + DEF_BUTTON_IMAGE, offsetof(TkButton, tristateImagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue", - DEF_BUTTON_TRISTATE_VALUE, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0}, + DEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), -1, 0, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0}, + DEF_BUTTON_UNDERLINE, -1, offsetof(TkButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", - DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1, + DEF_CHECKBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", - DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0}, + DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), -1, 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", - DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), - Tk_Offset(TkButton, wrapLength), 0, 0, 0}, + DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr), + offsetof(TkButton, wrapLength), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; static const Tk_OptionSpec radiobuttonOptionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder), + DEF_BUTTON_ACTIVE_BG_COLOR, -1, offsetof(TkButton, activeBorder), 0, DEF_BUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", - DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg), + DEF_CHKRAD_ACTIVE_FG_COLOR, -1, offsetof(TkButton, activeFg), TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0}, + DEF_BUTTON_ANCHOR, -1, offsetof(TkButton, anchor), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), + DEF_BUTTON_BG_COLOR, -1, offsetof(TkButton, normalBorder), 0, DEF_BUTTON_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", - DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), + DEF_BUTTON_BITMAP, -1, offsetof(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr), - Tk_Offset(TkButton, borderWidth), 0, 0, 0}, + tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr), + offsetof(TkButton, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", - DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1, + DEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0, + DEF_BUTTON_COMPOUND, -1, offsetof(TkButton, compound), 0, compoundStrings, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor), + DEF_BUTTON_CURSOR, -1, offsetof(TkButton, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, - -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, + -1, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, + DEF_BUTTON_FONT, -1, offsetof(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0}, + DEF_CHKRAD_FG, -1, offsetof(TkButton, normalFg), 0, 0, 0}, {TK_OPTION_STRING, "-height", "height", "Height", - DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0}, + DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), -1, 0, 0, 0}, {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkButton, highlightBorder), 0, + -1, offsetof(TkButton, highlightBorder), 0, (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr), + DEF_BUTTON_HIGHLIGHT, -1, offsetof(TkButton, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", tkDefButtonHighlightWidth, - Tk_Offset(TkButton, highlightWidthPtr), - Tk_Offset(TkButton, highlightWidth), 0, 0, 0}, + offsetof(TkButton, highlightWidthPtr), + offsetof(TkButton, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-image", "image", "Image", - DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1, + DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn", - DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), + DEF_BUTTON_INDICATOR, -1, offsetof(TkButton, indicatorOn), 0, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0}, + DEF_BUTTON_JUSTIFY, -1, offsetof(TkButton, justify), 0, 0, 0}, {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0}, + DEF_BUTTON_RELIEF, -1, offsetof(TkButton, offRelief), 0, 0, 0}, {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief", - DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief), + DEF_BUTTON_OVER_RELIEF, -1, offsetof(TkButton, overRelief), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - tkDefLabelPadx, Tk_Offset(TkButton, padXPtr), - Tk_Offset(TkButton, padX), 0, 0, 0}, + tkDefLabelPadx, offsetof(TkButton, padXPtr), + offsetof(TkButton, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - tkDefLabelPady, Tk_Offset(TkButton, padYPtr), - Tk_Offset(TkButton, padY), 0, 0, 0}, + tkDefLabelPady, offsetof(TkButton, padYPtr), + offsetof(TkButton, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0}, + DEF_LABCHKRAD_RELIEF, -1, offsetof(TkButton, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background", - DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder), + DEF_BUTTON_SELECT_COLOR, -1, offsetof(TkButton, selectBorder), TK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0}, {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage", - DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1, + DEF_BUTTON_SELECT_IMAGE, offsetof(TkButton, selectImagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state), + DEF_BUTTON_STATE, -1, offsetof(TkButton, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1, + DEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0}, + DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1, + DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage", - DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1, + DEF_BUTTON_IMAGE, offsetof(TkButton, tristateImagePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue", - DEF_BUTTON_TRISTATE_VALUE, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0}, + DEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), -1, 0, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0}, + DEF_BUTTON_UNDERLINE, -1, offsetof(TkButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-value", "value", "Value", - DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0}, + DEF_BUTTON_VALUE, offsetof(TkButton, onValuePtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", - DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1, + DEF_RADIOBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), -1, 0, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", - DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0}, + DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), -1, 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", - DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), - Tk_Offset(TkButton, wrapLength), 0, 0, 0}, + DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr), + offsetof(TkButton, wrapLength), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* * The following table maps from one of the type values defined in tkButton.h, @@ -747,11 +747,11 @@ Tk_CreateEventHandler(butPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, ButtonEventProc, butPtr); - if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin) + if (Tk_InitOptions(interp, butPtr, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(butPtr->tkwin); return TCL_ERROR; } if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) { @@ -808,21 +808,21 @@ case COMMAND_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "cget option"); goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) butPtr, + objPtr = Tk_GetOptionValue(interp, butPtr, butPtr->optionTable, objv[2], butPtr->tkwin); if (objPtr == NULL) { goto error; } Tcl_SetObjResult(interp, objPtr); break; case COMMAND_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) butPtr, + objPtr = Tk_GetOptionInfo(interp, butPtr, butPtr->optionTable, (objc == 3) ? objv[2] : NULL, butPtr->tkwin); if (objPtr == NULL) { goto error; } @@ -1072,11 +1072,11 @@ if (!error) { /* * First pass: set options to new values. */ - if (Tk_SetOptions(interp, (char *) butPtr, + if (Tk_SetOptions(interp, butPtr, butPtr->optionTable, objc, objv, butPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -1173,11 +1173,11 @@ * If a radiobutton has the empty string as value it should be * selected. */ if ((butPtr->type == TYPE_RADIO_BUTTON) && - (*Tcl_GetString(butPtr->onValuePtr) == 0)) { + (*Tcl_GetString(butPtr->onValuePtr) == '\0')) { butPtr->flags |= SELECTED; } } } @@ -1614,31 +1614,38 @@ { register TkButton *butPtr = clientData; const char *value; Tcl_Obj *valuePtr; - /* - * See ticket [5d991b82]. - */ - - if (butPtr->selVarNamePtr == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - ButtonVarProc, clientData); - } - return NULL; - } - /* * If the variable is being unset, then just re-establish the trace unless * the whole interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { butPtr->flags &= ~(SELECTED | TRISTATED); - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp)) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + Tcl_GetString(butPtr->selVarNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ButtonVarProc, probe); + if (probe == (ClientData)butPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * selVarNamePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + goto redisplay; + } Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr), NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, clientData); } goto redisplay; @@ -1709,41 +1716,55 @@ /* ARGSUSED */ static char * ButtonTextVarProc( ClientData clientData, /* Information about button. */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Name of variable. */ - const char *name2, /* Second part of variable name. */ + const char *name1, /* Not used. */ + const char *name2, /* Not used. */ int flags) /* Information about what happened. */ { TkButton *butPtr = clientData; Tcl_Obj *valuePtr; if (butPtr->flags & BUTTON_DELETED) { return NULL; } - /* - * See ticket [5d991b82]. - */ - - if (butPtr->textVarNamePtr == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - ButtonTextVarProc, clientData); - } - return NULL; - } - /* * If the variable is unset, then immediately recreate it unless the whole * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && butPtr->textVarNamePtr != NULL) { + + /* + * An unset trace on some variable brought us here, but is it + * the variable we have stored in butPtr->textVarNamePtr ? + */ + + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + Tcl_GetString(butPtr->textVarNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ButtonTextVarProc, probe); + if (probe == (ClientData)butPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarNamePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former textvariable must be, and we should ignore it. + */ + return NULL; + } + Tcl_ObjSetVar2(interp, butPtr->textVarNamePtr, NULL, butPtr->textPtr, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr), NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, clientData); Index: generic/tkCanvArc.c ================================================================== --- generic/tkCanvArc.c +++ generic/tkCanvArc.c @@ -11,10 +11,12 @@ */ #include "tkInt.h" #include "tkCanvas.h" +#include "float.h" + /* * The structure below defines the record for each arc item. */ typedef enum { @@ -60,10 +62,16 @@ GC fillGC; /* Graphics context for filling item. */ double center1[2]; /* Coordinates of center of arc outline at * start (see ComputeArcOutline). */ double center2[2]; /* Coordinates of center of arc outline at * start+extent (see ComputeArcOutline). */ + double height; /* Distance from the arc's chord to its + * mid-point. */ + double startPoint[2]; /* Start point of arc used when specifying + * height. */ + double endPoint[2]; /* End point of arc used when specifying + * height. */ } ArcItem; /* * The definitions below define the sizes of the polygons used to display * outline information for various styles of arcs: @@ -102,69 +110,71 @@ TkPixelParseProc, TkPixelPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.activeDash), + NULL, offsetof(ArcItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-activefill", NULL, NULL, - NULL, Tk_Offset(ArcItem, activeFillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, activeFillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, - NULL, Tk_Offset(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, - "0.0", Tk_Offset(ArcItem, outline.activeWidth), + "0.0", offsetof(ArcItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.dash), + NULL, offsetof(ArcItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, - "0", Tk_Offset(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0", offsetof(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.disabledDash), + NULL, offsetof(ArcItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, - NULL, Tk_Offset(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, - NULL, Tk_Offset(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL, - "0.0", Tk_Offset(ArcItem, outline.disabledWidth), + "0.0", offsetof(ArcItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_DOUBLE, "-extent", NULL, NULL, - "90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "90", offsetof(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_COLOR, "-fill", NULL, NULL, - NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, fillColor), TK_CONFIG_NULL_OK, NULL}, + {TK_CONFIG_DOUBLE, "-height", NULL, NULL, + 0, offsetof(ArcItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, - "0,0", Tk_Offset(ArcItem, tsoffset), + "0,0", offsetof(ArcItem, tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_COLOR, "-outline", NULL, NULL, - "black", Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL}, + "black", offsetof(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL, - "0,0", Tk_Offset(ArcItem, outline.tsoffset), + "0,0", offsetof(ArcItem, outline.tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL, - NULL, Tk_Offset(ArcItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_DOUBLE, "-start", NULL, NULL, - "0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0", offsetof(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, - NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ArcItem, fillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-style", NULL, NULL, - NULL, Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT, + NULL, offsetof(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT, &styleOption}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_CUSTOM, "-width", NULL, NULL, - "1.0", Tk_Offset(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, + "1.0", offsetof(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* @@ -173,10 +183,11 @@ static void ComputeArcBbox(Tk_Canvas canvas, ArcItem *arcPtr); static int ConfigureArc(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[], int flags); +static void ComputeArcParametersFromHeight(ArcItem *arcPtr); static int CreateArc(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[]); static void DeleteArc(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display); @@ -203,10 +214,12 @@ double y, double rx, double ry, double start, double extent); static int VertLineToArc(double x, double y1, double y2, double rx, double ry, double start, double extent); +static void RotateArc(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); /* * The structures below defines the arc item types by means of functions that * can be invoked by generic item code. */ @@ -230,11 +243,12 @@ NULL, /* icursorProc */ NULL, /* selectionProc */ NULL, /* insertProc */ NULL, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateArc, /* rotateProc */ + 0, NULL, NULL }; /* *-------------------------------------------------------------- * @@ -289,10 +303,11 @@ arcPtr->fillStipple = None; arcPtr->activeFillStipple = None; arcPtr->disabledFillStipple = None; arcPtr->style = PIESLICE_STYLE; arcPtr->fillGC = NULL; + arcPtr->height = 0; /* * Process the arguments to fill in the item record. */ @@ -349,12 +364,12 @@ objs[0] = Tcl_NewDoubleObj(arcPtr->bbox[0]); objs[1] = Tcl_NewDoubleObj(arcPtr->bbox[1]); objs[2] = Tcl_NewDoubleObj(arcPtr->bbox[2]); objs[3] = Tcl_NewDoubleObj(arcPtr->bbox[3]); Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs)); - } else if ((objc == 1)||(objc == 4)) { - if (objc==1) { + } else if ((objc == 1) || (objc == 4)) { + if (objc == 1) { if (Tcl_ListObjGetElements(interp, objv[0], &objc, (Tcl_Obj ***) &objv) != TCL_OK) { return TCL_ERROR; } else if (objc != 4) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -372,10 +387,21 @@ &arcPtr->bbox[2]) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3], &arcPtr->bbox[3]) != TCL_OK)) { return TCL_ERROR; } + + /* + * Store bbox as start and end points so they can be used if either + * radius or height is specified. + */ + + arcPtr->startPoint[0] = arcPtr->bbox[0]; + arcPtr->startPoint[1] = arcPtr->bbox[1]; + arcPtr->endPoint[0] = arcPtr->bbox[2]; + arcPtr->endPoint[1] = arcPtr->bbox[3]; + ComputeArcBbox(canvas, arcPtr); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # coordinates: expected 0 or 4, got %d", objc)); Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "ARC", NULL); @@ -445,10 +471,26 @@ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; } else { itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; } + /* + * Override the start and extent if the height is given. + */ + + ComputeArcParametersFromHeight(arcPtr); + + ComputeArcBbox(canvas, arcPtr); + + i = (int) (arcPtr->start/360.0); + arcPtr->start -= i*360.0; + if (arcPtr->start < 0) { + arcPtr->start += 360.0; + } + i = (int) (arcPtr->extent/360.0); + arcPtr->extent -= i*360.0; + tsoffset = &arcPtr->outline.tsoffset; flags = tsoffset->flags; if (flags & TK_OFFSET_LEFT) { tsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5); } else if (flags & TK_OFFSET_CENTER) { @@ -462,18 +504,10 @@ tsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2); } else if (flags & TK_OFFSET_BOTTOM) { tsoffset->yoffset = (int) (arcPtr->bbox[2] + 0.5); } - i = (int) (arcPtr->start/360.0); - arcPtr->start -= i*360.0; - if (arcPtr->start < 0) { - arcPtr->start += 360.0; - } - i = (int) (arcPtr->extent/360.0); - arcPtr->extent -= i*360.0; - mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(arcPtr->outline)); if (mask) { gcValues.cap_style = CapButt; mask |= GCCapStyle; newGC = Tk_GetGC(tkwin, mask, &gcValues); @@ -507,11 +541,11 @@ color = arcPtr->disabledFillColor; } if (arcPtr->disabledFillStipple!=None) { stipple = arcPtr->disabledFillStipple; } - } + } if (arcPtr->style == ARC_STYLE) { newGC = NULL; } else if (color == NULL) { newGC = NULL; @@ -553,10 +587,107 @@ } ComputeArcBbox(canvas, arcPtr); return TCL_OK; } + +/* + *-------------------------------------------------------------- + * + * ComputeArcParametersFromHeight -- + * + * This function calculates the arc parameters given start-point, + * end-point and height (!= 0). + * + * Results: + * None. + * + * Side effects: + * The height parameter is set to 0 on exit. + * + *-------------------------------------------------------------- + */ + +static void +ComputeArcParametersFromHeight( + ArcItem* arcPtr) +{ + double chordLen, chordDir[2], chordCen[2], arcCen[2], d, radToDeg, radius; + + /* + * Do nothing if no height has been specified. + */ + + if (arcPtr->height == 0) + return; + + /* + * Calculate the chord length, return early if it is too small. + */ + + chordLen = hypot(arcPtr->endPoint[1] - arcPtr->startPoint[1], + arcPtr->startPoint[0] - arcPtr->endPoint[0]); + + if (chordLen < DBL_EPSILON) { + arcPtr->start = arcPtr->extent = arcPtr->height = 0; + return; + } + + chordDir[0] = (arcPtr->endPoint[0] - arcPtr->startPoint[0]) / chordLen; + chordDir[1] = (arcPtr->endPoint[1] - arcPtr->startPoint[1]) / chordLen; + chordCen[0] = (arcPtr->startPoint[0] + arcPtr->endPoint[0]) / 2; + chordCen[1] = (arcPtr->startPoint[1] + arcPtr->endPoint[1]) / 2; + + /* + * Calculate the radius (assumes height != 0). + */ + + radius = (4*pow(arcPtr->height, 2) + pow(chordLen, 2)) + / (8 * arcPtr->height); + + /* + * The arc centre. + */ + + d = radius - arcPtr->height; + arcCen[0] = chordCen[0] - d * chordDir[1]; + arcCen[1] = chordCen[1] + d * chordDir[0]; + + /* + * The arc start and span. Angles are negated because the coordinate + * system is left-handed. + */ + + radToDeg = 45 / atan(1); + arcPtr->start = atan2(arcCen[1] - arcPtr->startPoint[1], + arcPtr->startPoint[0] - arcCen[0]) * radToDeg; + arcPtr->extent = -2 * asin(chordLen / (2 * radius)) * radToDeg; + + /* + * Handle spans > 180. + */ + + if (fabs(2 * arcPtr->height) > chordLen) { + arcPtr->extent = arcPtr->extent > 0 ? (360 - arcPtr->extent) + : -(360 + arcPtr->extent); + } + + /* + * Create the bounding box. + */ + + arcPtr->bbox[0] = arcCen[0] - radius; + arcPtr->bbox[1] = arcCen[1] - radius; + arcPtr->bbox[2] = arcCen[0] + radius; + arcPtr->bbox[3] = arcCen[1] + radius; + + /* + * Set the height to 0 so that itemcget -height returns 0. + */ + + arcPtr->height = 0; +} /* *-------------------------------------------------------------- * * DeleteArc -- @@ -675,11 +806,11 @@ } ComputeArcOutline(canvas,arcPtr); /* - * To compute the bounding box, start with the the bbox formed by the two + * To compute the bounding box, start with the bbox formed by the two * endpoints of the arc. Then add in the center of the arc's oval (if * relevant) and the 3-o'clock, 6-o'clock, 9-o'clock, and 12-o'clock * positions, if they are relevant. */ @@ -1371,10 +1502,64 @@ arcPtr->bbox[0] = originX + scaleX*(arcPtr->bbox[0] - originX); arcPtr->bbox[1] = originY + scaleY*(arcPtr->bbox[1] - originY); arcPtr->bbox[2] = originX + scaleX*(arcPtr->bbox[2] - originX); arcPtr->bbox[3] = originY + scaleY*(arcPtr->bbox[3] - originY); + ComputeArcBbox(canvas, arcPtr); +} + +/* + *-------------------------------------------------------------- + * + * RotateArc -- + * + * This function is called to rotate an arc by a given amount. + * + * Results: + * None. + * + * Side effects: + * The position of the arc is rotated by angleRad radians about (originX, + * originY), and the bounding box is updated in the generic part of the + * item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateArc( + Tk_Canvas canvas, + Tk_Item *itemPtr, + double originX, + double originY, + double angleRad) +{ + ArcItem *arcPtr = (ArcItem *) itemPtr; + double newX, newY, oldX, oldY; + + /* + * Compute the centre of the box, then rotate that about the origin. + */ + + newX = oldX = (arcPtr->bbox[0] + arcPtr->bbox[2]) / 2.0; + newY = oldY = (arcPtr->bbox[1] + arcPtr->bbox[3]) / 2.0; + TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad), + &newX, &newY); + + /* + * Apply the translation to the box. + */ + + arcPtr->bbox[0] += newX - oldX; + arcPtr->bbox[1] += newY - oldY; + arcPtr->bbox[2] += newX - oldX; + arcPtr->bbox[3] += newY - oldY; + + /* + * TODO: update the arc endpoints? + */ + ComputeArcBbox(canvas, arcPtr); } /* *-------------------------------------------------------------- Index: generic/tkCanvBmap.c ================================================================== --- generic/tkCanvBmap.c +++ generic/tkCanvBmap.c @@ -47,34 +47,34 @@ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_COLOR, "-activebackground", NULL, NULL, - NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activebitmap", NULL, NULL, - NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-activeforeground", NULL, NULL, - NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, - "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "center", offsetof(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_COLOR, "-background", NULL, NULL, - NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-bitmap", NULL, NULL, - NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-disabledbackground", NULL, NULL, - NULL, Tk_Offset(BitmapItem, disabledBgColor), + NULL, offsetof(BitmapItem, disabledBgColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledbitmap", NULL, NULL, - NULL, Tk_Offset(BitmapItem, disabledBitmap), + NULL, offsetof(BitmapItem, disabledBitmap), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-disabledforeground", NULL, NULL, - NULL, Tk_Offset(BitmapItem, disabledFgColor), + NULL, offsetof(BitmapItem, disabledFgColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-foreground", NULL, NULL, - "black", Tk_Offset(BitmapItem, fgColor), 0, NULL}, + "black", offsetof(BitmapItem, fgColor), 0, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; @@ -103,10 +103,12 @@ static void DeleteBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display); static void DisplayBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, int x, int y, int width, int height); +static void RotateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void ScaleBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); static void TranslateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -135,11 +137,12 @@ NULL, /* icursorProc */ NULL, /* selectionProc */ NULL, /* insertProc */ NULL, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateBitmap, /* rotateProc */ + 0, NULL, NULL }; /* *-------------------------------------------------------------- * @@ -784,10 +787,43 @@ bmapPtr->x = originX + scaleX*(bmapPtr->x - originX); bmapPtr->y = originY + scaleY*(bmapPtr->y - originY); ComputeBitmapBbox(canvas, bmapPtr); } + +/* + *-------------------------------------------------------------- + * + * RotateBitmap -- + * + * This function is called to rotate a bitmap's origin by a given amount. + * + * Results: + * None. + * + * Side effects: + * The position of the bitmap is rotated by angleRad radians about + * (originX, originY), and the bounding box is updated in the generic + * part of the item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateBitmap( + Tk_Canvas canvas, + Tk_Item *itemPtr, + double originX, + double originY, + double angleRad) +{ + BitmapItem *bmapPtr = (BitmapItem *) itemPtr; + + TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad), + &bmapPtr->x, &bmapPtr->y); + ComputeBitmapBbox(canvas, bmapPtr); +} /* *-------------------------------------------------------------- * * TranslateBitmap -- Index: generic/tkCanvImg.c ================================================================== --- generic/tkCanvImg.c +++ generic/tkCanvImg.c @@ -50,19 +50,19 @@ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_STRING, "-activeimage", NULL, NULL, - NULL, Tk_Offset(ImageItem, activeImageString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ImageItem, activeImageString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, - "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "center", offsetof(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_STRING, "-disabledimage", NULL, NULL, - NULL, Tk_Offset(ImageItem, disabledImageString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ImageItem, disabledImageString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_STRING, "-image", NULL, NULL, - NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(ImageItem, imageString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; @@ -92,10 +92,12 @@ static void DeleteImage(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display); static void DisplayImage(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, int x, int y, int width, int height); +static void RotateImage(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void ScaleImage(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); static void TranslateImage(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -124,11 +126,12 @@ NULL, /* icursorProc */ NULL, /* selectionProc */ NULL, /* insertProc */ NULL, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateImage, /* rotateProc */ + 0, NULL, NULL }; /* *-------------------------------------------------------------- * @@ -755,10 +758,44 @@ } return Tk_PostscriptImage(image, interp, canvasWin, ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass); } + +/* + *-------------------------------------------------------------- + * + * RotateImage -- + * + * This function is called to rotate an image's origin by a given amount. + * This does *not* rotate the contents of the image. + * + * Results: + * None. + * + * Side effects: + * The position of the image anchor is rotated by angleRad radians about + * (originX, originY), and the bounding box is updated in the generic + * part of the item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateImage( + Tk_Canvas canvas, + Tk_Item *itemPtr, + double originX, + double originY, + double angleRad) +{ + ImageItem *imgPtr = (ImageItem *) itemPtr; + + TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad), + &imgPtr->x, &imgPtr->y); + ComputeImageBbox(canvas, imgPtr); +} /* *-------------------------------------------------------------- * * ScaleImage -- Index: generic/tkCanvLine.c ================================================================== --- generic/tkCanvLine.c +++ generic/tkCanvLine.c @@ -115,10 +115,12 @@ Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *recordPtr, int offset); static const char * PrintArrowShape(ClientData clientData, Tk_Window tkwin, char *recordPtr, int offset, Tcl_FreeProc **freeProcPtr); +static void RotateLine(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void ScaleLine(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); static void TranslateLine(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -155,62 +157,62 @@ TkPixelParseProc, TkPixelPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.activeDash), + NULL, offsetof(LineItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-activefill", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(LineItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, - "0.0", Tk_Offset(LineItem, outline.activeWidth), + "0.0", offsetof(LineItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_CUSTOM, "-arrow", NULL, NULL, - "none", Tk_Offset(LineItem, arrow), + "none", offsetof(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT, &arrowOption}, {TK_CONFIG_CUSTOM, "-arrowshape", NULL, NULL, - "8 10 3", Tk_Offset(LineItem, arrowShapeA), + "8 10 3", offsetof(LineItem, arrowShapeA), TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption}, {TK_CONFIG_CAP_STYLE, "-capstyle", NULL, NULL, - "butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "butt", offsetof(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_COLOR, "-fill", NULL, NULL, - "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL}, + "black", offsetof(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.dash), + NULL, offsetof(LineItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, - "0", Tk_Offset(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0", offsetof(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.disabledDash), + NULL, offsetof(LineItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL, - "0.0", Tk_Offset(LineItem, outline.disabledWidth), + "0.0", offsetof(LineItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL, - "round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "round", offsetof(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, - "0,0", Tk_Offset(LineItem, outline.tsoffset), + "0,0", offsetof(LineItem, outline.tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL, - "0", Tk_Offset(LineItem, smooth), + "0", offsetof(LineItem, smooth), TK_CONFIG_DONT_SET_DEFAULT, &smoothOption}, {TK_CONFIG_INT, "-splinesteps", NULL, NULL, - "12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "12", offsetof(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, - NULL, Tk_Offset(LineItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(LineItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_CUSTOM, "-width", NULL, NULL, - "1.0", Tk_Offset(LineItem, outline.width), + "1.0", offsetof(LineItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* @@ -237,11 +239,12 @@ NULL, /* icursorProc */ NULL, /* selectionProc */ LineInsert, /* insertProc */ LineDeleteCoords, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateLine, /* rotateProc */ + 0, NULL, NULL }; /* * The definition below determines how large are static arrays used to hold * spline points (splines larger than this have to have their arrays @@ -1854,10 +1857,60 @@ } /* *-------------------------------------------------------------- * + * RotateLine -- + * + * This function is called to rotate a line by a given amount about a + * point. + * + * Results: + * None. + * + * Side effects: + * The position of the line is rotated by angleRad about (originX, + * originY), and the bounding box is updated in the generic part of the + * item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateLine( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double originX, double originY, + double angleRad) /* Amount by which item is to be rotated. */ +{ + LineItem *linePtr = (LineItem *) itemPtr; + double *coordPtr; + int i; + double s = sin(angleRad), c = cos(angleRad); + + for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints; + i++, coordPtr += 2) { + TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]); + } + if (linePtr->firstArrowPtr != NULL) { + for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; + i++, coordPtr += 2) { + TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]); + } + } + if (linePtr->lastArrowPtr != NULL) { + for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; + i++, coordPtr += 2) { + TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]); + } + } + ComputeLineBbox(canvas, linePtr); +} + +/* + *-------------------------------------------------------------- + * * ParseArrowShape -- * * This function is called back during option parsing to parse arrow * shape information. * @@ -1887,11 +1940,11 @@ LineItem *linePtr = (LineItem *) recordPtr; double a, b, c; int argc; const char **argv = NULL; - if (offset != Tk_Offset(LineItem, arrowShapeA)) { + if ((size_t)offset != offsetof(LineItem, arrowShapeA)) { Tcl_Panic("ParseArrowShape received bogus offset"); } if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) { goto syntaxError; Index: generic/tkCanvPoly.c ================================================================== --- generic/tkCanvPoly.c +++ generic/tkCanvPoly.c @@ -74,73 +74,73 @@ TkPixelParseProc, TkPixelPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.activeDash), + NULL, offsetof(PolygonItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-activefill", NULL, NULL, - NULL, Tk_Offset(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.activeStipple), + NULL, offsetof(PolygonItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, - NULL, Tk_Offset(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, - "0.0", Tk_Offset(PolygonItem, outline.activeWidth), + "0.0", offsetof(PolygonItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.dash), + NULL, offsetof(PolygonItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, - "0", Tk_Offset(PolygonItem, outline.offset), + "0", offsetof(PolygonItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.disabledDash), + NULL, offsetof(PolygonItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, - NULL, Tk_Offset(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.disabledColor), + NULL, offsetof(PolygonItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.disabledStipple), + NULL, offsetof(PolygonItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, - NULL, Tk_Offset(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL, - "0.0", Tk_Offset(PolygonItem, outline.disabledWidth), + "0.0", offsetof(PolygonItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_COLOR, "-fill", NULL, NULL, - "black", Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL}, + "black", offsetof(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL, - "round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "round", offsetof(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, - "0,0", Tk_Offset(PolygonItem, tsoffset), + "0,0", offsetof(PolygonItem, tsoffset), TK_CONFIG_NULL_OK, &offsetOption}, {TK_CONFIG_COLOR, "-outline", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.color), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, outline.color), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL, - "0,0", Tk_Offset(PolygonItem, outline.tsoffset), + "0,0", offsetof(PolygonItem, outline.tsoffset), TK_CONFIG_NULL_OK, &offsetOption}, {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL, - NULL, Tk_Offset(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL, - "0", Tk_Offset(PolygonItem, smooth), + "0", offsetof(PolygonItem, smooth), TK_CONFIG_DONT_SET_DEFAULT, &smoothOption}, {TK_CONFIG_INT, "-splinesteps", NULL, NULL, - "12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "12", offsetof(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, - NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PolygonItem, fillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_CUSTOM, "-width", NULL, NULL, - "1.0", Tk_Offset(PolygonItem, outline.width), + "1.0", offsetof(PolygonItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* @@ -174,10 +174,12 @@ Tk_Item *itemPtr, double *rectPtr); static double PolygonToPoint(Tk_Canvas canvas, Tk_Item *itemPtr, double *pointPtr); static int PolygonToPostscript(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void RotatePolygon(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void ScalePolygon(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); static void TranslatePolygon(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -200,17 +202,18 @@ PolygonToPoint, /* pointProc */ PolygonToArea, /* areaProc */ PolygonToPostscript, /* postscriptProc */ ScalePolygon, /* scaleProc */ TranslatePolygon, /* translateProc */ - GetPolygonIndex, /* indexProc */ + GetPolygonIndex, /* indexProc */ NULL, /* icursorProc */ NULL, /* selectionProc */ - PolygonInsert, /* insertProc */ + PolygonInsert, /* insertProc */ PolygonDeleteCoords, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotatePolygon, /* rotateProc */ + 0, NULL, NULL }; /* * The definition below determines how large are static arrays used to hold * spline points (splines larger than this have to have their arrays @@ -516,11 +519,11 @@ #ifdef MAC_OSX_TK /* * Mac OS X CG drawing needs access to the outline linewidth * even for fills (as linewidth controls antialiasing). */ - gcValues.line_width = polyPtr->outline.gc != None ? + gcValues.line_width = polyPtr->outline.gc != NULL ? polyPtr->outline.gc->line_width : 0; mask |= GCLineWidth; #endif newGC = Tk_GetGC(tkwin, mask, &gcValues); } @@ -1732,10 +1735,48 @@ badIndex: Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string)); Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "POLY", NULL); return TCL_ERROR; } + +/* + *-------------------------------------------------------------- + * + * RotatePolygon -- + * + * This function is called to rotate a polygon by a given amount about a + * point. + * + * Results: + * None. + * + * Side effects: + * The position of the polygon is rotated by angleRad about (originX, + * originY), and the bounding box is updated in the generic part of the + * item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotatePolygon( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double originX, double originY, + double angleRad) /* Amount by which item is to be rotated. */ +{ + PolygonItem *polyPtr = (PolygonItem *) itemPtr; + double *coordPtr; + int i; + double s = sin(angleRad), c = cos(angleRad); + + for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints; + i++, coordPtr += 2) { + TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]); + } + ComputePolygonBbox(canvas, polyPtr); +} /* *-------------------------------------------------------------- * * TranslatePolygon -- Index: generic/tkCanvPs.c ================================================================== --- generic/tkCanvPs.c +++ generic/tkCanvPs.c @@ -92,41 +92,41 @@ * canvas "postscript" command and fill in TkPostscriptInfo structures. */ static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_STRING, "-colormap", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, colorVar), 0, NULL}, + "", offsetof(TkPostscriptInfo, colorVar), 0, NULL}, {TK_CONFIG_STRING, "-colormode", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, colorMode), 0, NULL}, + "", offsetof(TkPostscriptInfo, colorMode), 0, NULL}, {TK_CONFIG_STRING, "-file", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, fileName), 0, NULL}, + "", offsetof(TkPostscriptInfo, fileName), 0, NULL}, {TK_CONFIG_STRING, "-channel", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, channelName), 0, NULL}, + "", offsetof(TkPostscriptInfo, channelName), 0, NULL}, {TK_CONFIG_STRING, "-fontmap", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, fontVar), 0, NULL}, + "", offsetof(TkPostscriptInfo, fontVar), 0, NULL}, {TK_CONFIG_PIXELS, "-height", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, height), 0, NULL}, + "", offsetof(TkPostscriptInfo, height), 0, NULL}, {TK_CONFIG_ANCHOR, "-pageanchor", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, pageAnchor), 0, NULL}, + "", offsetof(TkPostscriptInfo, pageAnchor), 0, NULL}, {TK_CONFIG_STRING, "-pageheight", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, pageHeightString), 0, NULL}, + "", offsetof(TkPostscriptInfo, pageHeightString), 0, NULL}, {TK_CONFIG_STRING, "-pagewidth", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, pageWidthString), 0, NULL}, + "", offsetof(TkPostscriptInfo, pageWidthString), 0, NULL}, {TK_CONFIG_STRING, "-pagex", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, pageXString), 0, NULL}, + "", offsetof(TkPostscriptInfo, pageXString), 0, NULL}, {TK_CONFIG_STRING, "-pagey", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, pageYString), 0, NULL}, + "", offsetof(TkPostscriptInfo, pageYString), 0, NULL}, {TK_CONFIG_BOOLEAN, "-prolog", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, prolog), 0, NULL}, + "", offsetof(TkPostscriptInfo, prolog), 0, NULL}, {TK_CONFIG_BOOLEAN, "-rotate", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, rotate), 0, NULL}, + "", offsetof(TkPostscriptInfo, rotate), 0, NULL}, {TK_CONFIG_PIXELS, "-width", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, width), 0, NULL}, + "", offsetof(TkPostscriptInfo, width), 0, NULL}, {TK_CONFIG_PIXELS, "-x", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, x), 0, NULL}, + "", offsetof(TkPostscriptInfo, x), 0, NULL}, {TK_CONFIG_PIXELS, "-y", NULL, NULL, - "", Tk_Offset(TkPostscriptInfo, y), 0, NULL}, + "", offsetof(TkPostscriptInfo, y), 0, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* * Forward declarations for functions defined later in this file: @@ -379,11 +379,11 @@ * Check that the channel is found in this interpreter and that it is * open for writing. */ psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, &mode); - if (psInfo.chan == (Tcl_Channel) NULL) { + if (psInfo.chan == NULL) { result = TCL_ERROR; goto cleanup; } if (!(mode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -489,11 +489,11 @@ */ Tcl_AppendObjToObj(psObj, preambleObj); if (psInfo.chan != NULL) { - if (Tcl_WriteObj(psInfo.chan, psObj) == -1) { + if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) { channelWriteFailed: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "problem writing postscript data to channel: %s", Tcl_PosixError(interp))); result = TCL_ERROR; @@ -543,11 +543,11 @@ psInfo.x2, Tk_PostscriptY((double)psInfo.y2, (Tk_PostscriptInfo)psInfoPtr), psInfo.x, Tk_PostscriptY((double)psInfo.y2, (Tk_PostscriptInfo)psInfoPtr)); if (psInfo.chan != NULL) { - if (Tcl_WriteObj(psInfo.chan, psObj) == -1) { + if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) { goto channelWriteFailed; } Tcl_DecrRefCount(psObj); psObj = Tcl_NewObj(); } @@ -585,11 +585,11 @@ Tcl_AppendToObj(psObj, "gsave\n", -1); Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); Tcl_AppendToObj(psObj, "grestore\n", -1); if (psInfo.chan != NULL) { - if (Tcl_WriteObj(psInfo.chan, psObj) == -1) { + if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) { goto channelWriteFailed; } Tcl_DecrRefCount(psObj); psObj = Tcl_NewObj(); } @@ -606,11 +606,11 @@ "%%Trailer\n" "end\n" "%%EOF\n", -1); if (psInfo.chan != NULL) { - if (Tcl_WriteObj(psInfo.chan, psObj) == -1) { + if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) { goto channelWriteFailed; } } } Index: generic/tkCanvText.c ================================================================== --- generic/tkCanvText.c +++ generic/tkCanvText.c @@ -93,42 +93,42 @@ TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE) }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_COLOR, "-activefill", NULL, NULL, - NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, - NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(TextItem, activeStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, - "center", Tk_Offset(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "center", offsetof(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_DOUBLE, "-angle", NULL, NULL, - "0.0", Tk_Offset(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0.0", offsetof(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, - NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(TextItem, disabledColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, - NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-fill", NULL, NULL, - "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK, NULL}, + "black", offsetof(TextItem, color), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_FONT, "-font", NULL, NULL, - DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0, NULL}, + DEF_CANVTEXT_FONT, offsetof(TextItem, tkfont), 0, NULL}, {TK_CONFIG_JUSTIFY, "-justify", NULL, NULL, - "left", Tk_Offset(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "left", offsetof(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, - "0,0", Tk_Offset(TextItem, tsoffset), + "0,0", offsetof(TextItem, tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, - NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(TextItem, stipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_STRING, "-text", NULL, NULL, - "", Tk_Offset(TextItem, text), 0, NULL}, + "", offsetof(TextItem, text), 0, NULL}, {TK_CONFIG_INT, "-underline", NULL, NULL, - "-1", Tk_Offset(TextItem, underline), 0, NULL}, + "-1", offsetof(TextItem, underline), 0, NULL}, {TK_CONFIG_PIXELS, "-width", NULL, NULL, - "0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0", offsetof(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* * Prototypes for functions defined in this file: @@ -168,10 +168,12 @@ Tk_Item *itemPtr, double *rectPtr); static double TextToPoint(Tk_Canvas canvas, Tk_Item *itemPtr, double *pointPtr); static int TextToPostscript(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void RotateText(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void TranslateText(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); /* * The structures below defines the rectangle and oval item types by means of @@ -197,11 +199,12 @@ SetTextCursor, /* icursorProc */ GetSelText, /* selectionProc */ TextInsert, /* insertProc */ TextDeleteChars, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateText, /* rotateProc */ + 0, NULL, NULL }; #define ROUND(d) ((int) floor((d) + 0.5)) /* @@ -1004,16 +1007,17 @@ int index, /* Character index before which string is to * be inserted. */ Tcl_Obj *obj) /* New characters to be inserted. */ { TextItem *textPtr = (TextItem *) itemPtr; - int byteIndex, byteCount, charsAdded; + int byteIndex, charsAdded; + TkSizeT byteCount; char *newStr, *text; const char *string; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; - string = Tcl_GetStringFromObj(obj, &byteCount); + string = TkGetStringFromObj(obj, &byteCount); text = textPtr->text; if (index < 0) { index = 0; @@ -1026,11 +1030,11 @@ if (byteCount == 0) { return; } newStr = ckalloc(textPtr->numBytes + byteCount + 1); - memcpy(newStr, text, (size_t) byteIndex); + memcpy(newStr, text, byteIndex); strcpy(newStr + byteIndex, string); strcpy(newStr + byteIndex + byteCount, text + byteIndex); ckfree(text); textPtr->text = newStr; @@ -1107,11 +1111,11 @@ byteIndex = Tcl_UtfAtIndex(text, first) - text; byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved) - (text + byteIndex); newStr = ckalloc(textPtr->numBytes + 1 - byteCount); - memcpy(newStr, text, (size_t) byteIndex); + memcpy(newStr, text, byteIndex); strcpy(newStr + byteIndex, text + byteIndex + byteCount); ckfree(text); textPtr->text = newStr; textPtr->numChars -= charsRemoved; @@ -1247,10 +1251,43 @@ } /* *-------------------------------------------------------------- * + * RotateText -- + * + * This function is called to rotate a text item by a given amount about a + * point. Note that this does *not* rotate the text of the item. + * + * Results: + * None. + * + * Side effects: + * The position of the text anchor is rotated by angleRad about (originX, + * originY), and the bounding box is updated in the generic part of the + * item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateText( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being rotated. */ + double originX, double originY, + double angleRad) /* Amount by which item is to be rotated. */ +{ + TextItem *textPtr = (TextItem *) itemPtr; + + TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad), + &textPtr->x, &textPtr->y); + ComputeTextBbox(canvas, textPtr); +} + +/* + *-------------------------------------------------------------- + * * ScaleText -- * * This function is invoked to rescale a text item. * * Results: @@ -1341,34 +1378,34 @@ * itemPtr's text. */ int *indexPtr) /* Where to store converted character * index. */ { TextItem *textPtr = (TextItem *) itemPtr; - int length; + TkSizeT length; int c; TkCanvas *canvasPtr = (TkCanvas *) canvas; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; - const char *string = Tcl_GetStringFromObj(obj, &length); + const char *string = TkGetStringFromObj(obj, &length); c = string[0]; - if ((c == 'e') && (strncmp(string, "end", (unsigned) length) == 0)) { + if ((c == 'e') && (strncmp(string, "end", length) == 0)) { *indexPtr = textPtr->numChars; } else if ((c == 'i') - && (strncmp(string, "insert", (unsigned) length) == 0)) { + && (strncmp(string, "insert", length) == 0)) { *indexPtr = textPtr->insertPos; } else if ((c == 's') && (length >= 5) - && (strncmp(string, "sel.first", (unsigned) length) == 0)) { + && (strncmp(string, "sel.first", length) == 0)) { if (textInfoPtr->selItemPtr != itemPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "selection isn't in item", -1)); Tcl_SetErrorCode(interp, "TK", "CANVAS", "UNSELECTED", NULL); return TCL_ERROR; } *indexPtr = textInfoPtr->selectFirst; } else if ((c == 's') && (length >= 5) - && (strncmp(string, "sel.last", (unsigned) length) == 0)) { + && (strncmp(string, "sel.last", length) == 0)) { if (textInfoPtr->selItemPtr != itemPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "selection isn't in item", -1)); Tcl_SetErrorCode(interp, "TK", "CANVAS", "UNSELECTED", NULL); return TCL_ERROR; @@ -1502,11 +1539,11 @@ byteCount = maxBytes; } if (byteCount <= 0) { return 0; } - memcpy(buffer, selStart + offset, (size_t) byteCount); + memcpy(buffer, selStart + offset, byteCount); buffer[byteCount] = '\0'; return byteCount; } /* Index: generic/tkCanvUtil.c ================================================================== --- generic/tkCanvUtil.c +++ generic/tkCanvUtil.c @@ -10,11 +10,10 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkCanvas.h" -#include /* * Structures defined only in this file. */ @@ -1263,11 +1262,10 @@ tsoffset->yoffset += h; return 1; } return 0; } - /* *-------------------------------------------------------------- * * Tk_ResetOutlineGC @@ -1861,13 +1859,50 @@ if (tempArr != staticSpace) { ckfree(tempArr); } return numOutput; } + +/* + *-------------------------------------------------------------- + * + * TkRotatePoint -- + * + * Rotate a point about another point. The angle should be converted into + * its sine and cosine before calling this function. + * + * Results: + * None + * + * Side effects: + * The point in (*xPtr,*yPtr) is updated to be rotated about + * (originX,originY) by the amount given by the sine and cosine of the + * angle to rotate. + * + *-------------------------------------------------------------- + */ + +void +TkRotatePoint( + double originX, double originY, /* The point about which to rotate. */ + double sine, double cosine, /* How much to rotate? */ + double *xPtr, double *yPtr) /* The point to be rotated. (INOUT) */ +{ + double x = *xPtr - originX; + double y = *yPtr - originY; + + /* + * Beware! The canvas coordinate space is flipped vertically, so rotations + * go the "wrong" way with respect to mathematics. + */ + + *xPtr = originX + x * cosine + y * sine; + *yPtr = originY - x * sine + y * cosine; +} /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tkCanvWind.c ================================================================== --- generic/tkCanvWind.c +++ generic/tkCanvWind.c @@ -44,21 +44,21 @@ Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, - "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "center", offsetof(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_PIXELS, "-height", NULL, NULL, - "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0", offsetof(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_PIXELS, "-width", NULL, NULL, - "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL}, + "0", offsetof(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_WINDOW, "-window", NULL, NULL, - NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(WindowItem, tkwin), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* * Prototypes for functions defined in this file: @@ -75,10 +75,12 @@ static void DeleteWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display); static void DisplayWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, int x, int y, int width, int height); +static void RotateWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void ScaleWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); static void TranslateWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -128,11 +130,12 @@ NULL, /* cursorProc */ NULL, /* selectionProc */ NULL, /* insertProc */ NULL, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateWinItem, /* rotateProc */ + 0, NULL, NULL }; /* * The structure below defines the official type record for the canvas (as * geometry manager): @@ -909,10 +912,44 @@ Tcl_DiscardInterpState(interpState); } Tcl_DecrRefCount(psObj); return result; } + +/* + *-------------------------------------------------------------- + * + * RotateWinItem -- + * + * This function is called to rotate a window item by a given amount + * about a point. Note that this does *not* rotate the window of the + * item. + * + * Results: + * None. + * + * Side effects: + * The position of the window anchor is rotated by angleRad about (originX, + * originY), and the bounding box is updated in the generic part of the + * item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateWinItem( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being rotated. */ + double originX, double originY, + double angleRad) /* Amount by which item is to be rotated. */ +{ + WindowItem *winItemPtr = (WindowItem *) itemPtr; + + TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad), + &winItemPtr->x, &winItemPtr->y); + ComputeWindowBbox(canvas, winItemPtr); +} /* *-------------------------------------------------------------- * * ScaleWinItem -- Index: generic/tkCanvas.c ================================================================== --- generic/tkCanvas.c +++ generic/tkCanvas.c @@ -11,15 +11,13 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -/* #define USE_OLD_TAG_SEARCH 1 */ - -#include "default.h" #include "tkInt.h" #include "tkCanvas.h" +#include "default.h" #ifdef TK_NO_DOUBLE_BUFFERING #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #endif #endif /* TK_NO_DOUBLE_BUFFERING */ @@ -26,30 +24,10 @@ /* * See tkCanvas.h for key data structures used to implement canvases. */ -#ifdef USE_OLD_TAG_SEARCH -/* - * The structure defined below is used to keep track of a tag search in - * progress. No field should be accessed by anyone other than StartTagSearch - * and NextItem. - */ - -typedef struct TagSearch { - TkCanvas *canvasPtr; /* Canvas widget being searched. */ - Tk_Uid tag; /* Tag to search for. 0 means return all - * items. */ - Tk_Item *currentPtr; /* Pointer to last item returned. */ - Tk_Item *lastPtr; /* The item right before the currentPtr is - * tracked so if the currentPtr is deleted we - * don't have to start from the beginning. */ - int searchOver; /* Non-zero means NextItem should always - * return NULL. */ -} TagSearch; - -#else /* USE_OLD_TAG_SEARCH */ /* * The structure defined below is used to keep track of a tag search in * progress. No field should be accessed by anyone other than TagSearchScan, * TagSearchFirst, TagSearchNext, TagSearchScanExpr, TagSearchEvalExpr, * TagSearchExprInit, TagSearchExprDestroy, TagSearchDestroy. @@ -92,12 +70,10 @@ #define SEARCH_TYPE_ID 1 /* Looking for an item by id */ #define SEARCH_TYPE_ALL 2 /* Looking for all items */ #define SEARCH_TYPE_TAG 3 /* Looking for an item by simple tag */ #define SEARCH_TYPE_EXPR 4 /* Compound search */ -#endif /* USE_OLD_TAG_SEARCH */ - /* * Custom option for handling "-state" and "-offset" */ static const Tk_CustomOption stateOption = { @@ -113,96 +89,96 @@ * Information used for argv parsing. */ static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_CANVAS_BG_COLOR, Tk_Offset(TkCanvas, bgBorder), + DEF_CANVAS_BG_COLOR, offsetof(TkCanvas, bgBorder), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_CANVAS_BG_MONO, Tk_Offset(TkCanvas, bgBorder), + DEF_CANVAS_BG_MONO, offsetof(TkCanvas, bgBorder), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL}, {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL}, {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_CANVAS_BORDER_WIDTH, Tk_Offset(TkCanvas, borderWidth), 0, NULL}, + DEF_CANVAS_BORDER_WIDTH, offsetof(TkCanvas, borderWidth), 0, NULL}, {TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough", - DEF_CANVAS_CLOSE_ENOUGH, Tk_Offset(TkCanvas, closeEnough), 0, NULL}, + DEF_CANVAS_CLOSE_ENOUGH, offsetof(TkCanvas, closeEnough), 0, NULL}, {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine", - DEF_CANVAS_CONFINE, Tk_Offset(TkCanvas, confine), 0, NULL}, + DEF_CANVAS_CONFINE, offsetof(TkCanvas, confine), 0, NULL}, {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", - DEF_CANVAS_CURSOR, Tk_Offset(TkCanvas, cursor), TK_CONFIG_NULL_OK, NULL}, + DEF_CANVAS_CURSOR, offsetof(TkCanvas, cursor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_PIXELS, "-height", "height", "Height", - DEF_CANVAS_HEIGHT, Tk_Offset(TkCanvas, height), 0, NULL}, + DEF_CANVAS_HEIGHT, offsetof(TkCanvas, height), 0, NULL}, {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_CANVAS_HIGHLIGHT_BG, - Tk_Offset(TkCanvas, highlightBgColorPtr), 0, NULL}, + offsetof(TkCanvas, highlightBgColorPtr), 0, NULL}, {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_CANVAS_HIGHLIGHT, Tk_Offset(TkCanvas, highlightColorPtr), 0, NULL}, + DEF_CANVAS_HIGHLIGHT, offsetof(TkCanvas, highlightColorPtr), 0, NULL}, {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", - DEF_CANVAS_HIGHLIGHT_WIDTH, Tk_Offset(TkCanvas, highlightWidth), 0, NULL}, + DEF_CANVAS_HIGHLIGHT_WIDTH, offsetof(TkCanvas, highlightWidth), 0, NULL}, {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground", - DEF_CANVAS_INSERT_BG, Tk_Offset(TkCanvas, textInfo.insertBorder), 0, NULL}, + DEF_CANVAS_INSERT_BG, offsetof(TkCanvas, textInfo.insertBorder), 0, NULL}, {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_CANVAS_INSERT_BD_COLOR, - Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_COLOR_ONLY, NULL}, + offsetof(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_CANVAS_INSERT_BD_MONO, - Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_MONO_ONLY, NULL}, + offsetof(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_CANVAS_INSERT_OFF_TIME, Tk_Offset(TkCanvas, insertOffTime), 0, NULL}, + DEF_CANVAS_INSERT_OFF_TIME, offsetof(TkCanvas, insertOffTime), 0, NULL}, {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_CANVAS_INSERT_ON_TIME, Tk_Offset(TkCanvas, insertOnTime), 0, NULL}, + DEF_CANVAS_INSERT_ON_TIME, offsetof(TkCanvas, insertOnTime), 0, NULL}, {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_CANVAS_INSERT_WIDTH, Tk_Offset(TkCanvas, textInfo.insertWidth), 0, NULL}, + DEF_CANVAS_INSERT_WIDTH, offsetof(TkCanvas, textInfo.insertWidth), 0, NULL}, {TK_CONFIG_CUSTOM, "-offset", "offset", "Offset", "0,0", - Tk_Offset(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT, + offsetof(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", - DEF_CANVAS_RELIEF, Tk_Offset(TkCanvas, relief), 0, NULL}, + DEF_CANVAS_RELIEF, offsetof(TkCanvas, relief), 0, NULL}, {TK_CONFIG_STRING, "-scrollregion", "scrollRegion", "ScrollRegion", - DEF_CANVAS_SCROLL_REGION, Tk_Offset(TkCanvas, regionString), + DEF_CANVAS_SCROLL_REGION, offsetof(TkCanvas, regionString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_CANVAS_SELECT_COLOR, Tk_Offset(TkCanvas, textInfo.selBorder), + DEF_CANVAS_SELECT_COLOR, offsetof(TkCanvas, textInfo.selBorder), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_CANVAS_SELECT_MONO, Tk_Offset(TkCanvas, textInfo.selBorder), + DEF_CANVAS_SELECT_MONO, offsetof(TkCanvas, textInfo.selBorder), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_CANVAS_SELECT_BD_COLOR, - Tk_Offset(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_COLOR_ONLY, NULL}, + offsetof(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", - DEF_CANVAS_SELECT_BD_MONO, Tk_Offset(TkCanvas, textInfo.selBorderWidth), + DEF_CANVAS_SELECT_BD_MONO, offsetof(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_CANVAS_SELECT_FG_COLOR, Tk_Offset(TkCanvas, textInfo.selFgColorPtr), + DEF_CANVAS_SELECT_FG_COLOR, offsetof(TkCanvas, textInfo.selFgColorPtr), TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(TkCanvas, textInfo.selFgColorPtr), + DEF_CANVAS_SELECT_FG_MONO, offsetof(TkCanvas, textInfo.selFgColorPtr), TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-state", "state", "State", - "normal", Tk_Offset(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT, + "normal", offsetof(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT, &stateOption}, {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_CANVAS_TAKE_FOCUS, Tk_Offset(TkCanvas, takeFocus), + DEF_CANVAS_TAKE_FOCUS, offsetof(TkCanvas, takeFocus), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_PIXELS, "-width", "width", "Width", - DEF_CANVAS_WIDTH, Tk_Offset(TkCanvas, width), 0, NULL}, + DEF_CANVAS_WIDTH, offsetof(TkCanvas, width), 0, NULL}, {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_CANVAS_X_SCROLL_CMD, Tk_Offset(TkCanvas, xScrollCmd), + DEF_CANVAS_X_SCROLL_CMD, offsetof(TkCanvas, xScrollCmd), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement", - DEF_CANVAS_X_SCROLL_INCREMENT, Tk_Offset(TkCanvas, xScrollIncrement), + DEF_CANVAS_X_SCROLL_INCREMENT, offsetof(TkCanvas, xScrollIncrement), 0, NULL}, {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - DEF_CANVAS_Y_SCROLL_CMD, Tk_Offset(TkCanvas, yScrollCmd), + DEF_CANVAS_Y_SCROLL_CMD, offsetof(TkCanvas, yScrollCmd), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement", - DEF_CANVAS_Y_SCROLL_INCREMENT, Tk_Offset(TkCanvas, yScrollIncrement), + DEF_CANVAS_Y_SCROLL_INCREMENT, offsetof(TkCanvas, yScrollIncrement), 0, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* @@ -213,11 +189,10 @@ static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't been done * yet. */ TCL_DECLARE_MUTEX(typeListMutex) -#ifndef USE_OLD_TAG_SEARCH /* * Uids for operands in compiled advanced tag search expressions. * Initialization is done by GetStaticUids() */ @@ -234,11 +209,10 @@ Tk_Uid negtagvalUid; } SearchUids; static Tcl_ThreadDataKey dataKey; static SearchUids * GetStaticUids(void); -#endif /* USE_OLD_TAG_SEARCH */ /* * Prototypes for functions defined later in this file: */ @@ -265,43 +239,32 @@ Tcl_Obj *const *argv); static void CanvasWorldChanged(ClientData instanceData); static int ConfigureCanvas(Tcl_Interp *interp, TkCanvas *canvasPtr, int argc, Tcl_Obj *const *argv, int flags); -static void DestroyCanvas(char *memPtr); +static void DefaultRotateImplementation(TkCanvas *canvasPtr, + Tk_Item *itemPtr, double x, double y, + double angleRadians); +static void DestroyCanvas(void *memPtr); +static int DrawCanvas(Tcl_Interp *interp, ClientData clientData, Tk_PhotoHandle photohandle, int subsample, int zoom); static void DisplayCanvas(ClientData clientData); static void DoItem(Tcl_Obj *accumObj, Tk_Item *itemPtr, Tk_Uid tag); static void EventuallyRedrawItem(TkCanvas *canvasPtr, Tk_Item *itemPtr); -#ifdef USE_OLD_TAG_SEARCH -static int FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr, - int argc, Tcl_Obj *const *argv, - Tcl_Obj *newTagObj, int first); -#else /* USE_OLD_TAG_SEARCH */ static int FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr, int argc, Tcl_Obj *const *argv, Tcl_Obj *newTagObj, int first, TagSearch **searchPtrPtr); -#endif /* USE_OLD_TAG_SEARCH */ static int FindArea(Tcl_Interp *interp, TkCanvas *canvasPtr, Tcl_Obj *const *argv, Tk_Uid uid, int enclosed); static double GridAlign(double coord, double spacing); static const char** TkGetStringsFromObjs(int argc, Tcl_Obj *const *objv); static void InitCanvas(void); -#ifdef USE_OLD_TAG_SEARCH -static Tk_Item * NextItem(TagSearch *searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ static void PickCurrentItem(TkCanvas *canvasPtr, XEvent *eventPtr); static Tcl_Obj * ScrollFractions(int screen1, int screen2, int object1, int object2); -#ifdef USE_OLD_TAG_SEARCH -static void RelinkItems(TkCanvas *canvasPtr, - Tcl_Obj *tag, Tk_Item *prevPtr); -static Tk_Item * StartTagSearch(TkCanvas *canvasPtr, - Tcl_Obj *tag, TagSearch *searchPtr); -#else /* USE_OLD_TAG_SEARCH */ static int RelinkItems(TkCanvas *canvasPtr, Tcl_Obj *tag, Tk_Item *prevPtr, TagSearch **searchPtrPtr); static void TagSearchExprInit(TagSearchExpr **exprPtrPtr); static void TagSearchExprDestroy(TagSearchExpr *expr); static void TagSearchDestroy(TagSearch *searchPtr); @@ -311,11 +274,10 @@ TagSearch *searchPtr, TagSearchExpr *expr); static int TagSearchEvalExpr(TagSearchExpr *expr, Tk_Item *itemPtr); static Tk_Item * TagSearchFirst(TagSearch *searchPtr); static Tk_Item * TagSearchNext(TagSearch *searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ /* * The structure below defines canvas class behavior by means of functions * that can be invoked from generic window code. */ @@ -329,21 +291,10 @@ /* * Macros that significantly simplify all code that finds items. */ -#ifdef USE_OLD_TAG_SEARCH -#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ - itemPtr = StartTagSearch(canvasPtr,(objPtr),&search) -#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ - for (itemPtr = StartTagSearch(canvasPtr, (objPtr), &search); \ - itemPtr != NULL; itemPtr = NextItem(&search)) -#define FIND_ITEMS(objPtr, n) \ - FindItems(interp, canvasPtr, objc, objv, (objPtr), (n)) -#define RELINK_ITEMS(objPtr, itemPtr) \ - RelinkItems(canvasPtr, (objPtr), (itemPtr)) -#else /* USE_OLD_TAG_SEARCH */ #define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \ errorExitClause; \ } \ itemPtr = TagSearchFirst(*(searchPtrPtr)); @@ -355,11 +306,10 @@ itemPtr != NULL; itemPtr = TagSearchNext(*(searchPtrPtr))) #define FIND_ITEMS(objPtr, n) \ FindItems(interp, canvasPtr, objc, objv, (objPtr), (n), &searchPtr) #define RELINK_ITEMS(objPtr, itemPtr) \ result = RelinkItems(canvasPtr, (objPtr), (itemPtr), &searchPtr) -#endif /* USE_OLD_TAG_SEARCH */ /* * ---------------------------------------------------------------------- * * AlwaysRedraw, ItemConfigure, ItemCoords, etc. -- @@ -611,10 +561,106 @@ double yDelta) { itemPtr->typePtr->translateProc((Tk_Canvas) canvasPtr, itemPtr, xDelta, yDelta); } + +static inline void +ItemRotate( + TkCanvas *canvasPtr, + Tk_Item *itemPtr, + double x, + double y, + double angleRadians) +{ + if (itemPtr->typePtr->rotateProc != NULL) { + itemPtr->typePtr->rotateProc((Tk_Canvas) canvasPtr, + itemPtr, x, y, angleRadians); + } else { + DefaultRotateImplementation(canvasPtr, itemPtr, x, y, angleRadians); + } +} + +/* + *-------------------------------------------------------------- + * + * DefaultRotateImplementation -- + * + * The default implementation of the rotation operation, used when items + * do not provide their own version. + * + *-------------------------------------------------------------- + */ + +static void +DefaultRotateImplementation( + TkCanvas *canvasPtr, + Tk_Item *itemPtr, + double x, + double y, + double angleRadians) +{ + int objc, i, ok = 1; + Tcl_Obj **objv, **newObjv; + double *coordv; + double s = sin(angleRadians); + double c = cos(angleRadians); + Tcl_Interp *interp = canvasPtr->interp; + + /* + * Get the coordinates out of the item. + */ + + if (ItemCoords(canvasPtr, itemPtr, 0, NULL) == TCL_OK && + Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp), + &objc, &objv) == TCL_OK) { + coordv = (double *) ckalloc(sizeof(double) * objc); + for (i=0 ; itextInfo.focusItemPtr = NULL; canvasPtr->textInfo.gotFocus = 0; canvasPtr->textInfo.cursorOn = 0; canvasPtr->insertOnTime = 0; canvasPtr->insertOffTime = 0; - canvasPtr->insertBlinkHandler = (Tcl_TimerToken) NULL; + canvasPtr->insertBlinkHandler = NULL; canvasPtr->xOrigin = canvasPtr->yOrigin = 0; canvasPtr->drawableXOrigin = canvasPtr->drawableYOrigin = 0; canvasPtr->bindingTable = NULL; canvasPtr->currentItemPtr = NULL; canvasPtr->newCurrentPtr = NULL; @@ -733,13 +779,11 @@ canvasPtr->psInfo = NULL; canvasPtr->canvas_state = TK_STATE_NORMAL; canvasPtr->tsoffset.flags = 0; canvasPtr->tsoffset.xoffset = 0; canvasPtr->tsoffset.yoffset = 0; -#ifndef USE_OLD_TAG_SEARCH canvasPtr->bindTagExprs = NULL; -#endif Tcl_InitHashTable(&canvasPtr->idTable, TCL_ONE_WORD_KEYS); Tk_SetClass(canvasPtr->tkwin, "Canvas"); Tk_SetClassProcs(canvasPtr->tkwin, &canvasClass, canvasPtr); Tk_CreateEventHandler(canvasPtr->tkwin, @@ -790,40 +834,37 @@ { TkCanvas *canvasPtr = clientData; int c, result; Tk_Item *itemPtr = NULL; /* Initialization needed only to prevent * compiler warning. */ -#ifdef USE_OLD_TAG_SEARCH - TagSearch search; -#else /* USE_OLD_TAG_SEARCH */ TagSearch *searchPtr = NULL;/* Allocated by first TagSearchScan, freed by * TagSearchDestroy */ -#endif /* USE_OLD_TAG_SEARCH */ int index; static const char *const optionStrings[] = { "addtag", "bbox", "bind", "canvasx", "canvasy", "cget", "configure", "coords", "create", "dchars", "delete", "dtag", "find", "focus", "gettags", "icursor", - "imove", "index", "insert", "itemcget", - "itemconfigure", + "image", "imove", "index", "insert", + "itemcget", "itemconfigure", "lower", "move", "moveto", "postscript", - "raise", "rchars", "scale", "scan", - "select", "type", "xview", "yview", - NULL + "raise", "rchars", "rotate", "scale", + "scan", "select", "type", "xview", + "yview", NULL }; enum options { CANV_ADDTAG, CANV_BBOX, CANV_BIND, CANV_CANVASX, CANV_CANVASY, CANV_CGET, CANV_CONFIGURE, CANV_COORDS, CANV_CREATE, CANV_DCHARS, CANV_DELETE, CANV_DTAG, CANV_FIND, CANV_FOCUS, CANV_GETTAGS, CANV_ICURSOR, - CANV_IMOVE, CANV_INDEX, CANV_INSERT, CANV_ITEMCGET, - CANV_ITEMCONFIGURE, + CANV_IMAGE, CANV_IMOVE, CANV_INDEX, CANV_INSERT, + CANV_ITEMCGET, CANV_ITEMCONFIGURE, CANV_LOWER, CANV_MOVE, CANV_MOVETO, CANV_POSTSCRIPT, - CANV_RAISE, CANV_RCHARS, CANV_SCALE, CANV_SCAN, - CANV_SELECT, CANV_TYPE, CANV_XVIEW, CANV_YVIEW + CANV_RAISE, CANV_RCHARS, CANV_ROTATE, CANV_SCALE, + CANV_SCAN, CANV_SELECT, CANV_TYPE, CANV_XVIEW, + CANV_YVIEW }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; @@ -886,20 +927,20 @@ } } if (gotAny) { Tcl_Obj *resultObjs[4]; - resultObjs[0] = Tcl_NewIntObj(x1); - resultObjs[1] = Tcl_NewIntObj(y1); - resultObjs[2] = Tcl_NewIntObj(x2); - resultObjs[3] = Tcl_NewIntObj(y2); + resultObjs[0] = Tcl_NewWideIntObj(x1); + resultObjs[1] = Tcl_NewWideIntObj(y1); + resultObjs[2] = Tcl_NewWideIntObj(x2); + resultObjs[3] = Tcl_NewWideIntObj(y2); Tcl_SetObjResult(interp, Tcl_NewListObj(4, resultObjs)); } break; } case CANV_BIND: { - ClientData object; + void *object; if ((objc < 3) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?sequence? ?command?"); result = TCL_ERROR; goto done; @@ -909,48 +950,19 @@ * Figure out what object to use for the binding (individual item vs. * tag). */ object = NULL; -#ifdef USE_OLD_TAG_SEARCH - if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))) { - int id; - char *end; - Tcl_HashEntry *entryPtr; - - id = strtoul(Tcl_GetString(objv[2]), &end, 0); - if (*end != 0) { - goto bindByTag; - } - entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id); - if (entryPtr != NULL) { - itemPtr = Tcl_GetHashValue(entryPtr); - object = itemPtr; - } - - if (object == NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "item \"%s\" doesn't exist", Tcl_GetString(objv[2]))); - Tcl_SetErrorCode(interp, "TK", "LOOKUP", "CANVAS_ITEM", - Tcl_GetString(objv[2]), NULL); - result = TCL_ERROR; - goto done; - } - } else { - bindByTag: - object = Tk_GetUid(Tcl_GetString(objv[2])); - } -#else /* USE_OLD_TAG_SEARCH */ result = TagSearchScan(canvasPtr, objv[2], &searchPtr); if (result != TCL_OK) { goto done; } if (searchPtr->type == SEARCH_TYPE_ID) { Tcl_HashEntry *entryPtr; entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, - (char *) INT2PTR(searchPtr->id)); + INT2PTR(searchPtr->id)); if (entryPtr != NULL) { itemPtr = Tcl_GetHashValue(entryPtr); object = itemPtr; } @@ -961,13 +973,12 @@ Tcl_GetString(objv[2]), NULL); result = TCL_ERROR; goto done; } } else { - object = (ClientData) searchPtr->expr->uid; + object = (char *)searchPtr->expr->uid; } -#endif /* USE_OLD_TAG_SEARCH */ /* * Make a binding table if the canvas doesn't already have one. */ @@ -983,11 +994,10 @@ if (argv4[0] == 0) { result = Tk_DeleteBinding(interp, canvasPtr->bindingTable, object, Tcl_GetString(objv[3])); goto done; } -#ifndef USE_OLD_TAG_SEARCH if (searchPtr->type == SEARCH_TYPE_EXPR) { /* * If new tag expression, then insert in linked list. */ @@ -1014,11 +1024,10 @@ */ searchPtr->expr = NULL; } } -#endif /* not USE_OLD_TAG_SEARCH */ if (argv4[0] == '+') { argv4++; append = 1; } mask = Tk_CreateBinding(interp, canvasPtr->bindingTable, @@ -1025,11 +1034,11 @@ object, Tcl_GetString(objv[3]), argv4, append); if (mask == 0) { result = TCL_ERROR; goto done; } - if (mask & (unsigned long) ~(ButtonMotionMask|Button1MotionMask + if (mask & ~(unsigned long)(ButtonMotionMask|Button1MotionMask |Button2MotionMask|Button3MotionMask|Button4MotionMask |Button5MotionMask|ButtonPressMask|ButtonReleaseMask |EnterWindowMask|LeaveWindowMask|KeyPressMask |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) { Tk_DeleteBinding(interp, canvasPtr->bindingTable, @@ -1240,19 +1249,18 @@ Tk_ItemType *matchPtr = NULL; Tk_Item *itemPtr; int isNew = 0; Tcl_HashEntry *entryPtr; const char *arg; - size_t length; + TkSizeT length; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg ...?"); result = TCL_ERROR; goto done; } - arg = Tcl_GetString(objv[2]); - length = objv[2]->length; + arg = TkGetStringFromObj(objv[2], &length); c = arg[0]; /* * Lock because the list of types is a global resource that could be * updated by another thread. That's fairly unlikely, but not @@ -1313,11 +1321,11 @@ goto done; } itemPtr->nextPtr = NULL; entryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable, - (char *) INT2PTR(itemPtr->id), &isNew); + INT2PTR(itemPtr->id), &isNew); Tcl_SetHashValue(entryPtr, itemPtr); itemPtr->prevPtr = canvasPtr->lastItemPtr; canvasPtr->hotPtr = itemPtr; canvasPtr->hotPrevPtr = canvasPtr->lastItemPtr; if (canvasPtr->lastItemPtr == NULL) { @@ -1327,11 +1335,11 @@ } canvasPtr->lastItemPtr = itemPtr; itemPtr->redraw_flags |= FORCE_REDRAW; EventuallyRedrawItem(canvasPtr, itemPtr); canvasPtr->flags |= REPICK_NEEDED; - Tcl_SetObjResult(interp, Tcl_NewIntObj(itemPtr->id)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(itemPtr->id)); break; } case CANV_DCHARS: { int first, last; int x1, x2, y1, y2; @@ -1392,11 +1400,11 @@ ItemDelete(canvasPtr, itemPtr); if (itemPtr->tagPtr != itemPtr->staticTagSpace) { ckfree(itemPtr->tagPtr); } entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, - (char *) INT2PTR(itemPtr->id)); + INT2PTR(itemPtr->id)); Tcl_DeleteHashEntry(entryPtr); if (itemPtr->nextPtr != NULL) { itemPtr->nextPtr->prevPtr = itemPtr->prevPtr; } if (itemPtr->prevPtr != NULL) { @@ -1473,11 +1481,11 @@ goto done; } itemPtr = canvasPtr->textInfo.focusItemPtr; if (objc == 2) { if (itemPtr != NULL) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(itemPtr->id)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(itemPtr->id)); } goto done; } if (canvasPtr->textInfo.gotFocus) { EventuallyRedrawItem(canvasPtr, itemPtr); @@ -1565,11 +1573,11 @@ } result = ItemIndex(canvasPtr, itemPtr, objv[3], &index); if (result != TCL_OK) { goto done; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index)); break; } case CANV_INSERT: { int beforeThis; int x1, x2, y1, y2; @@ -1846,10 +1854,34 @@ x1, y1, x2, y2); EventuallyRedrawItem(canvasPtr, itemPtr); } itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; } + break; + } + case CANV_ROTATE: { + double x, y, angle; + Tk_Canvas canvas = (Tk_Canvas) canvasPtr; + + if (objc != 6) { + Tcl_WrongNumArgs(interp, 2, objv, "tagOrId x y angle"); + result = TCL_ERROR; + goto done; + } + if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3], &x) != TCL_OK || + Tk_CanvasGetCoordFromObj(interp, canvas, objv[4], &y) != TCL_OK || + Tcl_GetDoubleFromObj(interp, objv[5], &angle) != TCL_OK) { + result = TCL_ERROR; + goto done; + } + angle = angle * 3.1415927 / 180.0; + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { + EventuallyRedrawItem(canvasPtr, itemPtr); + ItemRotate(canvasPtr, itemPtr, x, y, angle); + EventuallyRedrawItem(canvasPtr, itemPtr); + canvasPtr->flags |= REPICK_NEEDED; + } break; } case CANV_SCALE: { double xOrigin, yOrigin, xScale, yScale; @@ -2012,11 +2044,11 @@ result = TCL_ERROR; goto done; } if (canvasPtr->textInfo.selItemPtr != NULL) { Tcl_SetObjResult(interp, - Tcl_NewIntObj(canvasPtr->textInfo.selItemPtr->id)); + Tcl_NewWideIntObj(canvasPtr->textInfo.selItemPtr->id)); } break; case CANV_TO: if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index"); @@ -2129,16 +2161,54 @@ break; } CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY); break; } + case CANV_IMAGE: { + Tk_PhotoHandle photohandle; + int subsample = 1, zoom = 1; + + if (objc < 3 || objc > 5) { + Tcl_WrongNumArgs(interp, 2, objv, "imagename ?subsample? ?zoom?"); + result = TCL_ERROR; + goto done; + } + + if ((photohandle = Tk_FindPhoto(interp, Tcl_GetString(objv[2]) )) == 0) { + result = TCL_ERROR; + goto done; + } + + /* + * If we are given a subsample or a zoom then grab them. + */ + + if (objc >= 4 && Tcl_GetIntFromObj(interp, objv[3], &subsample) != TCL_OK) { + result = TCL_ERROR; + goto done; + } + if (objc >= 5 && Tcl_GetIntFromObj(interp, objv[4], &zoom) != TCL_OK) { + result = TCL_ERROR; + goto done; + } + + /* + * Set the image size to zero, which allows the DrawCanvas() function + * to expand the image automatically when it copies the pixmap into it. + */ + + if (Tk_PhotoSetSize(interp, photohandle, 0, 0) != TCL_OK) { + result = TCL_ERROR; + goto done; + } + + result = DrawCanvas(interp, clientData, photohandle, subsample, zoom); + } } done: -#ifndef USE_OLD_TAG_SEARCH TagSearchDestroy(searchPtr); -#endif /* not USE_OLD_TAG_SEARCH */ Tcl_Release(canvasPtr); return result; } /* @@ -2159,17 +2229,15 @@ *---------------------------------------------------------------------- */ static void DestroyCanvas( - char *memPtr) /* Info about canvas widget. */ + void *memPtr) /* Info about canvas widget. */ { - TkCanvas *canvasPtr = (TkCanvas *) memPtr; + TkCanvas *canvasPtr = memPtr; Tk_Item *itemPtr; -#ifndef USE_OLD_TAG_SEARCH TagSearchExpr *expr, *next; -#endif /* * Free up all of the items in the canvas. */ @@ -2190,18 +2258,16 @@ Tcl_DeleteHashTable(&canvasPtr->idTable); if (canvasPtr->pixmapGC != NULL) { Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC); } -#ifndef USE_OLD_TAG_SEARCH expr = canvasPtr->bindTagExprs; while (expr) { next = expr->next; TagSearchExprDestroy(expr); expr = next; } -#endif /* USE_OLD_TAG_SEARCH */ Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler); if (canvasPtr->bindingTable != NULL) { Tk_DeleteBindingTable(canvasPtr->bindingTable); } Tk_FreeOptions(configSpecs, (char *) canvasPtr, canvasPtr->display, 0); @@ -2414,10 +2480,504 @@ canvasPtr->xOrigin, canvasPtr->yOrigin, canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin), canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin)); } +/* + *---------------------------------------------------------------------- + * + * DecomposeMaskToShiftAndBits -- + * + * Given a 32 bit pixel mask, we find the position of the lowest bit and the + * width of the mask bits. + * + * Results: + * None. + * + * Side effects: +* None. + * + *---------------------------------------------------------------------- + */ +static void +DecomposeMaskToShiftAndBits( + unsigned long mask, /* The pixel mask to examine */ + int *shift, /* Where to put the shift count (position of lowest bit) */ + int *bits) /* Where to put the bit count (width of the pixel mask) */ +{ + int i; + + *shift = 0; + *bits = 0; + + /* + * Find the lowest '1' bit in the mask. + */ + + for (i = 0; i < 32; ++i) { + if (mask & 1 << i) + break; + } + if (i < 32) { + *shift = i; + + /* + * Now find the next '0' bit and the width of the mask. + */ + + for ( ; i < 32; ++i) { + if ((mask & 1 << i) == 0) + break; + else + ++*bits; + } + + /* + * Limit to the top 8 bits if the mask was wider than 8. + */ + + if (*bits > 8) { + *shift += *bits - 8; + *bits = 8; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawCanvas -- + * + * This function draws the contents of a canvas into the given Photo image. + * This function is called from the widget "image" subcommand. + * The canvas does not need to be mapped (one of it's ancestors must be) + * in order for this function to work. + * + * Results: + * None. + * + * Side effects: + * Canvas contents from within the -scrollregion or widget size are rendered + * into the Photo. Any errors are left in the result. + * + *---------------------------------------------------------------------- + */ + +#define OVERDRAW_PIXELS 32 /* How much larger we make the pixmap + * that the canvas objects are drawn into */ + +/* From stackoverflow.com/questions/2100331/c-macro-definition-to-determine-big-endian-or-little-endian-machine */ +#define IS_BIG_ENDIAN (*(unsigned short *)"\0\xff" < 0x100) + +#define BYTE_SWAP16(n) ((((unsigned short)n)>>8) | (((unsigned short)n)<<8)) +#define BYTE_SWAP32(n) (((n>>24)&0x000000FF) | ((n<<8)&0x00FF0000) | ((n>>8)&0x0000FF00) | ((n<<24)&0xFF000000)) + +static int +DrawCanvas( + Tcl_Interp *interp, /* As passed to the widget command, and we will leave errors here */ + ClientData clientData, + Tk_PhotoHandle photohandle, /* The photo we are rendering into */ + int subsample, /* If either subsample or zoom are not 1 then we call Tk_PhotoPutZoomedBlock() */ + int zoom) +{ + TkCanvas * canvasPtr = clientData; + Tk_Window tkwin; + Display *displayPtr; + Tk_PhotoImageBlock blockPtr = {0}; + Window wid; + Tk_Item * itemPtr; + Pixmap pixmap = 0; + XImage *ximagePtr = NULL; + Visual *visualPtr; + GC xgc = 0; + XGCValues xgcValues; + int canvasX1, canvasY1, canvasX2, canvasY2, cWidth, cHeight, + pixmapX1, pixmapY1, pixmapX2, pixmapY2, pmWidth, pmHeight, + bitsPerPixel, bytesPerPixel, x, y, result = TCL_OK, + rshift, gshift, bshift, rbits, gbits, bbits; + +#ifdef DEBUG_DRAWCANVAS + char buffer[128]; +#endif + + if ((tkwin = canvasPtr->tkwin) == NULL) { + Tcl_AppendResult(interp, "canvas tkwin is NULL!", NULL); + result = TCL_ERROR; + goto done; + } + + /* + * If this canvas is unmapped, then we won't have a window id, so we will + * try the ancestors of the canvas until we find a window that has a + * valid window id. The Tk_GetPixmap() call requires a valid window id. + */ + + do { + + if ((displayPtr = Tk_Display(tkwin)) == NULL) { + Tcl_AppendResult(interp, "canvas (or parent) display is NULL!", NULL); + result = TCL_ERROR; + goto done; + } + + if ((wid = Tk_WindowId(tkwin)) != 0) { + continue; + } + + if ((tkwin = Tk_Parent(tkwin)) == NULL) { + Tcl_AppendResult(interp, "canvas has no parent with a valid window id! Is the toplevel window mapped?", NULL); + result = TCL_ERROR; + goto done; + } + + } while (wid == 0); + + bitsPerPixel = Tk_Depth(tkwin); + visualPtr = Tk_Visual(tkwin); + + if (subsample == 0) { + Tcl_AppendResult(interp, "subsample cannot be zero", NULL); + result = TCL_ERROR; + goto done; + } + + /* + * Scan through the item list, registering the bounding box for all items + * that didn't do that for the final coordinates yet. This can be + * determined by the FORCE_REDRAW flag. + */ + + for (itemPtr = canvasPtr -> firstItemPtr; itemPtr != NULL; + itemPtr = itemPtr -> nextPtr) { + if (itemPtr -> redraw_flags & FORCE_REDRAW) { + itemPtr -> redraw_flags &= ~FORCE_REDRAW; + EventuallyRedrawItem(canvasPtr, itemPtr); + itemPtr -> redraw_flags &= ~FORCE_REDRAW; + } + } + + /* + * The DisplayCanvas() function works out the region that needs redrawing, + * but we don't do this. We grab the whole scrollregion or canvas window + * area. If we have a defined -scrollregion we use that as the drawing + * region, otherwise use the canvas window height and width with an origin + * of 0,0. + */ + if (canvasPtr->scrollX1 != 0 || canvasPtr->scrollY1 != 0 || + canvasPtr->scrollX2 != 0 || canvasPtr->scrollY2 != 0) { + + canvasX1 = canvasPtr->scrollX1; + canvasY1 = canvasPtr->scrollY1; + canvasX2 = canvasPtr->scrollX2; + canvasY2 = canvasPtr->scrollY2; + cWidth = canvasX2 - canvasX1 + 1; + cHeight = canvasY2 - canvasY1 + 1; + + } else { + + cWidth = Tk_Width(tkwin); + cHeight = Tk_Height(tkwin); + canvasX1 = 0; + canvasY1 = 0; + canvasX2 = canvasX1 + cWidth - 1; + canvasY2 = canvasY1 + cHeight - 1; + } + + /* + * Allocate a pixmap to draw into. We add OVERDRAW_PIXELS in the same way + * that DisplayCanvas() does to avoid problems on some systems when objects + * are being drawn too close to the edge. + */ + + pixmapX1 = canvasX1 - OVERDRAW_PIXELS; + pixmapY1 = canvasY1 - OVERDRAW_PIXELS; + pixmapX2 = canvasX2 + OVERDRAW_PIXELS; + pixmapY2 = canvasY2 + OVERDRAW_PIXELS; + pmWidth = pixmapX2 - pixmapX1 + 1; + pmHeight = pixmapY2 - pixmapY1 + 1; + if ((pixmap = Tk_GetPixmap(displayPtr, Tk_WindowId(tkwin), pmWidth, pmHeight, + bitsPerPixel)) == 0) { + Tcl_AppendResult(interp, "failed to create drawing Pixmap", NULL); + result = TCL_ERROR; + goto done; + } + + /* + * Before we can draw the canvas objects into the pixmap it's background + * should be filled with canvas background colour. + */ + + xgcValues.function = GXcopy; + xgcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel; + xgc = XCreateGC(displayPtr, pixmap, GCFunction|GCForeground, &xgcValues); + XFillRectangle(displayPtr,pixmap,xgc,0,0,pmWidth,pmHeight); + + /* + * Draw all the cavas items into the pixmap + */ + + canvasPtr->drawableXOrigin = pixmapX1; + canvasPtr->drawableYOrigin = pixmapY1; + for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; + itemPtr = itemPtr->nextPtr) { + if ((itemPtr->x1 >= pixmapX2) || (itemPtr->y1 >= pixmapY2) || + (itemPtr->x2 < pixmapX1) || (itemPtr->y2 < pixmapY1)) { + if (!AlwaysRedraw(itemPtr)) { + continue; + } + } + if (itemPtr->state == TK_STATE_HIDDEN || + (itemPtr->state == TK_STATE_NULL && canvasPtr->canvas_state + == TK_STATE_HIDDEN)) { + continue; + } + ItemDisplay(canvasPtr, itemPtr, pixmap, pixmapX1, pixmapY1, pmWidth, + pmHeight); + } + + /* + * Copy the Pixmap into an ZPixmap format XImage so we can copy it across + * to the photo image. This seems to be the only way to get Pixmap image + * data out of an image. Note we have to account for the OVERDRAW_PIXELS + * border width. + */ + + if ((ximagePtr = XGetImage(displayPtr, pixmap, -pixmapX1, -pixmapY1, cWidth, + cHeight, AllPlanes, ZPixmap)) == NULL) { + Tcl_AppendResult(interp, "failed to copy Pixmap to XImage", NULL); + result = TCL_ERROR; + goto done; + } + +#ifdef DEBUG_DRAWCANVAS + Tcl_AppendResult(interp, "ximagePtr {", NULL); + sprintf(buffer,"%d",ximagePtr->width); Tcl_AppendResult(interp, " width ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->height); Tcl_AppendResult(interp, " height ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->xoffset); Tcl_AppendResult(interp, " xoffset ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->format); Tcl_AppendResult(interp, " format ", buffer, NULL); + Tcl_AppendResult(interp, " ximagePtr->data", NULL); + if (ximagePtr->data != NULL) { + int ix, iy; + + Tcl_AppendResult(interp, " {", NULL); + for (iy = 0; iy < ximagePtr->height; ++ iy) { + Tcl_AppendResult(interp, " {", NULL); + for (ix = 0; ix < ximagePtr->bytes_per_line; ++ ix) { + if (ix > 0) { + if (ix % 4 == 0) + Tcl_AppendResult(interp, "-", NULL); + else + Tcl_AppendResult(interp, " ", NULL); + } + sprintf(buffer,"%2.2x",ximagePtr->data[ximagePtr->bytes_per_line * iy + ix]&0xFF); + Tcl_AppendResult(interp, buffer, NULL); + } + Tcl_AppendResult(interp, " }", NULL); + } + Tcl_AppendResult(interp, " }", NULL); + } else + sprintf(buffer," NULL"); + sprintf(buffer,"%d",ximagePtr->byte_order); Tcl_AppendResult(interp, " byte_order ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->bitmap_unit); Tcl_AppendResult(interp, " bitmap_unit ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->bitmap_bit_order); Tcl_AppendResult(interp, " bitmap_bit_order ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->bitmap_pad); Tcl_AppendResult(interp, " bitmap_pad ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->depth); Tcl_AppendResult(interp, " depth ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->bytes_per_line); Tcl_AppendResult(interp, " bytes_per_line ", buffer, NULL); + sprintf(buffer,"%d",ximagePtr->bits_per_pixel); Tcl_AppendResult(interp, " bits_per_pixel ", buffer, NULL); + sprintf(buffer,"0x%8.8lx",ximagePtr->red_mask); Tcl_AppendResult(interp, " red_mask ", buffer, NULL); + sprintf(buffer,"0x%8.8lx",ximagePtr->green_mask); Tcl_AppendResult(interp, " green_mask ", buffer, NULL); + sprintf(buffer,"0x%8.8lx",ximagePtr->blue_mask); Tcl_AppendResult(interp, " blue_mask ", buffer, NULL); + Tcl_AppendResult(interp, " }", NULL); + + Tcl_AppendResult(interp, "\nvisualPtr {", NULL); + sprintf(buffer,"0x%8.8lx",visualPtr->red_mask); Tcl_AppendResult(interp, " red_mask ", buffer, NULL); + sprintf(buffer,"0x%8.8lx",visualPtr->green_mask); Tcl_AppendResult(interp, " green_mask ", buffer, NULL); + sprintf(buffer,"0x%8.8lx",visualPtr->blue_mask); Tcl_AppendResult(interp, " blue_mask ", buffer, NULL); + Tcl_AppendResult(interp, " }", NULL); + +#endif + + /* + * Fill in the PhotoImageBlock structure abd allocate a block of memory + * for the converted image data. Note we allocate an alpha channel even + * though we don't use one, because this layout helps Tk_PhotoPutBlock() + * use memcpy() instead of the slow pixel or line copy. + */ + + blockPtr.width = cWidth; + blockPtr.height = cHeight; + blockPtr.pixelSize = 4; + blockPtr.pitch = blockPtr.pixelSize * blockPtr.width; + blockPtr.offset[0] = 0; + blockPtr.offset[1] = 1; + blockPtr.offset[2] = 2; + blockPtr.offset[3] = 3; + blockPtr.pixelPtr = ckalloc(blockPtr.pixelSize * blockPtr.height * blockPtr.width); + + /* + * Now convert the image data pixel by pixel from XImage to 32bit RGBA + * format suitable for Tk_PhotoPutBlock(). + */ + + DecomposeMaskToShiftAndBits(visualPtr->red_mask,&rshift,&rbits); + DecomposeMaskToShiftAndBits(visualPtr->green_mask,&gshift,&gbits); + DecomposeMaskToShiftAndBits(visualPtr->blue_mask,&bshift,&bbits); + +#ifdef DEBUG_DRAWCANVAS + sprintf(buffer,"%d",rshift); Tcl_AppendResult(interp, "\nbits { rshift ", buffer, NULL); + sprintf(buffer,"%d",gshift); Tcl_AppendResult(interp, " gshift ", buffer, NULL); + sprintf(buffer,"%d",bshift); Tcl_AppendResult(interp, " bshift ", buffer, NULL); + sprintf(buffer,"%d",rbits); Tcl_AppendResult(interp, " rbits ", buffer, NULL); + sprintf(buffer,"%d",gbits); Tcl_AppendResult(interp, " gbits ", buffer, NULL); + sprintf(buffer,"%d",bbits); Tcl_AppendResult(interp, " bbits ", buffer, " }", NULL); + Tcl_AppendResult(interp, "\nConverted_image {", NULL); +#endif + + /* Ok, had to use ximagePtr->bits_per_pixel here and in the switch (...) + * below to get this to work on Windows. X11 correctly sets the bitmap + *_pad and bitmap_unit fields to 32, but on Windows they are 0 and 8 + * respectively! + */ + + bytesPerPixel = ximagePtr->bits_per_pixel/8; + for (y = 0; y < blockPtr.height; ++y) { + +#ifdef DEBUG_DRAWCANVAS + Tcl_AppendResult(interp, " {", NULL); +#endif + + for(x = 0; x < blockPtr.width; ++x) { + unsigned long pixel = 0; + + switch (ximagePtr->bits_per_pixel) { + + /* + * Get an 8 bit pixel from the XImage. + */ + + case 8 : + pixel = *((unsigned char *)(ximagePtr->data + bytesPerPixel * x + + ximagePtr->bytes_per_line * y)); + break; + + /* + * Get a 16 bit pixel from the XImage, and correct the + * byte order as necessary. + */ + + case 16 : + pixel = *((unsigned short *)(ximagePtr->data + bytesPerPixel * x + + ximagePtr->bytes_per_line * y)); + if ((IS_BIG_ENDIAN && ximagePtr->byte_order == LSBFirst) + || (!IS_BIG_ENDIAN && ximagePtr->byte_order == MSBFirst)) + pixel = BYTE_SWAP16(pixel); + break; + + /* + * Grab a 32 bit pixel from the XImage, and correct the + * byte order as necessary. + */ + + case 32 : + pixel = *((unsigned long *)(ximagePtr->data + bytesPerPixel * x + + ximagePtr->bytes_per_line * y)); + if ((IS_BIG_ENDIAN && ximagePtr->byte_order == LSBFirst) + || (!IS_BIG_ENDIAN && ximagePtr->byte_order == MSBFirst)) + pixel = BYTE_SWAP32(pixel); + break; + } + + /* + * We have a pixel with the correct byte order, so pull out the + * colours and place them in the photo block. Perhaps we could + * just not bother with the alpha byte because we are using + * TK_PHOTO_COMPOSITE_SET later? + * ***Windows: We have to swap the red and blue values. The + * XImage storage is B - G - R - A which becomes a 32bit ARGB + * quad. However the visual mask is a 32bit ABGR quad. And + * Tk_PhotoPutBlock() wants R-G-B-A which is a 32bit ABGR quad. + * If the visual mask was correct there would be no need to + * swap anything here. + */ + +#ifdef _WIN32 +#define R_OFFSET 2 +#define B_OFFSET 0 +#else +#define R_OFFSET 0 +#define B_OFFSET 2 +#endif + blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x + R_OFFSET] = + (unsigned char)((pixel & visualPtr->red_mask) >> rshift); + blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x +1] = + (unsigned char)((pixel & visualPtr->green_mask) >> gshift); + blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x + B_OFFSET] = + (unsigned char)((pixel & visualPtr->blue_mask) >> bshift); + blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x +3] = 0xFF; + +#ifdef DEBUG_DRAWCANVAS + { + int ix; + if (x > 0) + Tcl_AppendResult(interp, "-", NULL); + for (ix = 0; ix < 4; ++ix) { + if (ix > 0) + Tcl_AppendResult(interp, " ", NULL); + sprintf(buffer,"%2.2x",blockPtr.pixelPtr[blockPtr.pitch * y + + blockPtr.pixelSize * x + ix]&0xFF); + Tcl_AppendResult(interp, buffer, NULL); + } + } +#endif + + } + +#ifdef DEBUG_DRAWCANVAS + Tcl_AppendResult(interp, " }", NULL); +#endif + + } + +#ifdef DEBUG_DRAWCANVAS + Tcl_AppendResult(interp, " }", NULL); +#endif + + /* + * Now put the copied pixmap into the photo. + * If either zoom or subsample are not 1, we use the zoom function. + */ + + if (subsample != 1 || zoom != 1) { + if ((result = Tk_PhotoPutZoomedBlock(interp, photohandle, &blockPtr, + 0, 0, cWidth * zoom / subsample, cHeight * zoom / subsample, + zoom, zoom, subsample, subsample, TK_PHOTO_COMPOSITE_SET)) + != TCL_OK) { + goto done; + } + } else { + if ((result = Tk_PhotoPutBlock(interp, photohandle, &blockPtr, 0, 0, + cWidth, cHeight, TK_PHOTO_COMPOSITE_SET)) != TCL_OK) { + goto done; + } + } + + /* + * Clean up anything we have allocated and exit. + */ + +done: + if (blockPtr.pixelPtr) + ckfree(blockPtr.pixelPtr); + if (pixmap) + Tk_FreePixmap(Tk_Display(tkwin), pixmap); + if (ximagePtr) + XDestroyImage(ximagePtr); + if (xgc) + XFreeGC(displayPtr,xgc); + return result; +} + /* *---------------------------------------------------------------------- * * DisplayCanvas -- * @@ -3048,212 +3608,10 @@ tkArcType.nextPtr = &tkWindowType; tkWindowType.nextPtr = NULL; Tcl_MutexUnlock(&typeListMutex); } -#ifdef USE_OLD_TAG_SEARCH -/* - *-------------------------------------------------------------- - * - * StartTagSearch -- - * - * This function is called to initiate an enumeration of all items in a - * given canvas that contain a given tag. - * - * Results: - * The return value is a pointer to the first item in canvasPtr that - * matches tag, or NULL if there is no such item. The information at - * *searchPtr is initialized such that successive calls to NextItem will - * return successive items that match tag. - * - * Side effects: - * SearchPtr is linked into a list of searches in progress on canvasPtr, - * so that elements can safely be deleted while the search is in - * progress. EndTagSearch must be called at the end of the search to - * unlink searchPtr from this list. - * - *-------------------------------------------------------------- - */ - -static Tk_Item * -StartTagSearch( - TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */ - Tcl_Obj *tagObj, /* Object giving tag value. */ - TagSearch *searchPtr) /* Record describing tag search; will be - * initialized here. */ -{ - int id; - Tk_Item *itemPtr, *lastPtr; - Tk_Uid *tagPtr; - Tk_Uid uid; - char *tag = Tcl_GetString(tagObj); - int count; - TkWindow *tkwin = (TkWindow *) canvasPtr->tkwin; - TkDisplay *dispPtr = tkwin->dispPtr; - - /* - * Initialize the search. - */ - - searchPtr->canvasPtr = canvasPtr; - searchPtr->searchOver = 0; - - /* - * Find the first matching item in one of several ways. If the tag is a - * number then it selects the single item with the matching identifier. - * In this case see if the item being requested is the hot item, in which - * case the search can be skipped. - */ - - if (isdigit(UCHAR(*tag))) { - char *end; - Tcl_HashEntry *entryPtr; - - dispPtr->numIdSearches++; - id = strtoul(tag, &end, 0); - if (*end == 0) { - itemPtr = canvasPtr->hotPtr; - lastPtr = canvasPtr->hotPrevPtr; - if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL) - || (lastPtr->nextPtr != itemPtr)) { - dispPtr->numSlowSearches++; - entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char*) id); - if (entryPtr != NULL) { - itemPtr = Tcl_GetHashValue(entryPtr); - lastPtr = itemPtr->prevPtr; - } else { - lastPtr = itemPtr = NULL; - } - } - searchPtr->lastPtr = lastPtr; - searchPtr->searchOver = 1; - canvasPtr->hotPtr = itemPtr; - canvasPtr->hotPrevPtr = lastPtr; - return itemPtr; - } - } - - searchPtr->tag = uid = Tk_GetUid(tag); - if (uid == Tk_GetUid("all")) { - /* - * All items match. - */ - - searchPtr->tag = NULL; - searchPtr->lastPtr = NULL; - searchPtr->currentPtr = canvasPtr->firstItemPtr; - return canvasPtr->firstItemPtr; - } - - /* - * None of the above. Search for an item with a matching tag. - */ - - for (lastPtr = NULL, itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; - lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { - for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; - count > 0; tagPtr++, count--) { - if (*tagPtr == uid) { - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; - } - } - } - searchPtr->lastPtr = lastPtr; - searchPtr->searchOver = 1; - return NULL; -} - -/* - *-------------------------------------------------------------- - * - * NextItem -- - * - * This function returns successive items that match a given tag; it - * should be called only after StartTagSearch has been used to begin a - * search. - * - * Results: - * The return value is a pointer to the next item that matches the tag - * specified to StartTagSearch, or NULL if no such item exists. - * *SearchPtr is updated so that the next call to this function will - * return the next item. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ - -static Tk_Item * -NextItem( - TagSearch *searchPtr) /* Record describing search in progress. */ -{ - Tk_Item *itemPtr, *lastPtr; - int count; - Tk_Uid uid; - Tk_Uid *tagPtr; - - /* - * Find next item in list (this may not actually be a suitable one to - * return), and return if there are no items left. - */ - - lastPtr = searchPtr->lastPtr; - if (lastPtr == NULL) { - itemPtr = searchPtr->canvasPtr->firstItemPtr; - } else { - itemPtr = lastPtr->nextPtr; - } - if ((itemPtr == NULL) || (searchPtr->searchOver)) { - searchPtr->searchOver = 1; - return NULL; - } - if (itemPtr != searchPtr->currentPtr) { - /* - * The structure of the list has changed. Probably the previously- - * returned item was removed from the list. In this case, don't - * advance lastPtr; just return its new successor (i.e. do nothing - * here). - */ - } else { - lastPtr = itemPtr; - itemPtr = lastPtr->nextPtr; - } - - /* - * Handle special case of "all" search by returning next item. - */ - - uid = searchPtr->tag; - if (uid == NULL) { - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; - } - - /* - * Look for an item with a particular tag. - */ - - for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { - for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; - count > 0; tagPtr++, count--) { - if (*tagPtr == uid) { - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; - } - } - } - searchPtr->lastPtr = lastPtr; - searchPtr->searchOver = 1; - return NULL; -} - -#else /* !USE_OLD_TAG_SEARCH */ /* *---------------------------------------------------------------------- * * GetStaticUids -- * @@ -4013,11 +4371,11 @@ itemPtr = searchPtr->canvasPtr->hotPtr; lastPtr = searchPtr->canvasPtr->hotPrevPtr; if ((itemPtr == NULL) || (itemPtr->id != searchPtr->id) || (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) { entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable, - (char *) INT2PTR(searchPtr->id)); + INT2PTR(searchPtr->id)); if (entryPtr != NULL) { itemPtr = Tcl_GetHashValue(entryPtr); lastPtr = itemPtr->prevPtr; } else { lastPtr = itemPtr = NULL; @@ -4178,11 +4536,10 @@ } searchPtr->lastPtr = lastPtr; searchPtr->searchOver = 1; return NULL; } -#endif /* USE_OLD_TAG_SEARCH */ /* *-------------------------------------------------------------- * * DoItem -- @@ -4215,11 +4572,11 @@ /* * Handle the "add-to-result" case and return, if appropriate. */ if (tag == NULL) { - Tcl_ListObjAppendElement(NULL, accumObj, Tcl_NewIntObj(itemPtr->id)); + Tcl_ListObjAppendElement(NULL, accumObj, Tcl_NewWideIntObj(itemPtr->id)); return; } for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; count > 0; tagPtr++, count--) { @@ -4291,18 +4648,13 @@ * items are returned in the interp's * result. */ int first /* For error messages: gives number of * elements of objv which are already * handled. */ -#ifndef USE_OLD_TAG_SEARCH ,TagSearch **searchPtrPtr /* From CanvasWidgetCmd local vars*/ -#endif /* not USE_OLD_TAG_SEARCH */ ) { -#ifdef USE_OLD_TAG_SEARCH - TagSearch search; -#endif /* USE_OLD_TAG_SEARCH */ Tk_Item *itemPtr; Tk_Uid uid; int index, result; Tcl_Obj *resultObj; static const char *const optionStrings[] = { @@ -4615,35 +4967,21 @@ * moved items relative to each other is not changed. * *-------------------------------------------------------------- */ -#ifdef USE_OLD_TAG_SEARCH -static void -RelinkItems( - TkCanvas *canvasPtr, /* Canvas to be modified. */ - Tcl_Obj *tag, /* Tag identifying items to be moved in the - * redisplay list. */ - Tk_Item *prevPtr) /* Reposition the items so that they go just - * after this item (NULL means put at - * beginning of list). */ -#else /* USE_OLD_TAG_SEARCH */ static int RelinkItems( TkCanvas *canvasPtr, /* Canvas to be modified. */ Tcl_Obj *tag, /* Tag identifying items to be moved in the * redisplay list. */ Tk_Item *prevPtr, /* Reposition the items so that they go just * after this item (NULL means put at * beginning of list). */ TagSearch **searchPtrPtr) /* From CanvasWidgetCmd local vars */ -#endif /* USE_OLD_TAG_SEARCH */ { Tk_Item *itemPtr; -#ifdef USE_OLD_TAG_SEARCH - TagSearch search; -#endif /* USE_OLD_TAG_SEARCH */ Tk_Item *firstMovePtr, *lastMovePtr; int result; /* * Find all of the items to be moved and remove them from the list, making @@ -4691,15 +5029,11 @@ * Insert the list of to-be-moved items back into the canvas's at the * desired position. */ if (firstMovePtr == NULL) { -#ifdef USE_OLD_TAG_SEARCH - return; -#else /* USE_OLD_TAG_SEARCH */ return TCL_OK; -#endif /* USE_OLD_TAG_SEARCH */ } if (prevPtr == NULL) { if (canvasPtr->firstItemPtr != NULL) { canvasPtr->firstItemPtr->prevPtr = lastMovePtr; } @@ -4716,13 +5050,11 @@ prevPtr->nextPtr = firstMovePtr; } if (canvasPtr->lastItemPtr == prevPtr) { canvasPtr->lastItemPtr = lastMovePtr; } -#ifndef USE_OLD_TAG_SEARCH return TCL_OK; -#endif /* not USE_OLD_TAG_SEARCH */ } /* *-------------------------------------------------------------- * @@ -4758,30 +5090,11 @@ */ switch (eventPtr->type) { case ButtonPress: case ButtonRelease: - switch (eventPtr->xbutton.button) { - case Button1: - mask = Button1Mask; - break; - case Button2: - mask = Button2Mask; - break; - case Button3: - mask = Button3Mask; - break; - case Button4: - mask = Button4Mask; - break; - case Button5: - mask = Button5Mask; - break; - default: - mask = 0; - break; - } + mask = TkGetButtonMask(eventPtr->xbutton.button); /* * For button press events, repick the current item using the button * state before the event, then process the event. For button release * events, first process the event, then repick the current item using @@ -4860,25 +5173,22 @@ XEvent *eventPtr) /* Event describing location of mouse cursor. * Must be EnterWindow, LeaveWindow, * ButtonRelease, or MotionNotify. */ { double coords[2]; - int buttonDown; + unsigned long buttonDown; Tk_Item *prevItemPtr; -#ifndef USE_OLD_TAG_SEARCH SearchUids *searchUids = GetStaticUids(); -#endif /* * Check whether or not a button is down. If so, we'll log entry and exit * into and out of the current item, but not entry into any other item. * This implements a form of grabbing equivalent to what the X server does * for windows. */ - buttonDown = canvasPtr->state - & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask); + buttonDown = canvasPtr->state & ALL_BUTTONS; /* * Save information about this event in the canvas. The event in the * canvas is used for two purposes: * @@ -4987,15 +5297,11 @@ * for that deletes the current item. */ if ((itemPtr == canvasPtr->currentItemPtr) && !buttonDown) { for (i = itemPtr->numTags-1; i >= 0; i--) { -#ifdef USE_OLD_TAG_SEARCH - if (itemPtr->tagPtr[i] == Tk_GetUid("current")) -#else /* USE_OLD_TAG_SEARCH */ if (itemPtr->tagPtr[i] == searchUids->currentUid) -#endif /* USE_OLD_TAG_SEARCH */ /* then */ { itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1]; itemPtr->numTags--; break; } @@ -5028,15 +5334,11 @@ ItemConfigure(canvasPtr, prevItemPtr, 0, NULL); } if (canvasPtr->currentItemPtr != NULL) { XEvent event; -#ifdef USE_OLD_TAG_SEARCH - DoItem(NULL, canvasPtr->currentItemPtr, Tk_GetUid("current")); -#else /* USE_OLD_TAG_SEARCH */ DoItem(NULL, canvasPtr->currentItemPtr, searchUids->currentUid); -#endif /* USE_OLD_TAG_SEARCH */ if ((canvasPtr->currentItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT && prevItemPtr != canvasPtr->currentItemPtr)) { ItemConfigure(canvasPtr, canvasPtr->currentItemPtr, 0, NULL); EventuallyRedrawItem(canvasPtr, canvasPtr->currentItemPtr); } @@ -5126,19 +5428,17 @@ TkCanvas *canvasPtr, /* Canvas widget in which event occurred. */ XEvent *eventPtr) /* Real or simulated X event that is to be * processed. */ { #define NUM_STATIC 3 - ClientData staticObjects[NUM_STATIC]; - ClientData *objectPtr; + void *staticObjects[NUM_STATIC]; + void **objectPtr; int numObjects, i; Tk_Item *itemPtr; -#ifndef USE_OLD_TAG_SEARCH TagSearchExpr *expr; int numExprs; SearchUids *searchUids = GetStaticUids(); -#endif /* not USE_OLD_TAG_SEARCH */ if (canvasPtr->bindingTable == NULL) { return; } @@ -5148,20 +5448,10 @@ } if (itemPtr == NULL) { return; } -#ifdef USE_OLD_TAG_SEARCH - /* - * Set up an array with all the relevant objects for processing this - * event. The relevant objects are (a) the event's item, (b) the tags - * associated with the event's item, and (c) the tag "all". If there are a - * lot of tags then malloc an array to hold all of the objects. - */ - - numObjects = itemPtr->numTags + 2; -#else /* USE_OLD_TAG_SEARCH */ /* * Set up an array with all the relevant objects for processing this * event. The relevant objects are: * (a) the event's item, * (b) the tags associated with the event's item, @@ -5186,27 +5476,21 @@ } expr = expr->next; } numObjects = itemPtr->numTags + numExprs + 2; -#endif /* not USE_OLD_TAG_SEARCH */ if (numObjects <= NUM_STATIC) { objectPtr = staticObjects; } else { - objectPtr = ckalloc(numObjects * sizeof(ClientData)); + objectPtr = ckalloc(numObjects * sizeof(void *)); } -#ifdef USE_OLD_TAG_SEARCH - objectPtr[0] = (ClientData) Tk_GetUid("all"); -#else /* USE_OLD_TAG_SEARCH */ - objectPtr[0] = (ClientData) searchUids->allUid; -#endif /* USE_OLD_TAG_SEARCH */ + objectPtr[0] = (char *)searchUids->allUid; for (i = itemPtr->numTags-1; i >= 0; i--) { - objectPtr[i+1] = (ClientData) itemPtr->tagPtr[i]; + objectPtr[i+1] = (char *)itemPtr->tagPtr[i]; } objectPtr[itemPtr->numTags+1] = itemPtr; -#ifndef USE_OLD_TAG_SEARCH /* * Copy uids of matching expressions into object array */ i = itemPtr->numTags+2; @@ -5215,11 +5499,10 @@ if (expr->match) { objectPtr[i++] = (int *) expr->uid; } expr = expr->next; } -#endif /* not USE_OLD_TAG_SEARCH */ /* * Invoke the binding system, then free up the object array if it was * malloc-ed. */ @@ -5305,11 +5588,11 @@ canvasPtr->insertOffTime, CanvasBlinkProc, canvasPtr); } } else { canvasPtr->textInfo.gotFocus = 0; canvasPtr->textInfo.cursorOn = 0; - canvasPtr->insertBlinkHandler = (Tcl_TimerToken) NULL; + canvasPtr->insertBlinkHandler = NULL; } EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr); if (canvasPtr->highlightWidth > 0) { canvasPtr->flags |= REDRAW_BORDERS; if (!(canvasPtr->flags & REDRAW_PENDING)) { Index: generic/tkCanvas.h ================================================================== --- generic/tkCanvas.h +++ generic/tkCanvas.h @@ -145,11 +145,11 @@ * if it is this close to it. */ XEvent pickEvent; /* The event upon which the current choice of * currentItem is based. Must be saved so that * if the currentItem is deleted, can pick * another. */ - int state; /* Last known modifier state. Used to defer + unsigned int state; /* Last known modifier state. Used to defer * picking a new current object while buttons * are down. */ /* * Information used for managing scrollbars: Index: generic/tkClipboard.c ================================================================== --- generic/tkClipboard.c +++ generic/tkClipboard.c @@ -420,11 +420,11 @@ ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { - Tk_Window tkwin = (Tk_Window) clientData; + Tk_Window tkwin = clientData; const char *path = NULL; Atom selection; static const char *const optionStrings[] = { "append", "clear", "get", NULL }; enum options { CLIPBOARD_APPEND, CLIPBOARD_CLEAR, CLIPBOARD_GET }; int index, i; @@ -447,14 +447,15 @@ const char *string; static const char *const appendOptionStrings[] = { "-displayof", "-format", "-type", NULL }; enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE }; - int subIndex, length; + int subIndex; + TkSizeT length; for (i = 2; i < objc - 1; i++) { - string = Tcl_GetStringFromObj(objv[i], &length); + string = TkGetStringFromObj(objv[i], &length); if (string[0] != '-') { break; } /* @@ -706,11 +707,11 @@ * selection. */ Tcl_Interp *interp, /* Interpreter used for error reporting (not * used). */ const char *portion) /* New information to be appended. */ { - Tcl_DStringAppend((Tcl_DString *) clientData, portion, -1); + Tcl_DStringAppend(clientData, portion, -1); return TCL_OK; } /* * Local Variables: Index: generic/tkCmds.c ================================================================== --- generic/tkCmds.c +++ generic/tkCmds.c @@ -744,19 +744,19 @@ objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("-height", 7)); Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewIntObj(caretPtr->height)); + Tcl_NewWideIntObj(caretPtr->height)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("-x", 2)); Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewIntObj(caretPtr->x)); + Tcl_NewWideIntObj(caretPtr->x)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("-y", 2)); Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewIntObj(caretPtr->y)); + Tcl_NewWideIntObj(caretPtr->y)); Tcl_SetObjResult(interp, objPtr); } else if (objc == 3) { int value; /* @@ -772,11 +772,11 @@ } else if (index == TK_CARET_Y) { value = caretPtr->y; } else /* if (index == TK_CARET_HEIGHT) -- last case */ { value = caretPtr->height; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(value)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value)); } else { int i, value, x = 0, y = 0, height = -1; for (i = 2; i < objc; i += 2) { if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings, @@ -940,15 +940,15 @@ if (skip < 0) { return TCL_ERROR; } if (objc - skip == 1) { - long inactive; + Tcl_WideInt inactive; inactive = (Tcl_IsSafe(interp) ? -1 : Tk_GetUserInactiveTime(Tk_Display(tkwin))); - Tcl_SetObjResult(interp, Tcl_NewLongObj(inactive)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(inactive)); } else if (objc - skip == 2) { const char *string; string = Tcl_GetString(objv[objc-1]); if (strcmp(string, "reset") != 0) { @@ -1361,11 +1361,11 @@ winPtr = (TkWindow *) tkwin; switch ((enum options) index) { case WIN_CELLS: Tcl_SetObjResult(interp, - Tcl_NewIntObj(Tk_Visual(tkwin)->map_entries)); + Tcl_NewWideIntObj(Tk_Visual(tkwin)->map_entries)); break; case WIN_CHILDREN: { Tcl_Obj *strPtr, *resultPtr = Tcl_NewObj(); winPtr = winPtr->childList; @@ -1384,18 +1384,18 @@ case WIN_COLORMAPFULL: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TkpCmapStressed(tkwin,Tk_Colormap(tkwin)))); break; case WIN_DEPTH: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Depth(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Depth(tkwin))); break; case WIN_GEOMETRY: Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d+%d+%d", Tk_Width(tkwin), Tk_Height(tkwin), Tk_X(tkwin), Tk_Y(tkwin))); break; case WIN_HEIGHT: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Height(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Height(tkwin))); break; case WIN_ID: { char buf[TCL_INTEGER_SPACE]; Tk_MakeWindowExist(tkwin); @@ -1442,60 +1442,60 @@ TkGetPointerCoords((Tk_Window) winPtr, &x, &y); } if (useX & useY) { Tcl_Obj *xyObj[2]; - xyObj[0] = Tcl_NewIntObj(x); - xyObj[1] = Tcl_NewIntObj(y); + xyObj[0] = Tcl_NewWideIntObj(x); + xyObj[1] = Tcl_NewWideIntObj(y); Tcl_SetObjResult(interp, Tcl_NewListObj(2, xyObj)); } else if (useX) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(x)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); } else { - Tcl_SetObjResult(interp, Tcl_NewIntObj(y)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y)); } break; case WIN_REQHEIGHT: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_ReqHeight(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_ReqHeight(tkwin))); break; case WIN_REQWIDTH: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_ReqWidth(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_ReqWidth(tkwin))); break; case WIN_ROOTX: Tk_GetRootCoords(tkwin, &x, &y); - Tcl_SetObjResult(interp, Tcl_NewIntObj(x)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); break; case WIN_ROOTY: Tk_GetRootCoords(tkwin, &x, &y); - Tcl_SetObjResult(interp, Tcl_NewIntObj(y)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y)); break; case WIN_SCREEN: Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s.%d", Tk_DisplayName(tkwin), Tk_ScreenNumber(tkwin))); break; case WIN_SCREENCELLS: Tcl_SetObjResult(interp, - Tcl_NewIntObj(CellsOfScreen(Tk_Screen(tkwin)))); + Tcl_NewWideIntObj(CellsOfScreen(Tk_Screen(tkwin)))); break; case WIN_SCREENDEPTH: Tcl_SetObjResult(interp, - Tcl_NewIntObj(DefaultDepthOfScreen(Tk_Screen(tkwin)))); + Tcl_NewWideIntObj(DefaultDepthOfScreen(Tk_Screen(tkwin)))); break; case WIN_SCREENHEIGHT: Tcl_SetObjResult(interp, - Tcl_NewIntObj(HeightOfScreen(Tk_Screen(tkwin)))); + Tcl_NewWideIntObj(HeightOfScreen(Tk_Screen(tkwin)))); break; case WIN_SCREENWIDTH: Tcl_SetObjResult(interp, - Tcl_NewIntObj(WidthOfScreen(Tk_Screen(tkwin)))); + Tcl_NewWideIntObj(WidthOfScreen(Tk_Screen(tkwin)))); break; case WIN_SCREENMMHEIGHT: Tcl_SetObjResult(interp, - Tcl_NewIntObj(HeightMMOfScreen(Tk_Screen(tkwin)))); + Tcl_NewWideIntObj(HeightMMOfScreen(Tk_Screen(tkwin)))); break; case WIN_SCREENMMWIDTH: Tcl_SetObjResult(interp, - Tcl_NewIntObj(WidthMMOfScreen(Tk_Screen(tkwin)))); + Tcl_NewWideIntObj(WidthMMOfScreen(Tk_Screen(tkwin)))); break; case WIN_SCREENVISUAL: class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class; goto visual; case WIN_SERVER: @@ -1537,32 +1537,32 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned) XVisualIDFromVisual(Tk_Visual(tkwin)))); break; case WIN_VROOTHEIGHT: Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetObjResult(interp, Tcl_NewIntObj(height)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(height)); break; case WIN_VROOTWIDTH: Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetObjResult(interp, Tcl_NewIntObj(width)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(width)); break; case WIN_VROOTX: Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetObjResult(interp, Tcl_NewIntObj(x)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); break; case WIN_VROOTY: Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetObjResult(interp, Tcl_NewIntObj(y)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y)); break; case WIN_WIDTH: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Width(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Width(tkwin))); break; case WIN_X: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_X(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_X(tkwin))); break; case WIN_Y: - Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Y(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Y(tkwin))); break; /* * Uses -displayof. */ @@ -1577,15 +1577,15 @@ return TCL_ERROR; } objv += skip; string = Tcl_GetString(objv[2]); Tcl_SetObjResult(interp, - Tcl_NewLongObj((long) Tk_InternAtom(tkwin, string))); + Tcl_NewWideIntObj(Tk_InternAtom(tkwin, string))); break; case WIN_ATOMNAME: { const char *name; - long id; + Tcl_WideInt id; skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); if (skip < 0) { return TCL_ERROR; } @@ -1592,11 +1592,11 @@ if (objc - skip != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id"); return TCL_ERROR; } objv += skip; - if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[2], &id) != TCL_OK) { return TCL_ERROR; } name = Tk_GetAtomName(tkwin, (Atom) id); if (strcmp(name, "?bad atom?") == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -1733,11 +1733,11 @@ } string = Tcl_GetString(objv[3]); if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) { return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(pixels)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pixels)); break; } case WIN_RGB: { XColor *colorPtr; @@ -1858,11 +1858,11 @@ TKWM_MINSIZE, TKWM_OVERRIDE, TKWM_POSFROM, TKWM_PROTOCOL, TKWM_RESIZABLE, TKWM_SIZEFROM, TKWM_STATE, TKWM_TITLE, TKWM_TRACING, TKWM_TRANSIENT, TKWM_WITHDRAW }; - tkwin = (Tk_Window) clientData; + tkwin = clientData; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg?"); return TCL_ERROR; } @@ -2069,18 +2069,18 @@ * option to "-displayof" argument, or * unmodified if "-displayof" argument was not * present. */ { const char *string; - int length; + TkSizeT length; if (objc < 1) { return 0; } - string = Tcl_GetStringFromObj(objv[0], &length); + string = TkGetStringFromObj(objv[0], &length); if ((length >= 2) && - (strncmp(string, "-displayof", (unsigned) length) == 0)) { + (strncmp(string, "-displayof", length) == 0)) { if (objc < 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "value for \"-displayof\" missing", -1)); Tcl_SetErrorCode(interp, "TK", "NO_VALUE", "DISPLAYOF", NULL); return -1; Index: generic/tkColor.c ================================================================== --- generic/tkColor.c +++ generic/tkColor.c @@ -29,11 +29,11 @@ /* * The structure below is used to allocate thread-local data. */ -typedef struct ThreadSpecificData { +typedef struct { char rgbString[20]; /* */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* @@ -478,12 +478,11 @@ if (tkColPtr->magic != COLOR_MAGIC) { Tcl_Panic("Tk_FreeColor called with bogus color"); } - tkColPtr->resourceRefCount--; - if (tkColPtr->resourceRefCount > 0) { + if (tkColPtr->resourceRefCount-- > 1) { return; } /* * This color is no longer being actively used, so free the color @@ -585,12 +584,11 @@ Tcl_Obj *objPtr) /* The object we are releasing. */ { TkColor *tkColPtr = objPtr->internalRep.twoPtrValue.ptr1; if (tkColPtr != NULL) { - tkColPtr->objRefCount--; - if ((tkColPtr->objRefCount == 0) + if ((tkColPtr->objRefCount-- <= 1) && (tkColPtr->resourceRefCount == 0)) { ckfree(tkColPtr); } objPtr->internalRep.twoPtrValue.ptr1 = NULL; } @@ -818,13 +816,13 @@ } for ( ; (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) { Tcl_Obj *objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(tkColPtr->resourceRefCount)); + Tcl_NewWideIntObj(tkColPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(tkColPtr->objRefCount)); + Tcl_NewWideIntObj(tkColPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } Index: generic/tkColor.h ================================================================== --- generic/tkColor.h +++ generic/tkColor.h @@ -36,21 +36,21 @@ Screen *screen; /* Screen where this color is valid. Used to * delete it, and to find its display. */ Colormap colormap; /* Colormap from which this entry was * allocated. */ Visual *visual; /* Visual associated with colormap. */ - int resourceRefCount; /* Number of active uses of this color (each + TkSizeT resourceRefCount; /* Number of active uses of this color (each * active use corresponds to a call to * Tk_AllocColorFromObj or Tk_GetColor). If * this count is 0, then this TkColor * structure is no longer valid and it isn't * present in a hash table: it is being kept * around only because there are objects * referring to it. The structure is freed * when resourceRefCount and objRefCount are * both 0. */ - int objRefCount; /* The number of Tcl objects that reference + TkSizeT objRefCount; /* The number of Tcl objects that reference * this structure. */ int type; /* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE. */ Tcl_HashEntry *hashPtr; /* Pointer to hash table entry for this * structure. (for use in deleting entry). */ struct TkColor *nextPtr; /* Points to the next TkColor structure with Index: generic/tkConfig.c ================================================================== --- generic/tkConfig.c +++ generic/tkConfig.c @@ -29,11 +29,11 @@ /* * The following definition keeps track of all of * the option tables that have been created for a thread. */ -typedef struct ThreadSpecificData { +typedef struct { int initialized; /* 0 means table below needs initializing. */ Tcl_HashTable hashTable; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -89,11 +89,11 @@ * One of the following exists for each Tk_OptionSpec array that has been * passed to Tk_CreateOptionTable. */ typedef struct OptionTable { - int refCount; /* Counts the number of uses of this table + size_t refCount; /* Counts the number of uses of this table * (the number of times Tk_CreateOptionTable * has returned it). This can be greater than * 1 if it is shared along several option * table chains, or if the same table is used * for multiple purposes. */ @@ -101,11 +101,11 @@ * used to delete the entry. */ struct OptionTable *nextPtr;/* If templatePtr was part of a chain of * templates, this points to the table * corresponding to the next template in the * chain. */ - int numOptions; /* The number of items in the options array + size_t numOptions; /* The number of items in the options array * below. */ Option options[1]; /* Information about the individual options in * the table. This must be the last field in * the structure: the actual size of the array * will be numOptions, not 1. */ @@ -113,18 +113,18 @@ /* * Forward declarations for functions defined later in this file: */ -static int DoObjConfig(Tcl_Interp *interp, char *recordPtr, +static int DoObjConfig(Tcl_Interp *interp, void *recordPtr, Option *optionPtr, Tcl_Obj *valuePtr, Tk_Window tkwin, Tk_SavedOption *savePtr); static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr, - char *internalPtr, Tk_Window tkwin); -static Tcl_Obj * GetConfigList(char *recordPtr, + void *internalPtr, Tk_Window tkwin); +static Tcl_Obj * GetConfigList(void *recordPtr, Option *optionPtr, Tk_Window tkwin); -static Tcl_Obj * GetObjectForOption(char *recordPtr, +static Tcl_Obj * GetObjectForOption(void *recordPtr, Option *optionPtr, Tk_Window tkwin); static Option * GetOption(const char *name, OptionTable *tablePtr); static Option * GetOptionFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, OptionTable *tablePtr); static int ObjectIsEmpty(Tcl_Obj *objPtr); @@ -175,11 +175,11 @@ Tcl_HashEntry *hashEntryPtr; int newEntry; OptionTable *tablePtr; const Tk_OptionSpec *specPtr, *specPtr2; Option *optionPtr; - int numOptions, i; + size_t numOptions, i; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * We use an TSD in the thread to keep a hash table of @@ -277,11 +277,11 @@ optionPtr->extra.custom = specPtr->clientData; } } if (((specPtr->type == TK_OPTION_STRING) - && (specPtr->internalOffset >= 0)) + && (specPtr->internalOffset != TCL_AUTO_LENGTH)) || (specPtr->type == TK_OPTION_COLOR) || (specPtr->type == TK_OPTION_FONT) || (specPtr->type == TK_OPTION_BITMAP) || (specPtr->type == TK_OPTION_BORDER) || (specPtr->type == TK_OPTION_CURSOR) @@ -328,14 +328,13 @@ Tk_DeleteOptionTable( Tk_OptionTable optionTable) /* The option table to delete. */ { OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; - int count; + size_t count; - tablePtr->refCount--; - if (tablePtr->refCount > 0) { + if (tablePtr->refCount-- > 1) { return; } if (tablePtr->nextPtr != NULL) { Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr); @@ -380,11 +379,11 @@ int Tk_InitOptions( Tcl_Interp *interp, /* Interpreter for error reporting. NULL means * don't leave an error message. */ - char *recordPtr, /* Pointer to the record to configure. Note: + void *recordPtr, /* Pointer to the record to configure. Note: * the caller should have properly initialized * the record with NULL pointers for each * option value. */ Tk_OptionTable optionTable, /* The token which matches the config specs * for the widget in question. */ @@ -551,11 +550,11 @@ static int DoObjConfig( Tcl_Interp *interp, /* Interpreter for error reporting. If NULL, * then no message is left if an error * occurs. */ - char *recordPtr, /* The record to modify to hold the new option + void *recordPtr, /* The record to modify to hold the new option * value. */ Option *optionPtr, /* Pointer to information about the option. */ Tcl_Obj *valuePtr, /* New value for option. */ Tk_Window tkwin, /* Window in which option will be used (needed * to allocate resources for some options). @@ -567,14 +566,14 @@ * be stored here, and it becomes the property * of the caller (the caller must eventually * free the old value). */ { Tcl_Obj **slotPtrPtr, *oldPtr; - char *internalPtr; /* Points to location in record where internal + void *internalPtr; /* Points to location in record where internal * representation of value should be stored, * or NULL. */ - char *oldInternalPtr; /* Points to location in which to save old + void *oldInternalPtr; /* Points to location in which to save old * internal representation of value. */ Tk_SavedOption internal; /* Used to save the old internal * representation of the value if * savedOptionPtr is NULL. */ const Tk_OptionSpec *specPtr; @@ -583,12 +582,12 @@ /* * Save the old object form for the value, if there is one. */ specPtr = optionPtr->specPtr; - if (specPtr->objOffset >= 0) { - slotPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset); + if (specPtr->objOffset != TCL_AUTO_LENGTH) { + slotPtrPtr = (Tcl_Obj **) ((char *)recordPtr + specPtr->objOffset); oldPtr = *slotPtrPtr; } else { slotPtrPtr = NULL; oldPtr = NULL; } @@ -596,12 +595,12 @@ /* * Apply the new value in a type-specific way. Also remember the old * object and internal forms, if they exist. */ - if (specPtr->internalOffset >= 0) { - internalPtr = recordPtr + specPtr->internalOffset; + if (specPtr->internalOffset != TCL_AUTO_LENGTH) { + internalPtr = (char *)recordPtr + specPtr->internalOffset; } else { internalPtr = NULL; } if (savedOptionPtr != NULL) { savedOptionPtr->optionPtr = optionPtr; @@ -655,18 +654,18 @@ break; } case TK_OPTION_STRING: { char *newStr; const char *value; - int length; + TkSizeT length; if (nullOK && ObjectIsEmpty(valuePtr)) { valuePtr = NULL; } if (internalPtr != NULL) { if (valuePtr != NULL) { - value = Tcl_GetStringFromObj(valuePtr, &length); + value = TkGetStringFromObj(valuePtr, &length); newStr = ckalloc(length + 1); strcpy(newStr, value); } else { newStr = NULL; } @@ -973,11 +972,11 @@ OptionTable *tablePtr) /* Table in which to look up name. */ { Option *bestPtr, *optionPtr; OptionTable *tablePtr2; const char *p1, *p2; - int count; + size_t count; /* * Search through all of the option tables in the chain to find the best * match. Some tricky aspects: * @@ -1221,11 +1220,11 @@ int Tk_SetOptions( Tcl_Interp *interp, /* Interpreter for error reporting. If NULL, * then no error message is returned.*/ - char *recordPtr, /* The record to configure. */ + void *recordPtr, /* The record to configure. */ Tk_OptionTable optionTable, /* Describes valid options. */ int objc, /* The number of elements in objv. */ Tcl_Obj *const objv[], /* Contains one or more name-value pairs. */ Tk_Window tkwin, /* Window associated with the thing being * configured; needed for some options (such @@ -1339,16 +1338,16 @@ void Tk_RestoreSavedOptions( Tk_SavedOptions *savePtr) /* Holds saved option information; must have * been passed to Tk_SetOptions. */ { - int i; + size_t i; Option *optionPtr; Tcl_Obj *newPtr; /* New object value of option, which we * replace with old value and free. Taken from * record. */ - char *internalPtr; /* Points to internal value of option in + void *internalPtr; /* Points to internal value of option in * record. */ const Tk_OptionSpec *specPtr; /* * Be sure to restore the options in the opposite order they were set. @@ -1359,26 +1358,26 @@ if (savePtr->nextPtr != NULL) { Tk_RestoreSavedOptions(savePtr->nextPtr); ckfree(savePtr->nextPtr); savePtr->nextPtr = NULL; } - for (i = savePtr->numItems - 1; i >= 0; i--) { + for (i = savePtr->numItems - 1; i != (size_t)-1; i--) { optionPtr = savePtr->items[i].optionPtr; specPtr = optionPtr->specPtr; /* * First free the new value of the option, which is currently in the * record. */ - if (specPtr->objOffset >= 0) { - newPtr = *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset)); + if (specPtr->objOffset != TCL_AUTO_LENGTH) { + newPtr = *((Tcl_Obj **) ((char *)savePtr->recordPtr + specPtr->objOffset)); } else { newPtr = NULL; } - if (specPtr->internalOffset >= 0) { - internalPtr = savePtr->recordPtr + specPtr->internalOffset; + if (specPtr->internalOffset != TCL_AUTO_LENGTH) { + internalPtr = (char *)savePtr->recordPtr + specPtr->internalOffset; } else { internalPtr = NULL; } if (optionPtr->flags & OPTION_NEEDS_FREEING) { FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin); @@ -1389,15 +1388,15 @@ /* * Now restore the old value of the option. */ - if (specPtr->objOffset >= 0) { - *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset)) + if (specPtr->objOffset != TCL_AUTO_LENGTH) { + *((Tcl_Obj **) ((char *)savePtr->recordPtr + specPtr->objOffset)) = savePtr->items[i].valuePtr; } - if (specPtr->internalOffset >= 0) { + if (specPtr->internalOffset != TCL_AUTO_LENGTH) { register char *ptr = (char *) &savePtr->items[i].internalForm; CLANG_ASSERT(internalPtr); switch (specPtr->type) { case TK_OPTION_BOOLEAN: @@ -1486,11 +1485,11 @@ void Tk_FreeSavedOptions( Tk_SavedOptions *savePtr) /* Contains options saved in a previous call * to Tk_SetOptions. */ { - int count; + size_t count; Tk_SavedOption *savedOptionPtr; if (savePtr->nextPtr != NULL) { Tk_FreeSavedOptions(savePtr->nextPtr); ckfree(savePtr->nextPtr); @@ -1526,21 +1525,21 @@ */ /* ARGSUSED */ void Tk_FreeConfigOptions( - char *recordPtr, /* Record whose fields contain current values + void *recordPtr, /* Record whose fields contain current values * for options. */ Tk_OptionTable optionTable, /* Describes legal options. */ Tk_Window tkwin) /* Window associated with recordPtr; needed * for freeing some options. */ { OptionTable *tablePtr; Option *optionPtr; - int count; + size_t count; Tcl_Obj **oldPtrPtr, *oldPtr; - char *oldInternalPtr; + void *oldInternalPtr; const Tk_OptionSpec *specPtr; for (tablePtr = (OptionTable *) optionTable; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { for (optionPtr = tablePtr->options, count = tablePtr->numOptions; @@ -1547,19 +1546,19 @@ count > 0; optionPtr++, count--) { specPtr = optionPtr->specPtr; if (specPtr->type == TK_OPTION_SYNONYM) { continue; } - if (specPtr->objOffset >= 0) { - oldPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset); + if (specPtr->objOffset != TCL_AUTO_LENGTH) { + oldPtrPtr = (Tcl_Obj **) ((char *)recordPtr + specPtr->objOffset); oldPtr = *oldPtrPtr; *oldPtrPtr = NULL; } else { oldPtr = NULL; } - if (specPtr->internalOffset >= 0) { - oldInternalPtr = recordPtr + specPtr->internalOffset; + if (specPtr->internalOffset != TCL_AUTO_LENGTH) { + oldInternalPtr = (char *)recordPtr + specPtr->internalOffset; } else { oldInternalPtr = NULL; } if (optionPtr->flags & OPTION_NEEDS_FREEING) { FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin); @@ -1592,14 +1591,14 @@ static void FreeResources( Option *optionPtr, /* Description of the configuration option. */ Tcl_Obj *objPtr, /* The current value of the option, specified * as an object. */ - char *internalPtr, /* A pointer to an internal representation for + void *internalPtr, /* A pointer to an internal representation for * the option's value, such as an int or * (XColor *). Only valid if - * optionPtr->specPtr->internalOffset >= 0. */ + * optionPtr->specPtr->internalOffset != -1. */ Tk_Window tkwin) /* The window in which this option is used. */ { int internalFormExists; /* @@ -1606,11 +1605,11 @@ * If there exists an internal form for the value, use it to free * resources (also zero out the internal form). If there is no internal * form, then use the object form. */ - internalFormExists = optionPtr->specPtr->internalOffset >= 0; + internalFormExists = optionPtr->specPtr->internalOffset != TCL_AUTO_LENGTH; switch (optionPtr->specPtr->type) { case TK_OPTION_STRING: if (internalFormExists) { if (*((char **) internalPtr) != NULL) { ckfree(*((char **) internalPtr)); @@ -1638,12 +1637,10 @@ break; case TK_OPTION_STYLE: if (internalFormExists) { Tk_FreeStyle(*((Tk_Style *) internalPtr)); *((Tk_Style *) internalPtr) = NULL; - } else if (objPtr != NULL) { - Tk_FreeStyleFromObj(objPtr); } break; case TK_OPTION_BITMAP: if (internalFormExists) { if (*((Pixmap *) internalPtr) != None) { @@ -1714,11 +1711,11 @@ Tcl_Obj * Tk_GetOptionInfo( Tcl_Interp *interp, /* Interpreter for error reporting. If NULL, * then no error message is created. */ - char *recordPtr, /* Record whose fields contain current values + void *recordPtr, /* Record whose fields contain current values * for options. */ Tk_OptionTable optionTable, /* Describes all the legal options. */ Tcl_Obj *namePtr, /* If non-NULL, the string value selects a * single option whose info is to be returned. * Otherwise info is returned for all options @@ -1728,11 +1725,11 @@ * options. */ { Tcl_Obj *resultPtr; OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; - int count; + size_t count; /* * If information is only wanted for a single configuration spec, then * handle that one spec specially. */ @@ -1782,11 +1779,11 @@ *-------------------------------------------------------------- */ static Tcl_Obj * GetConfigList( - char *recordPtr, /* Pointer to record holding current values of + void *recordPtr, /* Pointer to record holding current values of * configuration options. */ Option *optionPtr, /* Pointer to information describing a * particular option. */ Tk_Window tkwin) /* Window corresponding to recordPtr. */ { @@ -1825,12 +1822,12 @@ } else { elementPtr = Tcl_NewObj(); } Tcl_ListObjAppendElement(NULL, listPtr, elementPtr); - if (optionPtr->specPtr->objOffset >= 0) { - elementPtr = *((Tcl_Obj **) (recordPtr + if (optionPtr->specPtr->objOffset != TCL_AUTO_LENGTH) { + elementPtr = *((Tcl_Obj **) ((char *)recordPtr + optionPtr->specPtr->objOffset)); if (elementPtr == NULL) { elementPtr = Tcl_NewObj(); } } else { @@ -1860,29 +1857,29 @@ *---------------------------------------------------------------------- */ static Tcl_Obj * GetObjectForOption( - char *recordPtr, /* Pointer to record holding current values of + void *recordPtr, /* Pointer to record holding current values of * configuration options. */ Option *optionPtr, /* Pointer to information describing an option * whose internal value is stored in * *recordPtr. */ Tk_Window tkwin) /* Window corresponding to recordPtr. */ { Tcl_Obj *objPtr; - char *internalPtr; /* Points to internal value of option in + void *internalPtr; /* Points to internal value of option in * record. */ - internalPtr = recordPtr + optionPtr->specPtr->internalOffset; + internalPtr = (char *)recordPtr + optionPtr->specPtr->internalOffset; objPtr = NULL; switch (optionPtr->specPtr->type) { case TK_OPTION_BOOLEAN: - objPtr = Tcl_NewIntObj(*((int *) internalPtr)); + objPtr = Tcl_NewWideIntObj(*((int *) internalPtr)); break; case TK_OPTION_INT: - objPtr = Tcl_NewIntObj(*((int *) internalPtr)); + objPtr = Tcl_NewWideIntObj(*((int *) internalPtr)); break; case TK_OPTION_DOUBLE: objPtr = Tcl_NewDoubleObj(*((double *) internalPtr)); break; case TK_OPTION_STRING: @@ -1952,11 +1949,11 @@ case TK_OPTION_ANCHOR: objPtr = Tcl_NewStringObj(Tk_NameOfAnchor( *((Tk_Anchor *) internalPtr)), -1); break; case TK_OPTION_PIXELS: - objPtr = Tcl_NewIntObj(*((int *) internalPtr)); + objPtr = Tcl_NewWideIntObj(*((int *) internalPtr)); break; case TK_OPTION_WINDOW: { Tk_Window tkwin = *((Tk_Window *) internalPtr); if (tkwin != NULL) { @@ -2002,11 +1999,11 @@ Tcl_Obj * Tk_GetOptionValue( Tcl_Interp *interp, /* Interpreter for error reporting. If NULL * then no messages are provided for * errors. */ - char *recordPtr, /* Record whose fields contain current values + void *recordPtr, /* Record whose fields contain current values * for options. */ Tk_OptionTable optionTable, /* Describes legal options. */ Tcl_Obj *namePtr, /* Gives the command-line name for the option * whose value is to be returned. */ Tk_Window tkwin) /* Window corresponding to recordPtr. */ @@ -2020,12 +2017,12 @@ return NULL; } if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) { optionPtr = optionPtr->extra.synonymPtr; } - if (optionPtr->specPtr->objOffset >= 0) { - resultPtr = *((Tcl_Obj **) (recordPtr+optionPtr->specPtr->objOffset)); + if (optionPtr->specPtr->objOffset != TCL_AUTO_LENGTH) { + resultPtr = *((Tcl_Obj **) ((char *)recordPtr+optionPtr->specPtr->objOffset)); if (resultPtr == NULL) { /* * This option has a null value and is represented by a null * object pointer. We can't return the null pointer, since that * would indicate an error. Instead, return a new empty object. @@ -2091,13 +2088,13 @@ hashEntryPtr != NULL; hashEntryPtr = Tcl_NextHashEntry(&search)) { if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) { for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(tablePtr->refCount)); + Tcl_NewWideIntObj(tablePtr->refCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(tablePtr->numOptions)); + Tcl_NewWideIntObj(tablePtr->numOptions)); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj( tablePtr->options[0].specPtr->optionName, -1)); } break; } Index: generic/tkConsole.c ================================================================== --- generic/tkConsole.c +++ generic/tkConsole.c @@ -22,11 +22,11 @@ */ typedef struct ConsoleInfo { Tcl_Interp *consoleInterp; /* Interpreter displaying the console. */ Tcl_Interp *interp; /* Interpreter controlled by console. */ - int refCount; + size_t refCount; } ConsoleInfo; /* * Each console channel holds an instance of the ChannelData struct as * its instance data. It contains ConsoleInfo, so the channel can work @@ -221,11 +221,11 @@ /* * Ensure that we are getting a compatible version of Tcl. */ - if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) { return; } consoleInitPtr = Tcl_GetThreadData(&consoleInitKey, (int) sizeof(int)); if (*consoleInitPtr) { @@ -454,11 +454,11 @@ Tcl_DeleteCommandFromToken(interp, token); mainWindow = Tk_MainWindow(interp); if (mainWindow) { Tk_DeleteEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc, info); - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } goto error; } @@ -594,11 +594,11 @@ { ChannelData *data = instanceData; ConsoleInfo *info = data->info; if (info) { - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { /* * Assuming the Tcl_Interp * fields must already be NULL. */ ckfree(info); @@ -883,11 +883,11 @@ if (info->consoleInterp == interp) { Tcl_DeleteThreadExitHandler(DeleteConsoleInterp, info->consoleInterp); info->consoleInterp = NULL; } - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } /* @@ -914,11 +914,11 @@ ConsoleInfo *info = clientData; if (info->consoleInterp) { Tcl_DeleteInterp(info->consoleInterp); } - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } /* @@ -951,11 +951,11 @@ if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) { Tcl_EvalEx(consoleInterp, "tk::ConsoleExit", -1, TCL_EVAL_GLOBAL); } - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } } Index: generic/tkCursor.c ================================================================== --- generic/tkCursor.c +++ generic/tkCursor.c @@ -426,11 +426,11 @@ if (!dispPtr->cursorInit) { printid: sprintf(dispPtr->cursorString, "cursor id %p", cursor); return dispPtr->cursorString; } - idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor); + idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, cursor); if (idHashPtr == NULL) { goto printid; } cursorPtr = Tcl_GetHashValue(idHashPtr); if (cursorPtr->otherTable != &dispPtr->cursorNameTable) { @@ -461,12 +461,11 @@ FreeCursor( TkCursor *cursorPtr) /* Cursor to be released. */ { TkCursor *prevPtr; - cursorPtr->resourceRefCount--; - if (cursorPtr->resourceRefCount > 0) { + if (cursorPtr->resourceRefCount-- > 1) { return; } Tcl_DeleteHashEntry(cursorPtr->idHashPtr); prevPtr = Tcl_GetHashValue(cursorPtr->hashPtr); @@ -516,11 +515,11 @@ if (!dispPtr->cursorInit) { Tcl_Panic("Tk_FreeCursor called before Tk_GetCursor"); } - idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor); + idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, cursor); if (idHashPtr == NULL) { Tcl_Panic("Tk_FreeCursor received unknown cursor argument"); } FreeCursor(Tcl_GetHashValue(idHashPtr)); } @@ -588,12 +587,11 @@ Tcl_Obj *objPtr) /* The object we are releasing. */ { TkCursor *cursorPtr = objPtr->internalRep.twoPtrValue.ptr1; if (cursorPtr != NULL) { - cursorPtr->objRefCount--; - if ((cursorPtr->objRefCount == 0) + if ((cursorPtr->objRefCount-- <= 1) && (cursorPtr->resourceRefCount == 0)) { ckfree(cursorPtr); } objPtr->internalRep.twoPtrValue.ptr1 = NULL; } @@ -862,13 +860,13 @@ Tcl_Panic("TkDebugCursor found empty hash table entry"); } for ( ; (cursorPtr != NULL); cursorPtr = cursorPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(cursorPtr->resourceRefCount)); + Tcl_NewWideIntObj(cursorPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(cursorPtr->objRefCount)); + Tcl_NewWideIntObj(cursorPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } Index: generic/tkDList.h ================================================================== --- generic/tkDList.h +++ generic/tkDList.h @@ -40,12 +40,11 @@ */ #ifndef TK_DLIST_DEFINED #define TK_DLIST_DEFINED -#include -#include +#include "tkInt.h" /* * List definitions. */ Index: generic/tkDecls.h ================================================================== --- generic/tkDecls.h +++ generic/tkDecls.h @@ -15,10 +15,18 @@ #ifdef BUILD_tk #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT #endif +#if !defined(BUILD_tk) +# define TK_DEPRECATED(msg) EXTERN TCL_DEPRECATED_API(msg) +#elif defined(TK_NO_DEPRECATED) +# define TK_DEPRECATED(msg) MODULE_SCOPE +#else +# define TK_DEPRECATED(msg) EXTERN +#endif + /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tk.decls script. */ @@ -93,11 +101,11 @@ /* 18 */ EXTERN int Tk_CanvasTagsParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 19 */ -EXTERN CONST86 char * Tk_CanvasTagsPrintProc(ClientData clientData, +EXTERN const char * Tk_CanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 20 */ EXTERN Tk_Window Tk_CanvasTkwin(Tk_Canvas canvas); /* 21 */ @@ -131,11 +139,11 @@ char *widgRec, const char *argvName, int flags); /* 29 */ EXTERN int Tk_ConfigureWidget(Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, - int argc, CONST84 char **argv, char *widgRec, + int argc, const char **argv, char *widgRec, int flags); /* 30 */ EXTERN void Tk_ConfigureWindow(Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); @@ -213,11 +221,11 @@ EXTERN void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection, Atom target); /* 54 */ EXTERN void Tk_DestroyWindow(Tk_Window tkwin); /* 55 */ -EXTERN CONST84_RETURN char * Tk_DisplayName(Tk_Window tkwin); +EXTERN const char * Tk_DisplayName(Tk_Window tkwin); /* 56 */ EXTERN int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x, int y); /* 57 */ EXTERN void Tk_Draw3DPolygon(Tk_Window tkwin, Drawable drawable, @@ -279,11 +287,12 @@ /* 75 */ EXTERN void Tk_FreePixmap(Display *display, Pixmap pixmap); /* 76 */ EXTERN void Tk_FreeTextLayout(Tk_TextLayout textLayout); /* 77 */ -EXTERN void Tk_FreeXId(Display *display, XID xid); +TK_DEPRECATED("function does nothing, call can be removed") +void Tk_FreeXId(Display *display, XID xid); /* 78 */ EXTERN GC Tk_GCForColor(XColor *colorPtr, Drawable drawable); /* 79 */ EXTERN void Tk_GeometryRequest(Tk_Window tkwin, int reqWidth, int reqHeight); @@ -296,13 +305,13 @@ ClientData object); /* 82 */ EXTERN int Tk_GetAnchor(Tcl_Interp *interp, const char *str, Tk_Anchor *anchorPtr); /* 83 */ -EXTERN CONST84_RETURN char * Tk_GetAtomName(Tk_Window tkwin, Atom atom); +EXTERN const char * Tk_GetAtomName(Tk_Window tkwin, Atom atom); /* 84 */ -EXTERN CONST84_RETURN char * Tk_GetBinding(Tcl_Interp *interp, +EXTERN const char * Tk_GetBinding(Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 85 */ EXTERN Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, const char *str); @@ -346,11 +355,11 @@ Tk_ImageChangedProc *changeProc, ClientData clientData); /* 98 */ EXTERN ClientData Tk_GetImageMasterData(Tcl_Interp *interp, const char *name, - CONST86 Tk_ImageType **typePtrPtr); + const Tk_ImageType **typePtrPtr); /* 99 */ EXTERN Tk_ItemType * Tk_GetItemTypes(void); /* 100 */ EXTERN int Tk_GetJoinStyle(Tcl_Interp *interp, const char *str, int *joinPtr); @@ -374,11 +383,11 @@ /* 107 */ EXTERN void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr, int *yPtr); /* 108 */ EXTERN int Tk_GetScrollInfo(Tcl_Interp *interp, int argc, - CONST84 char **argv, double *dblPtr, + const char **argv, double *dblPtr, int *intPtr); /* 109 */ EXTERN int Tk_GetScreenMM(Tcl_Interp *interp, Tk_Window tkwin, const char *str, double *doublePtr); /* 110 */ @@ -436,48 +445,49 @@ /* 128 */ EXTERN void Tk_MoveWindow(Tk_Window tkwin, int x, int y); /* 129 */ EXTERN void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y); /* 130 */ -EXTERN CONST84_RETURN char * Tk_NameOf3DBorder(Tk_3DBorder border); +EXTERN const char * Tk_NameOf3DBorder(Tk_3DBorder border); /* 131 */ -EXTERN CONST84_RETURN char * Tk_NameOfAnchor(Tk_Anchor anchor); +EXTERN const char * Tk_NameOfAnchor(Tk_Anchor anchor); /* 132 */ -EXTERN CONST84_RETURN char * Tk_NameOfBitmap(Display *display, Pixmap bitmap); +EXTERN const char * Tk_NameOfBitmap(Display *display, Pixmap bitmap); /* 133 */ -EXTERN CONST84_RETURN char * Tk_NameOfCapStyle(int cap); +EXTERN const char * Tk_NameOfCapStyle(int cap); /* 134 */ -EXTERN CONST84_RETURN char * Tk_NameOfColor(XColor *colorPtr); +EXTERN const char * Tk_NameOfColor(XColor *colorPtr); /* 135 */ -EXTERN CONST84_RETURN char * Tk_NameOfCursor(Display *display, - Tk_Cursor cursor); +EXTERN const char * Tk_NameOfCursor(Display *display, Tk_Cursor cursor); /* 136 */ -EXTERN CONST84_RETURN char * Tk_NameOfFont(Tk_Font font); +EXTERN const char * Tk_NameOfFont(Tk_Font font); /* 137 */ -EXTERN CONST84_RETURN char * Tk_NameOfImage(Tk_ImageMaster imageMaster); +EXTERN const char * Tk_NameOfImage(Tk_ImageMaster imageMaster); /* 138 */ -EXTERN CONST84_RETURN char * Tk_NameOfJoinStyle(int join); +EXTERN const char * Tk_NameOfJoinStyle(int join); /* 139 */ -EXTERN CONST84_RETURN char * Tk_NameOfJustify(Tk_Justify justify); +EXTERN const char * Tk_NameOfJustify(Tk_Justify justify); /* 140 */ -EXTERN CONST84_RETURN char * Tk_NameOfRelief(int relief); +EXTERN const char * Tk_NameOfRelief(int relief); /* 141 */ EXTERN Tk_Window Tk_NameToWindow(Tcl_Interp *interp, const char *pathName, Tk_Window tkwin); /* 142 */ EXTERN void Tk_OwnSelection(Tk_Window tkwin, Atom selection, Tk_LostSelProc *proc, ClientData clientData); /* 143 */ EXTERN int Tk_ParseArgv(Tcl_Interp *interp, Tk_Window tkwin, - int *argcPtr, CONST84 char **argv, + int *argcPtr, const char **argv, const Tk_ArgvInfo *argTable, int flags); /* 144 */ -EXTERN void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle, +TK_DEPRECATED("function signature changed") +void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height); /* 145 */ -EXTERN void Tk_PhotoPutZoomedBlock_NoComposite( +TK_DEPRECATED("function signature changed") +void Tk_PhotoPutZoomedBlock_NoComposite( Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY); /* 146 */ @@ -484,17 +494,19 @@ EXTERN int Tk_PhotoGetImage(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr); /* 147 */ EXTERN void Tk_PhotoBlank(Tk_PhotoHandle handle); /* 148 */ -EXTERN void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle, +TK_DEPRECATED("function signature changed") +void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle, int width, int height); /* 149 */ EXTERN void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr, int *heightPtr); /* 150 */ -EXTERN void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, +TK_DEPRECATED("function signature changed") +void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, int width, int height); /* 151 */ EXTERN int Tk_PointToChar(Tk_TextLayout layout, int x, int y); /* 152 */ EXTERN int Tk_PostscriptFontName(Tk_Font tkfont, @@ -618,11 +630,11 @@ EXTERN void Tk_FreeBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); /* 194 */ EXTERN void Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); /* 195 */ -EXTERN void Tk_FreeConfigOptions(char *recordPtr, +EXTERN void Tk_FreeConfigOptions(void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 196 */ EXTERN void Tk_FreeSavedOptions(Tk_SavedOptions *savePtr); /* 197 */ EXTERN void Tk_FreeCursorFromObj(Tk_Window tkwin, @@ -640,16 +652,16 @@ /* 202 */ EXTERN XColor * Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); /* 203 */ EXTERN Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); /* 204 */ -EXTERN Tcl_Obj * Tk_GetOptionInfo(Tcl_Interp *interp, char *recordPtr, +EXTERN Tcl_Obj * Tk_GetOptionInfo(Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */ EXTERN Tcl_Obj * Tk_GetOptionValue(Tcl_Interp *interp, - char *recordPtr, Tk_OptionTable optionTable, + void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 206 */ EXTERN int Tk_GetJustifyFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr); /* 207 */ @@ -665,20 +677,20 @@ /* 210 */ EXTERN int Tk_GetScrollInfoObj(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); /* 211 */ -EXTERN int Tk_InitOptions(Tcl_Interp *interp, char *recordPtr, +EXTERN int Tk_InitOptions(Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 212 */ EXTERN void Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 213 */ EXTERN void Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr); /* 214 */ -EXTERN int Tk_SetOptions(Tcl_Interp *interp, char *recordPtr, +EXTERN int Tk_SetOptions(Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 215 */ EXTERN void Tk_InitConsoleChannels(Tcl_Interp *interp); @@ -774,15 +786,17 @@ int minWidth, int minHeight); /* 245 */ EXTERN void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height); /* 246 */ -EXTERN void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle, +TK_DEPRECATED("function signature changed") +void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 247 */ -EXTERN void Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle, +TK_DEPRECATED("function signature changed") +void Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 248 */ EXTERN int Tk_CollapseMotionEvents(Display *display, @@ -816,26 +830,26 @@ /* 260 */ EXTERN Tk_StyledElement Tk_GetStyledElement(Tk_Style style, int elementId, Tk_OptionTable optionTable); /* 261 */ EXTERN void Tk_GetElementSize(Tk_Style style, - Tk_StyledElement element, char *recordPtr, + Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 262 */ EXTERN void Tk_GetElementBox(Tk_Style style, - Tk_StyledElement element, char *recordPtr, + Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 263 */ EXTERN int Tk_GetElementBorderWidth(Tk_Style style, - Tk_StyledElement element, char *recordPtr, + Tk_StyledElement element, void *recordPtr, Tk_Window tkwin); /* 264 */ EXTERN void Tk_DrawElement(Tk_Style style, - Tk_StyledElement element, char *recordPtr, + Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 265 */ EXTERN int Tk_PhotoExpand(Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); @@ -893,21 +907,21 @@ void (*tk_CanvasPsPath) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, int numPoints); /* 14 */ int (*tk_CanvasPsStipple) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap); /* 15 */ double (*tk_CanvasPsY) (Tk_Canvas canvas, double y); /* 16 */ void (*tk_CanvasSetStippleOrigin) (Tk_Canvas canvas, GC gc); /* 17 */ int (*tk_CanvasTagsParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 18 */ - CONST86 char * (*tk_CanvasTagsPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 19 */ + const char * (*tk_CanvasTagsPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 19 */ Tk_Window (*tk_CanvasTkwin) (Tk_Canvas canvas); /* 20 */ void (*tk_CanvasWindowCoords) (Tk_Canvas canvas, double x, double y, short *screenXPtr, short *screenYPtr); /* 21 */ void (*tk_ChangeWindowAttributes) (Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes *attsPtr); /* 22 */ int (*tk_CharBbox) (Tk_TextLayout layout, int index, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 23 */ void (*tk_ClearSelection) (Tk_Window tkwin, Atom selection); /* 24 */ int (*tk_ClipboardAppend) (Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, const char *buffer); /* 25 */ int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */ int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 27 */ int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 28 */ - int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags); /* 29 */ + int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, const char **argv, char *widgRec, int flags); /* 29 */ void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */ Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, const char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */ Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */ unsigned long (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr, const char *script, int append); /* 33 */ Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */ @@ -929,11 +943,11 @@ void (*tk_DeleteEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 50 */ void (*tk_DeleteGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 51 */ void (*tk_DeleteImage) (Tcl_Interp *interp, const char *name); /* 52 */ void (*tk_DeleteSelHandler) (Tk_Window tkwin, Atom selection, Atom target); /* 53 */ void (*tk_DestroyWindow) (Tk_Window tkwin); /* 54 */ - CONST84_RETURN char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */ + const char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */ int (*tk_DistanceToTextLayout) (Tk_TextLayout layout, int x, int y); /* 56 */ void (*tk_Draw3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 57 */ void (*tk_Draw3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 58 */ void (*tk_DrawChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, int x, int y); /* 59 */ void (*tk_DrawFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable); /* 60 */ @@ -951,18 +965,18 @@ void (*tk_FreeGC) (Display *display, GC gc); /* 72 */ void (*tk_FreeImage) (Tk_Image image); /* 73 */ void (*tk_FreeOptions) (const Tk_ConfigSpec *specs, char *widgRec, Display *display, int needFlags); /* 74 */ void (*tk_FreePixmap) (Display *display, Pixmap pixmap); /* 75 */ void (*tk_FreeTextLayout) (Tk_TextLayout textLayout); /* 76 */ - void (*tk_FreeXId) (Display *display, XID xid); /* 77 */ + TCL_DEPRECATED_API("function does nothing, call can be removed") void (*tk_FreeXId) (Display *display, XID xid); /* 77 */ GC (*tk_GCForColor) (XColor *colorPtr, Drawable drawable); /* 78 */ void (*tk_GeometryRequest) (Tk_Window tkwin, int reqWidth, int reqHeight); /* 79 */ Tk_3DBorder (*tk_Get3DBorder) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid colorName); /* 80 */ void (*tk_GetAllBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object); /* 81 */ int (*tk_GetAnchor) (Tcl_Interp *interp, const char *str, Tk_Anchor *anchorPtr); /* 82 */ - CONST84_RETURN char * (*tk_GetAtomName) (Tk_Window tkwin, Atom atom); /* 83 */ - CONST84_RETURN char * (*tk_GetBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 84 */ + const char * (*tk_GetAtomName) (Tk_Window tkwin, Atom atom); /* 83 */ + const char * (*tk_GetBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 84 */ Pixmap (*tk_GetBitmap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 85 */ Pixmap (*tk_GetBitmapFromData) (Tcl_Interp *interp, Tk_Window tkwin, const void *source, int width, int height); /* 86 */ int (*tk_GetCapStyle) (Tcl_Interp *interp, const char *str, int *capPtr); /* 87 */ XColor * (*tk_GetColor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name); /* 88 */ XColor * (*tk_GetColorByValue) (Tk_Window tkwin, XColor *colorPtr); /* 89 */ @@ -972,21 +986,21 @@ Tk_Font (*tk_GetFont) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 93 */ Tk_Font (*tk_GetFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 94 */ void (*tk_GetFontMetrics) (Tk_Font font, Tk_FontMetrics *fmPtr); /* 95 */ GC (*tk_GetGC) (Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr); /* 96 */ Tk_Image (*tk_GetImage) (Tcl_Interp *interp, Tk_Window tkwin, const char *name, Tk_ImageChangedProc *changeProc, ClientData clientData); /* 97 */ - ClientData (*tk_GetImageMasterData) (Tcl_Interp *interp, const char *name, CONST86 Tk_ImageType **typePtrPtr); /* 98 */ + ClientData (*tk_GetImageMasterData) (Tcl_Interp *interp, const char *name, const Tk_ImageType **typePtrPtr); /* 98 */ Tk_ItemType * (*tk_GetItemTypes) (void); /* 99 */ int (*tk_GetJoinStyle) (Tcl_Interp *interp, const char *str, int *joinPtr); /* 100 */ int (*tk_GetJustify) (Tcl_Interp *interp, const char *str, Tk_Justify *justifyPtr); /* 101 */ int (*tk_GetNumMainWindows) (void); /* 102 */ Tk_Uid (*tk_GetOption) (Tk_Window tkwin, const char *name, const char *className); /* 103 */ int (*tk_GetPixels) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *intPtr); /* 104 */ Pixmap (*tk_GetPixmap) (Display *display, Drawable d, int width, int height, int depth); /* 105 */ int (*tk_GetRelief) (Tcl_Interp *interp, const char *name, int *reliefPtr); /* 106 */ void (*tk_GetRootCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 107 */ - int (*tk_GetScrollInfo) (Tcl_Interp *interp, int argc, CONST84 char **argv, double *dblPtr, int *intPtr); /* 108 */ + int (*tk_GetScrollInfo) (Tcl_Interp *interp, int argc, const char **argv, double *dblPtr, int *intPtr); /* 108 */ int (*tk_GetScreenMM) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, double *doublePtr); /* 109 */ int (*tk_GetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 110 */ Tk_Uid (*tk_GetUid) (const char *str); /* 111 */ Visual * (*tk_GetVisual) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *depthPtr, Colormap *colormapPtr); /* 112 */ void (*tk_GetVRootGeometry) (Tk_Window tkwin, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 113 */ @@ -1004,31 +1018,31 @@ void (*tk_MapWindow) (Tk_Window tkwin); /* 125 */ int (*tk_MeasureChars) (Tk_Font tkfont, const char *source, int numBytes, int maxPixels, int flags, int *lengthPtr); /* 126 */ void (*tk_MoveResizeWindow) (Tk_Window tkwin, int x, int y, int width, int height); /* 127 */ void (*tk_MoveWindow) (Tk_Window tkwin, int x, int y); /* 128 */ void (*tk_MoveToplevelWindow) (Tk_Window tkwin, int x, int y); /* 129 */ - CONST84_RETURN char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */ - CONST84_RETURN char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */ - CONST84_RETURN char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */ - CONST84_RETURN char * (*tk_NameOfCapStyle) (int cap); /* 133 */ - CONST84_RETURN char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */ - CONST84_RETURN char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */ - CONST84_RETURN char * (*tk_NameOfFont) (Tk_Font font); /* 136 */ - CONST84_RETURN char * (*tk_NameOfImage) (Tk_ImageMaster imageMaster); /* 137 */ - CONST84_RETURN char * (*tk_NameOfJoinStyle) (int join); /* 138 */ - CONST84_RETURN char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */ - CONST84_RETURN char * (*tk_NameOfRelief) (int relief); /* 140 */ + const char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */ + const char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */ + const char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */ + const char * (*tk_NameOfCapStyle) (int cap); /* 133 */ + const char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */ + const char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */ + const char * (*tk_NameOfFont) (Tk_Font font); /* 136 */ + const char * (*tk_NameOfImage) (Tk_ImageMaster imageMaster); /* 137 */ + const char * (*tk_NameOfJoinStyle) (int join); /* 138 */ + const char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */ + const char * (*tk_NameOfRelief) (int relief); /* 140 */ Tk_Window (*tk_NameToWindow) (Tcl_Interp *interp, const char *pathName, Tk_Window tkwin); /* 141 */ void (*tk_OwnSelection) (Tk_Window tkwin, Atom selection, Tk_LostSelProc *proc, ClientData clientData); /* 142 */ - int (*tk_ParseArgv) (Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, CONST84 char **argv, const Tk_ArgvInfo *argTable, int flags); /* 143 */ - void (*tk_PhotoPutBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height); /* 144 */ - void (*tk_PhotoPutZoomedBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY); /* 145 */ + int (*tk_ParseArgv) (Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, const char **argv, const Tk_ArgvInfo *argTable, int flags); /* 143 */ + TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height); /* 144 */ + TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutZoomedBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY); /* 145 */ int (*tk_PhotoGetImage) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr); /* 146 */ void (*tk_PhotoBlank) (Tk_PhotoHandle handle); /* 147 */ - void (*tk_PhotoExpand_Panic) (Tk_PhotoHandle handle, int width, int height); /* 148 */ + TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoExpand_Panic) (Tk_PhotoHandle handle, int width, int height); /* 148 */ void (*tk_PhotoGetSize) (Tk_PhotoHandle handle, int *widthPtr, int *heightPtr); /* 149 */ - void (*tk_PhotoSetSize_Panic) (Tk_PhotoHandle handle, int width, int height); /* 150 */ + TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoSetSize_Panic) (Tk_PhotoHandle handle, int width, int height); /* 150 */ int (*tk_PointToChar) (Tk_TextLayout layout, int x, int y); /* 151 */ int (*tk_PostscriptFontName) (Tk_Font tkfont, Tcl_DString *dsPtr); /* 152 */ void (*tk_PreserveColormap) (Display *display, Colormap colormap); /* 153 */ void (*tk_QueueWindowEvent) (XEvent *eventPtr, Tcl_QueuePosition position); /* 154 */ void (*tk_RedrawImage) (Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY); /* 155 */ @@ -1069,30 +1083,30 @@ Tk_OptionTable (*tk_CreateOptionTable) (Tcl_Interp *interp, const Tk_OptionSpec *templatePtr); /* 190 */ void (*tk_DeleteOptionTable) (Tk_OptionTable optionTable); /* 191 */ void (*tk_Free3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 192 */ void (*tk_FreeBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 193 */ void (*tk_FreeColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 194 */ - void (*tk_FreeConfigOptions) (char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */ + void (*tk_FreeConfigOptions) (void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */ void (*tk_FreeSavedOptions) (Tk_SavedOptions *savePtr); /* 196 */ void (*tk_FreeCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 197 */ void (*tk_FreeFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 198 */ Tk_3DBorder (*tk_Get3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 199 */ int (*tk_GetAnchorFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Anchor *anchorPtr); /* 200 */ Pixmap (*tk_GetBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 201 */ XColor * (*tk_GetColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 202 */ Tk_Cursor (*tk_GetCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 203 */ - Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */ - Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */ + Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */ + Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */ int (*tk_GetJustifyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr); /* 206 */ int (*tk_GetMMFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 207 */ int (*tk_GetPixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr); /* 208 */ int (*tk_GetReliefFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr); /* 209 */ int (*tk_GetScrollInfoObj) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); /* 210 */ - int (*tk_InitOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */ - void (*tk_MainEx) (int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 212 */ + int (*tk_InitOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */ + TCL_DEPRECATED_API("Don't use this function in a stub-enabled extension") void (*tk_MainEx) (int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 212 */ void (*tk_RestoreSavedOptions) (Tk_SavedOptions *savePtr); /* 213 */ - int (*tk_SetOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 214 */ + int (*tk_SetOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 214 */ void (*tk_InitConsoleChannels) (Tcl_Interp *interp); /* 215 */ int (*tk_CreateConsoleWindow) (Tcl_Interp *interp); /* 216 */ void (*tk_CreateSmoothMethod) (Tcl_Interp *interp, const Tk_SmoothMethod *method); /* 217 */ void (*reserved218)(void); void (*reserved219)(void); @@ -1120,12 +1134,12 @@ Tk_Window (*tk_CreateAnonymousWindow) (Tcl_Interp *interp, Tk_Window parent, const char *screenName); /* 241 */ void (*tk_SetClassProcs) (Tk_Window tkwin, const Tk_ClassProcs *procs, ClientData instanceData); /* 242 */ void (*tk_SetInternalBorderEx) (Tk_Window tkwin, int left, int right, int top, int bottom); /* 243 */ void (*tk_SetMinimumRequestSize) (Tk_Window tkwin, int minWidth, int minHeight); /* 244 */ void (*tk_SetCaretPos) (Tk_Window tkwin, int x, int y, int height); /* 245 */ - void (*tk_PhotoPutBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 246 */ - void (*tk_PhotoPutZoomedBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 247 */ + TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 246 */ + TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutZoomedBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 247 */ int (*tk_CollapseMotionEvents) (Display *display, int collapse); /* 248 */ Tk_StyleEngine (*tk_RegisterStyleEngine) (const char *name, Tk_StyleEngine parent); /* 249 */ Tk_StyleEngine (*tk_GetStyleEngine) (const char *name); /* 250 */ int (*tk_RegisterStyledElement) (Tk_StyleEngine engine, Tk_ElementSpec *templatePtr); /* 251 */ int (*tk_GetElementId) (const char *name); /* 252 */ @@ -1135,14 +1149,14 @@ const char * (*tk_NameOfStyle) (Tk_Style style); /* 256 */ Tk_Style (*tk_AllocStyleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 257 */ Tk_Style (*tk_GetStyleFromObj) (Tcl_Obj *objPtr); /* 258 */ void (*tk_FreeStyleFromObj) (Tcl_Obj *objPtr); /* 259 */ Tk_StyledElement (*tk_GetStyledElement) (Tk_Style style, int elementId, Tk_OptionTable optionTable); /* 260 */ - void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */ - void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */ - int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin); /* 263 */ - void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */ + void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */ + void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */ + int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin); /* 263 */ + void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */ int (*tk_PhotoExpand) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 265 */ int (*tk_PhotoPutBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 266 */ int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */ int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */ long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */ @@ -1718,16 +1732,34 @@ /* Functions that don't belong in the stub table */ #undef Tk_MainEx #undef Tk_Init #undef Tk_SafeInit #undef Tk_CreateConsoleWindow + +#undef Tk_FreeXId +#define Tk_FreeXId(display,xid) +#undef Tk_GetStyleFromObj +#undef Tk_FreeStyleFromObj +#define Tk_GetStyleFromObj(obj) Tk_AllocStyleFromObj(NULL, obj) +#define Tk_FreeStyleFromObj(obj) /* no-op */ + #if defined(_WIN32) && defined(UNICODE) # define Tk_MainEx Tk_MainExW EXTERN void Tk_MainExW(int argc, wchar_t **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); #endif + +#if defined(TK_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 +#undef Tk_PhotoPutBlock_NoComposite +#undef Tk_PhotoPutZoomedBlock_NoComposite +#undef Tk_PhotoExpand_Panic +#undef Tk_PhotoPutBlock_Panic +#undef Tk_PhotoPutZoomedBlock_Panic +#undef Tk_PhotoSetSize_Panic +#endif /* TK_NO_DEPRECATED */ + #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TKDECLS */ Index: generic/tkEntry.c ================================================================== --- generic/tkEntry.c +++ generic/tkEntry.c @@ -14,12 +14,12 @@ * 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 "default.h" #include "tkEntry.h" +#include "default.h" /* * The following macro defines how many extra pixels to leave on each side of * the text in the entry. */ @@ -61,104 +61,110 @@ * Information used for Entry objv parsing. */ static const Tk_OptionSpec entryOptSpec[] = { {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder), + DEF_ENTRY_BG_COLOR, -1, offsetof(Entry, normalBorder), 0, DEF_ENTRY_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0}, + DEF_ENTRY_BORDER_WIDTH, -1, offsetof(Entry, borderWidth), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor), + DEF_ENTRY_CURSOR, -1, offsetof(Entry, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground", "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1, - Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK, + offsetof(Entry, disabledBorder), TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1, - Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, + offsetof(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1, - Tk_Offset(Entry, exportSelection), 0, 0, 0}, + offsetof(Entry, exportSelection), 0, 0, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0}, + DEF_ENTRY_FONT, -1, offsetof(Entry, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0}, + DEF_ENTRY_FG, -1, offsetof(Entry, fgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG, - -1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0}, + -1, offsetof(Entry, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0}, + DEF_ENTRY_HIGHLIGHT, -1, offsetof(Entry, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1, - Tk_Offset(Entry, highlightWidth), 0, 0, 0}, + offsetof(Entry, highlightWidth), 0, 0, 0}, {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground", - DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0}, + DEF_ENTRY_INSERT_BG, -1, offsetof(Entry, insertBorder), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1, - Tk_Offset(Entry, insertBorderWidth), 0, + offsetof(Entry, insertBorderWidth), 0, (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0}, {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime), + DEF_ENTRY_INSERT_OFF_TIME, -1, offsetof(Entry, insertOffTime), 0, 0, 0}, {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0}, + DEF_ENTRY_INSERT_ON_TIME, -1, offsetof(Entry, insertOnTime), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0}, + DEF_ENTRY_INSERT_WIDTH, -1, offsetof(Entry, insertWidth), 0, 0, 0}, {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand", - DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd), + DEF_ENTRY_INVALIDCMD, -1, offsetof(Entry, invalidCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL, NULL, 0, -1, 0, "-invalidcommand", 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0}, + DEF_ENTRY_JUSTIFY, -1, offsetof(Entry, justify), 0, 0, 0}, + {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder", + DEF_ENTRY_PLACEHOLDER, -1, offsetof(Entry, placeholderString), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground", + "PlaceholderForeground", DEF_ENTRY_PLACEHOLDERFG, -1, + offsetof(Entry, placeholderColorPtr), 0, 0, 0}, {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground", "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1, - Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK, + offsetof(Entry, readonlyBorder), TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0}, + DEF_ENTRY_RELIEF, -1, offsetof(Entry, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder), + DEF_ENTRY_SELECT_COLOR, -1, offsetof(Entry, selBorder), 0, DEF_ENTRY_SELECT_MONO, 0}, {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1, - Tk_Offset(Entry, selBorderWidth), + offsetof(Entry, selBorderWidth), 0, DEF_ENTRY_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr), + DEF_ENTRY_SELECT_FG_COLOR, -1, offsetof(Entry, selFgColorPtr), TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0}, {TK_OPTION_STRING, "-show", "show", "Show", - DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar), + DEF_ENTRY_SHOW, -1, offsetof(Entry, showChar), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), + DEF_ENTRY_STATE, -1, offsetof(Entry, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), + DEF_ENTRY_TAKE_FOCUS, -1, offsetof(Entry, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName), + DEF_ENTRY_TEXT_VARIABLE, -1, offsetof(Entry, textVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", - DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), + DEF_ENTRY_VALIDATE, -1, offsetof(Entry, validate), 0, validateStrings, 0}, {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand", - NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL, NULL, 0, -1, 0, "-validatecommand", 0}, {TK_OPTION_INT, "-width", "width", "Width", - DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0}, + DEF_ENTRY_WIDTH, -1, offsetof(Entry, prefWidth), 0, 0, 0}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd), + DEF_ENTRY_SCROLL_COMMAND, -1, offsetof(Entry, scrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* @@ -178,137 +184,143 @@ #define DEF_SPINBOX_VALUES "" #define DEF_SPINBOX_WRAP "0" static const Tk_OptionSpec sbOptSpec[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Background", - DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(Spinbox, activeBorder), + DEF_BUTTON_ACTIVE_BG_COLOR, -1, offsetof(Spinbox, activeBorder), 0, DEF_BUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder), + DEF_ENTRY_BG_COLOR, -1, offsetof(Entry, normalBorder), 0, DEF_ENTRY_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0}, + DEF_ENTRY_BORDER_WIDTH, -1, offsetof(Entry, borderWidth), 0, 0, 0}, {TK_OPTION_BORDER, "-buttonbackground", "Button.background", "Background", - DEF_BUTTON_BG_COLOR, -1, Tk_Offset(Spinbox, buttonBorder), + DEF_BUTTON_BG_COLOR, -1, offsetof(Spinbox, buttonBorder), 0, DEF_BUTTON_BG_MONO, 0}, {TK_OPTION_CURSOR, "-buttoncursor", "Button.cursor", "Cursor", - DEF_BUTTON_CURSOR, -1, Tk_Offset(Spinbox, bCursor), + DEF_BUTTON_CURSOR, -1, offsetof(Spinbox, bCursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-buttondownrelief", "Button.relief", "Relief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, bdRelief), 0, 0, 0}, + DEF_BUTTON_RELIEF, -1, offsetof(Spinbox, bdRelief), 0, 0, 0}, {TK_OPTION_RELIEF, "-buttonuprelief", "Button.relief", "Relief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, buRelief), 0, 0, 0}, + DEF_BUTTON_RELIEF, -1, offsetof(Spinbox, buRelief), 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", - DEF_SPINBOX_CMD, -1, Tk_Offset(Spinbox, command), + DEF_SPINBOX_CMD, -1, offsetof(Spinbox, command), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor), + DEF_ENTRY_CURSOR, -1, offsetof(Entry, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground", "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1, - Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK, + offsetof(Entry, disabledBorder), TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1, - Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, + offsetof(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1, - Tk_Offset(Entry, exportSelection), 0, 0, 0}, + offsetof(Entry, exportSelection), 0, 0, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0}, + DEF_ENTRY_FONT, -1, offsetof(Entry, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0}, + DEF_ENTRY_FG, -1, offsetof(Entry, fgColorPtr), 0, 0, 0}, {TK_OPTION_STRING, "-format", "format", "Format", - DEF_SPINBOX_FORMAT, -1, Tk_Offset(Spinbox, reqFormat), + DEF_SPINBOX_FORMAT, -1, offsetof(Spinbox, reqFormat), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-from", "from", "From", - DEF_SPINBOX_FROM, -1, Tk_Offset(Spinbox, fromValue), 0, 0, 0}, + DEF_SPINBOX_FROM, -1, offsetof(Spinbox, fromValue), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG, - -1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0}, + -1, offsetof(Entry, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0}, + DEF_ENTRY_HIGHLIGHT, -1, offsetof(Entry, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1, - Tk_Offset(Entry, highlightWidth), 0, 0, 0}, + offsetof(Entry, highlightWidth), 0, 0, 0}, {TK_OPTION_DOUBLE, "-increment", "increment", "Increment", - DEF_SPINBOX_INCREMENT, -1, Tk_Offset(Spinbox, increment), 0, 0, 0}, + DEF_SPINBOX_INCREMENT, -1, offsetof(Spinbox, increment), 0, 0, 0}, {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground", - DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0}, + DEF_ENTRY_INSERT_BG, -1, offsetof(Entry, insertBorder), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1, - Tk_Offset(Entry, insertBorderWidth), 0, + offsetof(Entry, insertBorderWidth), 0, (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0}, {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime), + DEF_ENTRY_INSERT_OFF_TIME, -1, offsetof(Entry, insertOffTime), 0, 0, 0}, {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0}, + DEF_ENTRY_INSERT_ON_TIME, -1, offsetof(Entry, insertOnTime), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0}, + DEF_ENTRY_INSERT_WIDTH, -1, offsetof(Entry, insertWidth), 0, 0, 0}, {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand", - DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd), + DEF_ENTRY_INVALIDCMD, -1, offsetof(Entry, invalidCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL, NULL, 0, -1, 0, "-invalidcommand", 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0}, + DEF_ENTRY_JUSTIFY, -1, offsetof(Entry, justify), 0, 0, 0}, + {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder", + DEF_ENTRY_PLACEHOLDER, -1, offsetof(Entry, placeholderString), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground", + "PlaceholderForeground", DEF_ENTRY_PLACEHOLDERFG, -1, + offsetof(Entry, placeholderColorPtr), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0}, + DEF_ENTRY_RELIEF, -1, offsetof(Entry, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground", "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1, - Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK, + offsetof(Entry, readonlyBorder), TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0}, {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay", - DEF_SPINBOX_REPEAT_DELAY, -1, Tk_Offset(Spinbox, repeatDelay), + DEF_SPINBOX_REPEAT_DELAY, -1, offsetof(Spinbox, repeatDelay), 0, 0, 0}, {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval", - DEF_SPINBOX_REPEAT_INTERVAL, -1, Tk_Offset(Spinbox, repeatInterval), + DEF_SPINBOX_REPEAT_INTERVAL, -1, offsetof(Spinbox, repeatInterval), 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder), + DEF_ENTRY_SELECT_COLOR, -1, offsetof(Entry, selBorder), 0, DEF_ENTRY_SELECT_MONO, 0}, {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1, - Tk_Offset(Entry, selBorderWidth), + offsetof(Entry, selBorderWidth), 0, DEF_ENTRY_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr), + DEF_ENTRY_SELECT_FG_COLOR, -1, offsetof(Entry, selFgColorPtr), TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), + DEF_ENTRY_STATE, -1, offsetof(Entry, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), + DEF_ENTRY_TAKE_FOCUS, -1, offsetof(Entry, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName), + DEF_ENTRY_TEXT_VARIABLE, -1, offsetof(Entry, textVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-to", "to", "To", - DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0}, + DEF_SPINBOX_TO, -1, offsetof(Spinbox, toValue), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", - DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), + DEF_ENTRY_VALIDATE, -1, offsetof(Entry, validate), 0, validateStrings, 0}, {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand", - NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-values", "values", "Values", - DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr), + DEF_SPINBOX_VALUES, -1, offsetof(Spinbox, valueStr), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL, NULL, 0, -1, 0, "-validatecommand", 0}, {TK_OPTION_INT, "-width", "width", "Width", - DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0}, + DEF_ENTRY_WIDTH, -1, offsetof(Entry, prefWidth), 0, 0, 0}, {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap", - DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0}, + DEF_SPINBOX_WRAP, -1, offsetof(Spinbox, wrap), 0, 0, 0}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd), + DEF_ENTRY_SCROLL_COMMAND, -1, offsetof(Entry, scrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* @@ -535,10 +547,12 @@ entryPtr->selTextGC = NULL; entryPtr->highlightGC = NULL; entryPtr->avgWidth = 1; entryPtr->validate = VALIDATE_NONE; + entryPtr->placeholderGC = NULL; + /* * Keep a hold of the associated tkwin until we destroy the entry, * otherwise Tk might free it while we still need it. */ @@ -550,11 +564,11 @@ ExposureMask|StructureNotifyMask|FocusChangeMask, EntryEventProc, entryPtr); Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING, EntryFetchSelection, entryPtr, XA_STRING); - if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin) + if ((Tk_InitOptions(interp, entryPtr, optionTable, tkwin) != TCL_OK) || (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) { Tk_DestroyWindow(entryPtr->tkwin); return TCL_ERROR; } @@ -624,14 +638,14 @@ } if ((index == entryPtr->numChars) && (index > 0)) { index--; } Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height); - bbox[0] = Tcl_NewIntObj(x + entryPtr->layoutX); - bbox[1] = Tcl_NewIntObj(y + entryPtr->layoutY); - bbox[2] = Tcl_NewIntObj(width); - bbox[3] = Tcl_NewIntObj(height); + bbox[0] = Tcl_NewWideIntObj(x + entryPtr->layoutX); + bbox[1] = Tcl_NewWideIntObj(y + entryPtr->layoutY); + bbox[2] = Tcl_NewWideIntObj(width); + bbox[3] = Tcl_NewWideIntObj(height); Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox)); break; } case COMMAND_CGET: @@ -638,21 +652,21 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, + objPtr = Tk_GetOptionValue(interp, entryPtr, entryPtr->optionTable, objv[2], entryPtr->tkwin); if (objPtr == NULL) { goto error; } Tcl_SetObjResult(interp, objPtr); break; case COMMAND_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr, + objPtr = Tk_GetOptionInfo(interp, entryPtr, entryPtr->optionTable, (objc == 3) ? objv[2] : NULL, entryPtr->tkwin); if (objPtr == NULL) { goto error; @@ -718,11 +732,11 @@ } if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), &index) != TCL_OK) { goto error; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index)); break; } case COMMAND_INSERT: { int index, code; @@ -1135,11 +1149,11 @@ if (!error) { /* * First pass: set options to new values. */ - if (Tk_SetOptions(interp, (char *) entryPtr, + if (Tk_SetOptions(interp, entryPtr, entryPtr->optionTable, objc, objv, entryPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -1175,17 +1189,19 @@ entryPtr->insertBorderWidth = entryPtr->insertWidth/2; } if (entryPtr->type == TK_SPINBOX) { if (sbPtr->fromValue > sbPtr->toValue) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "-to value must be greater than -from value", - -1)); - Tcl_SetErrorCode(interp, "TK", "SPINBOX", "RANGE_SANITY", - NULL); - continue; - } + /* + * Swap -from and -to values. + */ + + double tmpFromTo = sbPtr->fromValue; + + sbPtr->fromValue = sbPtr->toValue; + sbPtr->toValue = tmpFromTo; + } if (sbPtr->reqFormat && (oldFormat != sbPtr->reqFormat)) { /* * Make sure that the given format is somewhat correct, and * calculate the minimum space we'll need for the values as @@ -1484,13 +1500,25 @@ gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues); if (entryPtr->textGC != NULL) { Tk_FreeGC(entryPtr->display, entryPtr->textGC); } entryPtr->textGC = gc; + + if (entryPtr->placeholderColorPtr != NULL) { + gcValues.foreground = entryPtr->placeholderColorPtr->pixel; + } + mask = GCForeground | GCFont | GCGraphicsExposures; + gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues); + if (entryPtr->placeholderGC != NULL) { + Tk_FreeGC(entryPtr->display, entryPtr->placeholderGC); + } + entryPtr->placeholderGC = gc; if (entryPtr->selFgColorPtr != NULL) { gcValues.foreground = entryPtr->selFgColorPtr->pixel; + } else { + gcValues.foreground = colorPtr->pixel; } gcValues.font = Tk_FontId(entryPtr->tkfont); mask = GCForeground | GCFont; gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues); if (entryPtr->selTextGC != NULL) { @@ -1511,21 +1539,19 @@ /* *-------------------------------------------------------------- * * TkpDrawEntryBorderAndFocus -- * - * This function redraws the border of an entry widget. It overrides the - * generic border drawing code if the entry widget parameters are such - * that the native widget drawing is a good fit. This version just - * returns 0, so platforms that don't do special native drawing don't - * have to implement it. + * Stub function for Tk on platforms other than Aqua + * (Windows and X11), which do not draw native entry borders. + * See macosx/tkMacOSXEntry.c for function definition in Tk Aqua. * * Results: - * 1 if it has drawn the border, 0 if not. + * Returns 0. * * Side effects: - * May draw the entry border into pixmap. + * None. * *-------------------------------------------------------------- */ int @@ -1540,21 +1566,19 @@ /* *-------------------------------------------------------------- * * TkpDrawSpinboxButtons -- * - * This function redraws the buttons of an spinbox widget. It overrides - * the generic button drawing code if the spinbox widget parameters are - * such that the native widget drawing is a good fit. This version just - * returns 0, so platforms that don't do special native drawing don't - * have to implement it. + * Stub function for Tk on platforms other than Aqua + * (Windows and X11), which do not draw native spinbox buttons. + * See macosx/tkMacOSXEntry.c for function definition in Tk Aqua. * * Results: - * 1 if it has drawn the border, 0 if not. + * Returns 0. * * Side effects: - * May draw the entry border into pixmap. + * None. * *-------------------------------------------------------------- */ int @@ -1734,13 +1758,19 @@ /* * Draw the text in two pieces: first the unselected portion, then the * selected portion on top of it. */ - Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC, + if ((entryPtr->numChars != 0) || (entryPtr->placeholderChars == 0)) { + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC, entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, entryPtr->leftIndex, entryPtr->numChars); + } else { + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->placeholderGC, + entryPtr->placeholderLayout, entryPtr->placeholderX, entryPtr->layoutY, + entryPtr->placeholderLeftIndex, entryPtr->placeholderChars); + } if (showSelection && (entryPtr->state != STATE_DISABLED) && (entryPtr->selTextGC != entryPtr->textGC) && (entryPtr->selectFirst < entryPtr->selectLast)) { int selFirst; @@ -1948,10 +1978,62 @@ memcpy(p, buf, size); p += size; } *p = '\0'; } + + /* Recompute layout of placeholder text. + * Only the placeholderX and placeholderLeftIndex value is needed. + * We use the same font so we can use the layoutY value from below. + */ + + Tk_FreeTextLayout(entryPtr->placeholderLayout); + if (entryPtr->placeholderString) { + entryPtr->placeholderChars = strlen(entryPtr->placeholderString); + entryPtr->placeholderLayout = Tk_ComputeTextLayout(entryPtr->tkfont, + entryPtr->placeholderString, entryPtr->placeholderChars, 0, + entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, NULL); + overflow = totalLength - + (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth); + if (overflow <= 0) { + entryPtr->placeholderLeftIndex = 0; + if (entryPtr->justify == TK_JUSTIFY_LEFT) { + entryPtr->placeholderX = entryPtr->inset; + } else if (entryPtr->justify == TK_JUSTIFY_RIGHT) { + entryPtr->placeholderX = Tk_Width(entryPtr->tkwin) - entryPtr->inset + - entryPtr->xWidth - totalLength; + } else { + entryPtr->placeholderX = (Tk_Width(entryPtr->tkwin) + - entryPtr->xWidth - totalLength)/2; + } + } else { + + /* + * The whole string can't fit in the window. Compute the maximum + * number of characters that may be off-screen to the left without + * leaving empty space on the right of the window, then don't let + * placeholderLeftIndex be any greater than that. + */ + + maxOffScreen = Tk_PointToChar(entryPtr->placeholderLayout, overflow, 0); + Tk_CharBbox(entryPtr->placeholderLayout, maxOffScreen, + &rightX, NULL, NULL, NULL); + if (rightX < overflow) { + maxOffScreen++; + } + entryPtr->placeholderLeftIndex = maxOffScreen; + Tk_CharBbox(entryPtr->placeholderLayout, entryPtr->placeholderLeftIndex, &rightX, + NULL, NULL, NULL); + entryPtr->placeholderX = entryPtr->inset -rightX; + } + } else { + entryPtr->placeholderChars = 0; + entryPtr->placeholderLayout = Tk_ComputeTextLayout(entryPtr->tkfont, + entryPtr->placeholderString, 0, 0, + entryPtr->justify, TK_IGNORE_NEWLINES, NULL, NULL); + entryPtr->placeholderX = entryPtr->inset; + } Tk_FreeTextLayout(entryPtr->textLayout); entryPtr->textLayout = Tk_ComputeTextLayout(entryPtr->tkfont, entryPtr->displayString, entryPtr->numChars, 0, entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height); @@ -2044,13 +2126,11 @@ int index, /* Add the new elements before this character * index. */ const char *value) /* New characters to add (NULL-terminated * string). */ { - ptrdiff_t byteIndex; - size_t byteCount, newByteCount; - int oldChars, charsAdded; + size_t byteIndex, byteCount, newByteCount, oldChars, charsAdded; const char *string; char *newStr; string = entryPtr->string; byteIndex = Tcl_UtfAtIndex(string, index) - string; @@ -3133,12 +3213,12 @@ /* ARGSUSED */ static char * EntryTextVarProc( ClientData clientData, /* Information about button. */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Name of variable. */ - const char *name2, /* Second part of variable name. */ + const char *name1, /* Not used. */ + const char *name2, /* Not used. */ int flags) /* Information about what happened. */ { Entry *entryPtr = clientData; const char *value; @@ -3147,37 +3227,44 @@ * Just abort early if we entered here while being deleted. */ return NULL; } - /* - * See ticket [5d991b82]. - */ - - if (entryPtr->textVarName == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - EntryTextVarProc, clientData); - } - return NULL; - } - /* * If the variable is unset, then immediately recreate it unless the whole * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && entryPtr->textVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + entryPtr->textVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + EntryTextVarProc, probe); + if (probe == (ClientData)entryPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2(interp, entryPtr->textVarName, NULL, entryPtr->string, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, clientData); entryPtr->flags |= ENTRY_VAR_TRACED; - } + } return NULL; } /* * Update the entry's text with the value of the variable, unless the @@ -3262,11 +3349,11 @@ * This function is invoked when any character is added or removed from * the entry widget, or a focus has trigerred validation. * * Results: * TCL_OK if the validatecommand accepts the new string, TCL_ERROR if any - * problems occured with validatecommand. + * problems occurred with validatecommand. * * Side effects: * The insertion/deletion may be aborted, and the validatecommand might * turn itself off (if an error or loop condition arises). * @@ -3319,11 +3406,11 @@ Tcl_DStringFree(&script); /* * If e->validate has become VALIDATE_NONE during the validation, or we * now have VALIDATE_VAR set (from EntrySetValue) and didn't before, it - * means that a loop condition almost occured. Do not allow this + * means that a loop condition almost occurred. Do not allow this * validation result to finish. */ if (entryPtr->validate == VALIDATE_NONE || (!varValidate && (entryPtr->flags & VALIDATE_VAR))) { @@ -3656,10 +3743,12 @@ sbPtr->increment = 1.0; sbPtr->formatBuf = ckalloc(TCL_DOUBLE_SPACE); sbPtr->bdRelief = TK_RELIEF_FLAT; sbPtr->buRelief = TK_RELIEF_FLAT; + entryPtr->placeholderGC = NULL; + /* * Keep a hold of the associated tkwin until we destroy the spinbox, * otherwise Tk might free it while we still need it. */ @@ -3671,11 +3760,11 @@ PointerMotionMask|ExposureMask|StructureNotifyMask|FocusChangeMask, EntryEventProc, entryPtr); Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING, EntryFetchSelection, entryPtr, XA_STRING); - if (Tk_InitOptions(interp, (char *) sbPtr, optionTable, tkwin) + if (Tk_InitOptions(interp, sbPtr, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(entryPtr->tkwin); return TCL_ERROR; } if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) { @@ -3752,14 +3841,14 @@ } if ((index == entryPtr->numChars) && (index > 0)) { index--; } Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height); - bbox[0] = Tcl_NewIntObj(x + entryPtr->layoutX); - bbox[1] = Tcl_NewIntObj(y + entryPtr->layoutY); - bbox[2] = Tcl_NewIntObj(width); - bbox[3] = Tcl_NewIntObj(height); + bbox[0] = Tcl_NewWideIntObj(x + entryPtr->layoutX); + bbox[1] = Tcl_NewWideIntObj(y + entryPtr->layoutY); + bbox[2] = Tcl_NewWideIntObj(width); + bbox[3] = Tcl_NewWideIntObj(height); Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox)); break; } case SB_CMD_CGET: @@ -3766,21 +3855,21 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, + objPtr = Tk_GetOptionValue(interp, entryPtr, entryPtr->optionTable, objv[2], entryPtr->tkwin); if (objPtr == NULL) { goto error; } Tcl_SetObjResult(interp, objPtr); break; case SB_CMD_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr, + objPtr = Tk_GetOptionInfo(interp, entryPtr, entryPtr->optionTable, (objc == 3) ? objv[2] : NULL, entryPtr->tkwin); if (objPtr == NULL) { goto error; } @@ -3866,11 +3955,11 @@ } if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), &index) != TCL_OK) { goto error; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index)); break; } case SB_CMD_INSERT: { int index, code; @@ -4296,20 +4385,21 @@ * Somehow the string changed from what we expected, so let's * do a search on the list to see if the current value is * there. If not, move to the first element of the list. */ - int i, listc, elemLen, length = entryPtr->numChars; + int i, listc; + TkSizeT elemLen, length = entryPtr->numChars; const char *bytes; Tcl_Obj **listv; Tcl_ListObjGetElements(interp, sbPtr->listObj, &listc, &listv); for (i = 0; i < listc; i++) { - bytes = Tcl_GetStringFromObj(listv[i], &elemLen); + bytes = TkGetStringFromObj(listv[i], &elemLen); if ((length == elemLen) && (memcmp(bytes, entryPtr->string, - (size_t) length) == 0)) { + length) == 0)) { sbPtr->eIndex = i; break; } } } Index: generic/tkEntry.h ================================================================== --- generic/tkEntry.h +++ generic/tkEntry.h @@ -126,10 +126,23 @@ char *showChar; /* Value of -show option. If non-NULL, first * character is used for displaying all * characters in entry. Malloc'ed. This is * only used by the Entry widget. */ + /* + * Fields used in displaying help text if entry value is empty + */ + + Tk_TextLayout placeholderLayout;/* Cached placeholder text layout information. */ + char *placeholderString; /* String value of placeholder. */ + int placeholderChars; /* Number of chars in placeholder. */ + XColor *placeholderColorPtr;/* Color value of placeholder foreground. */ + GC placeholderGC; /* For drawing placeholder text. */ + int placeholderX; /* Origin for layout. */ + int placeholderLeftIndex; /* Character index of left-most character + * visible in window. */ + /* * Fields whose values are derived from the current values of the * configuration settings above. */ Index: generic/tkError.c ================================================================== --- generic/tkError.c +++ generic/tkError.c @@ -162,31 +162,30 @@ * errors that might occur while the dead handlers are hanging around, but * reduces the overhead of scanning the list to clean up (particularly if * there are many handlers that stay around forever). */ - dispPtr->deleteCount += 1; - if (dispPtr->deleteCount >= 10) { + if (dispPtr->deleteCount++ >= 9) { TkErrorHandler *prevPtr; TkErrorHandler *nextPtr; - int lastSerial = LastKnownRequestProcessed(dispPtr->display); + unsigned long lastSerial = LastKnownRequestProcessed(dispPtr->display); /* * Last chance to catch errors for this handler: if no event/error * processing took place to follow up the end of this error handler * we need a round trip with the X server now. */ - if (errorPtr->lastRequest > (unsigned long) lastSerial) { + if (errorPtr->lastRequest > lastSerial) { XSync(dispPtr->display, False); } dispPtr->deleteCount = 0; errorPtr = dispPtr->errorPtr; for (prevPtr = NULL; errorPtr != NULL; errorPtr = nextPtr) { nextPtr = errorPtr->nextPtr; if ((errorPtr->lastRequest != (unsigned long) -1) - && (errorPtr->lastRequest <= (unsigned long) lastSerial)) { + && (errorPtr->lastRequest <= lastSerial)) { if (prevPtr == NULL) { dispPtr->errorPtr = nextPtr; } else { prevPtr->nextPtr = nextPtr; } Index: generic/tkEvent.c ================================================================== --- generic/tkEvent.c +++ generic/tkEvent.c @@ -137,11 +137,11 @@ * The structure below is used to store Data for the Event module that must be * kept thread-local. The "dataKey" is used to fetch the thread-specific * storage for the current thread. */ -typedef struct ThreadSpecificData { +typedef struct { int handlersActive; /* The following variable has a non-zero value * when a handler is active. */ InProgress *pendingPtr; /* Topmost search in progress, or NULL if * none. */ @@ -191,11 +191,10 @@ * Prototypes for functions that are only referenced locally within this file. */ static void CleanUpTkEvent(XEvent *eventPtr); static void DelayedMotionProc(ClientData clientData); -static int GetButtonMask(unsigned int Button); static unsigned long GetEventMaskFromXEvent(XEvent *eventPtr); static TkWindow * GetTkWindowFromXEvent(XEvent *eventPtr); static void InvokeClientMessageHandlers(ThreadSpecificData *tsdPtr, Tk_Window tkwin, XEvent *eventPtr); static int InvokeFocusHandlers(TkWindow **winPtrPtr, @@ -206,11 +205,10 @@ unsigned long mask, XEvent *eventPtr); static Window ParentXId(Display *display, Window w); static int RefreshKeyboardMappingIfNeeded(XEvent *eventPtr); static int TkXErrorHandler(ClientData clientData, XErrorEvent *errEventPtr); -static void UpdateButtonEventState(XEvent *eventPtr); static int WindowEventProc(Tcl_Event *evPtr, int flags); #ifdef TK_USE_INPUT_METHODS static void CreateXIC(TkWindow *winPtr); #endif /* TK_USE_INPUT_METHODS */ @@ -522,11 +520,11 @@ } /* *---------------------------------------------------------------------- * - * GetButtonMask -- + * TkGetButtonMask -- * * Return the proper Button${n}Mask for the button. * * Results: * A button mask. @@ -535,92 +533,20 @@ * None. * *---------------------------------------------------------------------- */ -static int -GetButtonMask( +static const unsigned long buttonMasks[] = { + 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask, + Button6Mask, Button7Mask, Button8Mask, Button9Mask +}; + +unsigned long +TkGetButtonMask( unsigned int button) { - switch (button) { - case 1: - return Button1Mask; - case 2: - return Button2Mask; - case 3: - return Button3Mask; - case 4: - return Button4Mask; - case 5: - return Button5Mask; - } - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * UpdateButtonEventState -- - * - * Update the button event state in our TkDisplay using the XEvent - * passed. We also may modify the the XEvent passed to fit some aspects - * of our TkDisplay. - * - * Results: - * None. - * - * Side effects: - * The TkDisplay's private button state may be modified. The eventPtr's - * state may be updated to reflect masks stored in our TkDisplay that the - * event doesn't contain. The eventPtr may also be modified to not - * contain a button state for the window in which it was not pressed in. - * - *---------------------------------------------------------------------- - */ - -static void -UpdateButtonEventState( - XEvent *eventPtr) -{ - TkDisplay *dispPtr; - int allButtonsMask = Button1Mask | Button2Mask | Button3Mask - | Button4Mask | Button5Mask; - - switch (eventPtr->type) { - case ButtonPress: - dispPtr = TkGetDisplay(eventPtr->xbutton.display); - dispPtr->mouseButtonWindow = eventPtr->xbutton.window; - eventPtr->xbutton.state |= dispPtr->mouseButtonState; - - dispPtr->mouseButtonState |= GetButtonMask(eventPtr->xbutton.button); - break; - - case ButtonRelease: - dispPtr = TkGetDisplay(eventPtr->xbutton.display); - dispPtr->mouseButtonWindow = None; - dispPtr->mouseButtonState &= ~GetButtonMask(eventPtr->xbutton.button); - eventPtr->xbutton.state |= dispPtr->mouseButtonState; - break; - - case MotionNotify: - dispPtr = TkGetDisplay(eventPtr->xmotion.display); - if (dispPtr->mouseButtonState & allButtonsMask) { - if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) { - /* - * This motion event should not be interpreted as a button - * press + motion event since this is not the same window the - * button was pressed down in. - */ - - dispPtr->mouseButtonState &= ~allButtonsMask; - dispPtr->mouseButtonWindow = None; - } else { - eventPtr->xmotion.state |= dispPtr->mouseButtonState; - } - } - break; - } + return (button > Button9) ? 0 : buttonMasks[button]; } /* *---------------------------------------------------------------------- * @@ -1218,12 +1144,10 @@ InProgress ip; Tcl_Interp *interp = NULL; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - UpdateButtonEventState(eventPtr); - /* * If the generic handler processed this event we are done and can return. */ if (InvokeGenericHandlers(tsdPtr, eventPtr)) { Index: generic/tkFileFilter.c ================================================================== --- generic/tkFileFilter.c +++ generic/tkFileFilter.c @@ -260,12 +260,12 @@ * static to the MacOS X/Darwin version of Tcl, and would therefore * require further code refactoring. */ for (i=0; inext = NULL; if (globCount > 0 && globList != NULL) { for (i=0; iflags & TK_ALREADY_DEAD) { return; } + /* + * Get the current focus window with the same display and application + * as winPtr. + */ + displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); /* - * If force is set, we should make sure we grab the focus regardless of - * the current focus window since under Windows, we may need to take - * control away from another application. + * Do nothing if the window already has focus and force is not set. If + * force is set, we need to grab the focus, since under Windows or macOS + * this may involve taking control away from another application. */ if (winPtr == displayFocusPtr->focusWinPtr && !force) { return; } /* - * Find the top-level window for winPtr, then find (or create) a record - * for the top-level. Also see whether winPtr and all its ancestors are + * Find the toplevel window for winPtr, then find (or create) a record + * for the toplevel. Also see whether winPtr and all its ancestors are * mapped. */ allMapped = 1; for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) { if (topLevelPtr == NULL) { + /* * The window is being deleted. No point in worrying about giving * it the focus. */ @@ -586,15 +592,15 @@ break; } } /* - * If the new focus window isn't mapped, then we can't focus on it (X will - * generate an error, for example). Instead, create an event handler that - * will set the focus to this window once it gets mapped. At the same - * time, delete any old handler that might be around; it's no longer - * relevant. + * If any ancestor of the new focus window isn't mapped, then we can't set + * focus for it (X will generate an error, for example). Instead, create + * an event handler that will set the focus to this window once it gets + * mapped. At the same time, delete any old handler that might be around; + * it's no longer relevant. */ if (displayFocusPtr->focusOnMapPtr != NULL) { Tk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr, StructureNotifyMask, FocusMapProc, @@ -621,32 +627,40 @@ tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr; winPtr->mainPtr->tlFocusPtr = tlFocusPtr; } tlFocusPtr->focusWinPtr = winPtr; - /* - * Reset the window system's focus window and generate focus events, with - * two special cases: - * - * 1. If the application is embedded and doesn't currently have the focus, - * don't set the focus directly. Instead, see if the embedding code can - * claim the focus from the enclosing container. - * 2. Otherwise, if the application doesn't currently have the focus, - * don't change the window system's focus unless it was already in this - * application or "force" was specified. - */ - - if ((topLevelPtr->flags & TK_EMBEDDED) - && (displayFocusPtr->focusWinPtr == NULL)) { + if (topLevelPtr->flags & TK_EMBEDDED) { + + /* + * We are assigning focus to an embedded toplevel. The platform + * specific function TkpClaimFocus needs to handle the job of + * assigning focus to the container, since we have no way to find the + * contaiuner. + */ + TkpClaimFocus(topLevelPtr, force); } else if ((displayFocusPtr->focusWinPtr != NULL) || force) { + + /* + * If we are forcing removal of focus from a container hosting a + * toplevel from a different application, clear the focus in that + * application. + */ + + if (force) { + TkWindow *focusPtr = winPtr->dispPtr->focusPtr; + if (focusPtr && focusPtr->mainPtr != winPtr->mainPtr) { + DisplayFocusInfo *displayFocusPtr2 = FindDisplayFocusInfo( + focusPtr->mainPtr, focusPtr->dispPtr); + displayFocusPtr2->focusWinPtr = NULL; + } + } + /* - * Generate events to shift focus between Tk windows. We do this - * regardless of what TkpChangeFocus does with the real X focus so - * that Tk widgets track focus commands when there is no window - * manager. GenerateFocusEvents will set up a serial number marker so - * we discard focus events that are triggered by the ChangeFocus. + * Call the platform specific function TkpChangeFocus to move the + * window manager's focus to a new toplevel. */ serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force); if (serial != 0) { displayFocusPtr->focusSerial = serial; Index: generic/tkFont.c ================================================================== --- generic/tkFont.c +++ generic/tkFont.c @@ -39,11 +39,11 @@ * for each named font that has been defined. The named font is only deleted * when the last reference to it goes away. */ typedef struct NamedFont { - int refCount; /* Number of users of named font. */ + size_t refCount; /* Number of users of named font. */ int deletePending; /* Non-zero if font should be deleted when * last reference goes away. */ TkFontAttributes fa; /* Desired attributes for named font. */ } NamedFont; @@ -349,11 +349,11 @@ const Tcl_ObjType tkFontObjType = { "font", /* name */ FreeFontObjProc, /* freeIntRepProc */ DupFontObjProc, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetFontFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* *--------------------------------------------------------------------------- * @@ -561,13 +561,13 @@ * The 'charPtr' arg must be a single Unicode. */ if (charPtr != NULL) { const char *string = Tcl_GetString(charPtr); - int len = TkUtfToUniChar(string, &uniChar); + size_t len = TkUtfToUniChar(string, &uniChar); - if (len != charPtr->length) { + if (len != (size_t)charPtr->length) { resultPtr = Tcl_NewStringObj( "expected a single character but got \"", -1); Tcl_AppendLimitedToObj(resultPtr, string, -1, 40, "..."); Tcl_AppendToObj(resultPtr, "\"", -1); @@ -710,11 +710,12 @@ break; } case FONT_MEASURE: { const char *string; Tk_Font tkfont; - int length = 0, skip = 0; + TkSizeT length = 0; + int skip = 0; if (objc > 4) { skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); if (skip < 0) { return TCL_ERROR; @@ -727,12 +728,12 @@ } tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); if (tkfont == NULL) { return TCL_ERROR; } - string = Tcl_GetStringFromObj(objv[3 + skip], &length); - Tcl_SetObjResult(interp, Tcl_NewIntObj( + string = TkGetStringFromObj(objv[3 + skip], &length); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( Tk_TextWidth(tkfont, string, length))); Tk_FreeFont(tkfont); break; } case FONT_METRICS: { @@ -775,11 +776,11 @@ case 0: i = fmPtr->ascent; break; case 1: i = fmPtr->descent; break; case 2: i = fmPtr->ascent + fmPtr->descent; break; case 3: i = fmPtr->fixed; break; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(i)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i)); } Tk_FreeFont(tkfont); break; } case FONT_NAMES: { @@ -1421,23 +1422,21 @@ NamedFont *nfPtr; if (fontPtr == NULL) { return; } - fontPtr->resourceRefCount--; - if (fontPtr->resourceRefCount > 0) { + if (fontPtr->resourceRefCount-- > 1) { return; } if (fontPtr->namedHashPtr != NULL) { /* * This font derived from a named font. Reduce the reference count on * the named font and free it if no-one else is using it. */ nfPtr = Tcl_GetHashValue(fontPtr->namedHashPtr); - nfPtr->refCount--; - if ((nfPtr->refCount == 0) && nfPtr->deletePending) { + if ((nfPtr->refCount-- <= 1) && nfPtr->deletePending) { Tcl_DeleteHashEntry(fontPtr->namedHashPtr); ckfree(nfPtr); } } @@ -1520,12 +1519,11 @@ Tcl_Obj *objPtr) /* The object we are releasing. */ { TkFont *fontPtr = objPtr->internalRep.twoPtrValue.ptr1; if (fontPtr != NULL) { - fontPtr->objRefCount--; - if ((fontPtr->resourceRefCount == 0) && (fontPtr->objRefCount == 0)) { + if ((fontPtr->objRefCount-- <= 1) && (fontPtr->resourceRefCount == 0)) { ckfree(fontPtr); } objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->internalRep.twoPtrValue.ptr2 = NULL; } @@ -1713,19 +1711,15 @@ while (isspace(UCHAR(*src))) { /* INTL: ISO space */ src++; upper = 1; } src += TkUtfToUniChar(src, &ch); - if (ch <= 0xffff) { - if (upper) { - ch = Tcl_UniCharToUpper(ch); - upper = 0; - } else { - ch = Tcl_UniCharToLower(ch); - } - } else { - upper = 0; + if (upper) { + ch = Tcl_UniCharToUpper(ch); + upper = 0; + } else { + ch = Tcl_UniCharToLower(ch); } dest += TkUniCharToUtf(ch, dest); } *dest = '\0'; Tcl_DStringSetLength(dsPtr, dest - Tcl_DStringValue(dsPtr)); @@ -3248,11 +3242,12 @@ { TextLayout *layoutPtr = (TextLayout *) layout; LayoutChunk *chunkPtr = layoutPtr->chunks; int baseline = chunkPtr->y; Tcl_Obj *psObj = Tcl_NewObj(); - int i, j, len; + int i, j; + TkSizeT len; const char *p, *glyphname; char uindex[5], c, *ps; int ch; Tcl_AppendToObj(psObj, "[(", -1); @@ -3306,11 +3301,11 @@ goto noMapping; } sprintf(uindex, "%04X", ch); /* endianness? */ glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", uindex, 0); if (glyphname) { - ps = Tcl_GetStringFromObj(psObj, &len); + ps = TkGetStringFromObj(psObj, &len); if (ps[len-1] == '(') { /* * In-place edit. Ewww! */ @@ -3497,13 +3492,13 @@ valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1)); break; case FONT_SIZE: if (faPtr->size >= 0.0) { - valuePtr = Tcl_NewIntObj((int)(faPtr->size + 0.5)); + valuePtr = Tcl_NewWideIntObj((Tcl_WideInt)(faPtr->size + 0.5)); } else { - valuePtr = Tcl_NewIntObj(-(int)(-faPtr->size + 0.5)); + valuePtr = Tcl_NewWideIntObj(-(Tcl_WideInt)(-faPtr->size + 0.5)); } break; case FONT_WEIGHT: str = TkFindStateString(weightMap, faPtr->weight); @@ -4207,13 +4202,13 @@ Tcl_Panic("TkDebugFont found empty hash table entry"); } for ( ; (fontPtr != NULL); fontPtr = fontPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(fontPtr->resourceRefCount)); + Tcl_NewWideIntObj(fontPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(fontPtr->objRefCount)); + Tcl_NewWideIntObj(fontPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } @@ -4253,11 +4248,11 @@ dst[0] = '\0'; return 0; } chunkPtr = layoutPtr->chunks; numBytesInChunk = chunkPtr->numBytes; - strncpy(dst, chunkPtr->start, (size_t) numBytesInChunk); + strncpy(dst, chunkPtr->start, numBytesInChunk); *font = layoutPtr->tkfont; return numBytesInChunk; } /* Index: generic/tkFont.h ================================================================== --- generic/tkFont.h +++ generic/tkFont.h @@ -83,21 +83,21 @@ typedef struct TkFont { /* * Fields used and maintained exclusively by generic code. */ - int resourceRefCount; /* Number of active uses of this font (each + TkSizeT resourceRefCount; /* Number of active uses of this font (each * active use corresponds to a call to * Tk_AllocFontFromTable or Tk_GetFont). If * this count is 0, then this TkFont structure * is no longer valid and it isn't present in * a hash table: it is being kept around only * because there are objects referring to it. * The structure is freed when * resourceRefCount and objRefCount are both * 0. */ - int objRefCount; /* The number of Tcl objects that reference + TkSizeT objRefCount; /* The number of Tcl objects that reference * this structure. */ Tcl_HashEntry *cacheHashPtr;/* Entry in font cache for this structure, * used when deleting it. */ Tcl_HashEntry *namedHashPtr;/* Pointer to hash table entry that * corresponds to the named font that the Index: generic/tkFrame.c ================================================================== --- generic/tkFrame.c +++ generic/tkFrame.c @@ -10,12 +10,12 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" +#include "default.h" /* * The following enum is used to define the type of the frame. */ @@ -92,10 +92,20 @@ int padX; /* Integer value corresponding to padXPtr. */ Tcl_Obj *padYPtr; /* Value of -padx option: specifies how many * pixels of extra space to leave above and * below child area. */ int padY; /* Integer value corresponding to padYPtr. */ + Tcl_Obj *bgimgPtr; /* Value of -backgroundimage option: specifies + * image to display on window's background, or + * NULL if none. */ + Tk_Image bgimg; /* Derived from bgimgPtr by calling + * Tk_GetImage, or NULL if bgimgPtr is + * NULL. */ + int tile; /* Whether to tile the bgimg. */ +#ifndef TK_NO_DOUBLE_BUFFERING + GC copyGC; /* GC for copying when double-buffering. */ +#endif /* TK_NO_DOUBLE_BUFFERING */ } Frame; /* * A data structure of the following type is kept for each labelframe widget * managed by this file: @@ -172,112 +182,126 @@ * table used by all and one table for each widget class. */ static const Tk_OptionSpec commonOptSpec[] = { {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_FRAME_BG_COLOR, -1, Tk_Offset(Frame, border), + DEF_FRAME_BG_COLOR, -1, offsetof(Frame, border), TK_OPTION_NULL_OK, DEF_FRAME_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_STRING, "-colormap", "colormap", "Colormap", - DEF_FRAME_COLORMAP, -1, Tk_Offset(Frame, colormapName), + DEF_FRAME_COLORMAP, -1, offsetof(Frame, colormapName), TK_OPTION_NULL_OK, 0, 0}, /* * Having -container is useless in a labelframe since a container has * no border. It should be deprecated. */ {TK_OPTION_BOOLEAN, "-container", "container", "Container", - DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer), 0, 0, 0}, + DEF_FRAME_CONTAINER, -1, offsetof(Frame, isContainer), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_FRAME_CURSOR, -1, Tk_Offset(Frame, cursor), + DEF_FRAME_CURSOR, -1, offsetof(Frame, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-height", "height", "Height", - DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height), 0, 0, 0}, + DEF_FRAME_HEIGHT, -1, offsetof(Frame, height), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, -1, - Tk_Offset(Frame, highlightBgColorPtr), 0, 0, 0}, + offsetof(Frame, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_FRAME_HIGHLIGHT, -1, Tk_Offset(Frame, highlightColorPtr), + DEF_FRAME_HIGHLIGHT, -1, offsetof(Frame, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, -1, - Tk_Offset(Frame, highlightWidth), 0, 0, 0}, + offsetof(Frame, highlightWidth), 0, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - DEF_FRAME_PADX, Tk_Offset(Frame, padXPtr), - Tk_Offset(Frame, padX), 0, 0, 0}, + DEF_FRAME_PADX, offsetof(Frame, padXPtr), + offsetof(Frame, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - DEF_FRAME_PADY, Tk_Offset(Frame, padYPtr), - Tk_Offset(Frame, padY), 0, 0, 0}, + DEF_FRAME_PADY, offsetof(Frame, padYPtr), + offsetof(Frame, padY), 0, 0, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_FRAME_TAKE_FOCUS, -1, Tk_Offset(Frame, takeFocus), + DEF_FRAME_TAKE_FOCUS, -1, offsetof(Frame, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-visual", "visual", "Visual", - DEF_FRAME_VISUAL, -1, Tk_Offset(Frame, visualName), + DEF_FRAME_VISUAL, -1, offsetof(Frame, visualName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-width", "width", "Width", - DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width), 0, 0, 0}, + DEF_FRAME_WIDTH, -1, offsetof(Frame, width), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; static const Tk_OptionSpec frameOptSpec[] = { + {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage", + DEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), -1, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bgimg", NULL, NULL, + NULL, 0, -1, 0, "-backgroundimage", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0}, + DEF_FRAME_BORDER_WIDTH, -1, offsetof(Frame, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-class", "class", "Class", - DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, + DEF_FRAME_CLASS, -1, offsetof(Frame, className), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0}, + DEF_FRAME_RELIEF, -1, offsetof(Frame, relief), 0, 0, 0}, + {TK_OPTION_BOOLEAN, "-tile", "tile", "Tile", + DEF_FRAME_BG_TILE, -1, offsetof(Frame, tile), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, commonOptSpec, 0} }; static const Tk_OptionSpec toplevelOptSpec[] = { + {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage", + DEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), -1, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bgimg", NULL, NULL, + NULL, 0, -1, 0, "-backgroundimage", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0}, + DEF_FRAME_BORDER_WIDTH, -1, offsetof(Frame, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-class", "class", "Class", - DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, + DEF_TOPLEVEL_CLASS, -1, offsetof(Frame, className), 0, 0, 0}, {TK_OPTION_STRING, "-menu", "menu", "Menu", - DEF_TOPLEVEL_MENU, -1, Tk_Offset(Frame, menuName), + DEF_TOPLEVEL_MENU, -1, offsetof(Frame, menuName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0}, + DEF_FRAME_RELIEF, -1, offsetof(Frame, relief), 0, 0, 0}, {TK_OPTION_STRING, "-screen", "screen", "Screen", - DEF_TOPLEVEL_SCREEN, -1, Tk_Offset(Frame, screenName), + DEF_TOPLEVEL_SCREEN, -1, offsetof(Frame, screenName), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_BOOLEAN, "-tile", "tile", "Tile", + DEF_FRAME_BG_TILE, -1, offsetof(Frame, tile), 0, 0, 0}, {TK_OPTION_STRING, "-use", "use", "Use", - DEF_TOPLEVEL_USE, -1, Tk_Offset(Frame, useThis), + DEF_TOPLEVEL_USE, -1, offsetof(Frame, useThis), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, commonOptSpec, 0} }; static const Tk_OptionSpec labelframeOptSpec[] = { {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_LABELFRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), + DEF_LABELFRAME_BORDER_WIDTH, -1, offsetof(Frame, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-class", "class", "Class", - DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, + DEF_LABELFRAME_CLASS, -1, offsetof(Frame, className), 0, 0, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_LABELFRAME_FONT, -1, Tk_Offset(Labelframe, tkfont), 0, 0, 0}, + DEF_LABELFRAME_FONT, -1, offsetof(Labelframe, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_LABELFRAME_FG, -1, Tk_Offset(Labelframe, textColorPtr), 0, 0, 0}, + DEF_LABELFRAME_FG, -1, offsetof(Labelframe, textColorPtr), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-labelanchor", "labelAnchor", "LabelAnchor", - DEF_LABELFRAME_LABELANCHOR, -1, Tk_Offset(Labelframe, labelAnchor), + DEF_LABELFRAME_LABELANCHOR, -1, offsetof(Labelframe, labelAnchor), 0, labelAnchorStrings, 0}, {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", - NULL, -1, Tk_Offset(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0}, + DEF_LABELFRAME_RELIEF, -1, offsetof(Frame, relief), 0, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_LABELFRAME_TEXT, Tk_Offset(Labelframe, textPtr), -1, + DEF_LABELFRAME_TEXT, offsetof(Labelframe, textPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, commonOptSpec, 0} }; @@ -309,10 +333,16 @@ int objc, Tcl_Obj *const argv[], enum FrameType type, const char *appName); static void DestroyFrame(void *memPtr); static void DestroyFramePartly(Frame *framePtr); static void DisplayFrame(ClientData clientData); +static void DrawFrameBackground(Tk_Window tkwin, Pixmap pixmap, + int highlightWidth, int borderWidth, + Tk_Image bgimg, int bgtile); +static void FrameBgImageProc(ClientData clientData, + int x, int y, int width, int height, + int imgWidth, int imgHeight); static void FrameCmdDeletedProc(ClientData clientData); static void FrameEventProc(ClientData clientData, XEvent *eventPtr); static void FrameLostSlaveProc(ClientData clientData, Tk_Window tkwin); @@ -486,11 +516,12 @@ Frame *framePtr; Tk_OptionTable optionTable; Tk_Window newWin; const char *className, *screenName, *visualName, *colormapName; const char *arg, *useOption; - int i, length, depth; + int i, depth; + TkSizeT length; unsigned int mask; Colormap colormap; Visual *visual; if (objc < 2) { @@ -513,28 +544,28 @@ */ className = colormapName = screenName = visualName = useOption = NULL; colormap = None; for (i = 2; i < objc; i += 2) { - arg = Tcl_GetStringFromObj(objv[i], &length); + arg = TkGetStringFromObj(objv[i], &length); if (length < 2) { continue; } if ((arg[1] == 'c') && (length >= 3) - && (strncmp(arg, "-class", (unsigned) length) == 0)) { + && (strncmp(arg, "-class", length) == 0)) { className = Tcl_GetString(objv[i+1]); } else if ((arg[1] == 'c') && (length >= 3) - && (strncmp(arg, "-colormap", (unsigned) length) == 0)) { + && (strncmp(arg, "-colormap", length) == 0)) { colormapName = Tcl_GetString(objv[i+1]); } else if ((arg[1] == 's') && (type == TYPE_TOPLEVEL) - && (strncmp(arg, "-screen", (unsigned) length) == 0)) { + && (strncmp(arg, "-screen", length) == 0)) { screenName = Tcl_GetString(objv[i+1]); } else if ((arg[1] == 'u') && (type == TYPE_TOPLEVEL) - && (strncmp(arg, "-use", (unsigned) length) == 0)) { + && (strncmp(arg, "-use", length) == 0)) { useOption = Tcl_GetString(objv[i+1]); } else if ((arg[1] == 'v') - && (strncmp(arg, "-visual", (unsigned) length) == 0)) { + && (strncmp(arg, "-visual", length) == 0)) { visualName = Tcl_GetString(objv[i+1]); } } /* @@ -680,11 +711,11 @@ mask = ExposureMask | StructureNotifyMask | FocusChangeMask; if (type == TYPE_TOPLEVEL) { mask |= ActivateMask; } Tk_CreateEventHandler(newWin, mask, FrameEventProc, framePtr); - if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, newWin) + if ((Tk_InitOptions(interp, framePtr, optionTable, newWin) != TCL_OK) || (ConfigureFrame(interp, framePtr, objc-2, objv+2) != TCL_OK)) { goto error; } if (framePtr->isContainer) { @@ -741,11 +772,12 @@ enum options { FRAME_CGET, FRAME_CONFIGURE }; register Frame *framePtr = clientData; int result = TCL_OK, index; - int c, i, length; + int c, i; + TkSizeT length; Tcl_Obj *objPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; @@ -760,21 +792,21 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; goto done; } - objPtr = Tk_GetOptionValue(interp, (char *) framePtr, + objPtr = Tk_GetOptionValue(interp, framePtr, framePtr->optionTable, objv[2], framePtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; goto done; } Tcl_SetObjResult(interp, objPtr); break; case FRAME_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) framePtr, + objPtr = Tk_GetOptionInfo(interp, framePtr, framePtr->optionTable, (objc == 3) ? objv[2] : NULL, framePtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; goto done; @@ -785,28 +817,28 @@ * Don't allow the options -class, -colormap, -container, -screen, * -use, or -visual to be changed. */ for (i = 2; i < objc; i++) { - const char *arg = Tcl_GetStringFromObj(objv[i], &length); + const char *arg = TkGetStringFromObj(objv[i], &length); if (length < 2) { continue; } c = arg[1]; if (((c == 'c') && (length >= 2) - && (strncmp(arg, "-class", (unsigned)length) == 0)) + && (strncmp(arg, "-class", length) == 0)) || ((c == 'c') && (length >= 3) - && (strncmp(arg, "-colormap", (unsigned)length) == 0)) + && (strncmp(arg, "-colormap", length) == 0)) || ((c == 'c') && (length >= 3) - && (strncmp(arg, "-container", (unsigned)length) == 0)) + && (strncmp(arg, "-container", length) == 0)) || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL) - && (strncmp(arg, "-screen", (unsigned)length) == 0)) + && (strncmp(arg, "-screen", length) == 0)) || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL) - && (strncmp(arg, "-use", (unsigned)length) == 0)) + && (strncmp(arg, "-use", length) == 0)) || ((c == 'v') - && (strncmp(arg, "-visual", (unsigned)length) == 0))) { + && (strncmp(arg, "-visual", length) == 0))) { #ifdef SUPPORT_CONFIG_EMBEDDED if (c == 'u') { const char *string = Tcl_GetString(objv[i+1]); @@ -866,13 +898,21 @@ Tk_FreeTextLayout(labelframePtr->textLayout); if (labelframePtr->textGC != NULL) { Tk_FreeGC(framePtr->display, labelframePtr->textGC); } } +#ifndef TK_NO_DOUBLE_BUFFERING + if (framePtr->copyGC != NULL) { + Tk_FreeGC(framePtr->display, framePtr->copyGC); + } +#endif /* TK_NO_DOUBLE_BUFFERING */ if (framePtr->colormap != None) { Tk_FreeColormap(framePtr->display, framePtr->colormap); } + if (framePtr->bgimg) { + Tk_FreeImage(framePtr->bgimg); + } ckfree(framePtr); } /* *---------------------------------------------------------------------- @@ -943,10 +983,11 @@ { Tk_SavedOptions savedOptions; char *oldMenuName; Tk_Window oldWindow = NULL; Labelframe *labelframePtr = (Labelframe *) framePtr; + Tk_Image image = NULL; /* * Need the old menubar name for the menu code to delete it. */ @@ -958,18 +999,32 @@ } if (framePtr->type == TYPE_LABELFRAME) { oldWindow = labelframePtr->labelWin; } - if (Tk_SetOptions(interp, (char *) framePtr, + if (Tk_SetOptions(interp, framePtr, framePtr->optionTable, objc, objv, framePtr->tkwin, &savedOptions, NULL) != TCL_OK) { if (oldMenuName != NULL) { ckfree(oldMenuName); } return TCL_ERROR; } + + if (framePtr->bgimgPtr) { + image = Tk_GetImage(interp, framePtr->tkwin, + Tcl_GetString(framePtr->bgimgPtr), FrameBgImageProc, framePtr); + if (image == NULL) { + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; + } + } + if (framePtr->bgimg) { + Tk_FreeImage(framePtr->bgimg); + } + framePtr->bgimg = image; + Tk_FreeSavedOptions(&savedOptions); /* * A few of the options require additional processing. */ @@ -1107,10 +1162,19 @@ (labelframePtr->textPtr != NULL) && (labelframePtr->labelWin == NULL); anyWindowLabel = (framePtr->type == TYPE_LABELFRAME) && (labelframePtr->labelWin != NULL); +#ifndef TK_NO_DOUBLE_BUFFERING + gcValues.graphics_exposures = False; + gc = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues); + if (framePtr->copyGC != NULL) { + Tk_FreeGC(framePtr->display, framePtr->copyGC); + } + framePtr->copyGC = gc; +#endif /* TK_NO_DOUBLE_BUFFERING */ + if (framePtr->type == TYPE_LABELFRAME) { /* * The textGC is needed even in the labelWin case, so it's always * created for a labelframe. */ @@ -1451,41 +1515,45 @@ if (framePtr->border == NULL) { return; } +#ifndef TK_NO_DOUBLE_BUFFERING + /* + * In order to avoid screen flashes, this function redraws the frame into + * off-screen memory, then copies it back on-screen in a single operation. + * This means there's no point in time where the on-screen image has been + * cleared. + */ + + pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); +#else + pixmap = Tk_WindowId(tkwin); +#endif /* TK_NO_DOUBLE_BUFFERING */ + if (framePtr->type != TYPE_LABELFRAME) { /* * Pass to platform specific draw function. In general, it just draws * a simple rectangle, but it may "theme" the background. */ noLabel: - TkpDrawFrame(tkwin, framePtr->border, hlWidth, + TkpDrawFrameEx(tkwin, pixmap, framePtr->border, hlWidth, framePtr->borderWidth, framePtr->relief); + if (framePtr->bgimg) { + DrawFrameBackground(tkwin, pixmap, hlWidth, framePtr->borderWidth, + framePtr->bgimg, framePtr->tile); + } } else { Labelframe *labelframePtr = (Labelframe *) framePtr; if ((labelframePtr->textPtr == NULL) && (labelframePtr->labelWin == NULL)) { goto noLabel; } -#ifndef TK_NO_DOUBLE_BUFFERING - /* - * In order to avoid screen flashes, this function redraws the frame - * into off-screen memory, then copies it back on-screen in a single - * operation. This means there's no point in time where the on-screen - * image has been cleared. - */ - - pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin), - Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); -#else - pixmap = Tk_WindowId(tkwin); -#endif /* TK_NO_DOUBLE_BUFFERING */ - /* * Clear the pixmap. */ Tk_Fill3DRectangle(tkwin, pixmap, framePtr->border, 0, 0, @@ -1593,26 +1661,58 @@ labelframePtr->labelBox.x, labelframePtr->labelBox.y, labelframePtr->labelBox.width, labelframePtr->labelBox.height); } } + } #ifndef TK_NO_DOUBLE_BUFFERING - /* - * Everything's been redisplayed; now copy the pixmap onto the screen - * and free up the pixmap. - */ - - XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin), - labelframePtr->textGC, hlWidth, hlWidth, - (unsigned) (Tk_Width(tkwin) - 2 * hlWidth), - (unsigned) (Tk_Height(tkwin) - 2 * hlWidth), - hlWidth, hlWidth); - Tk_FreePixmap(framePtr->display, pixmap); + /* + * Everything's been redisplayed; now copy the pixmap onto the screen and + * free up the pixmap. + */ + + XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin), + framePtr->copyGC, hlWidth, hlWidth, + (unsigned) (Tk_Width(tkwin) - 2 * hlWidth), + (unsigned) (Tk_Height(tkwin) - 2 * hlWidth), + hlWidth, hlWidth); + Tk_FreePixmap(framePtr->display, pixmap); #endif /* TK_NO_DOUBLE_BUFFERING */ - } +} + +/* + *---------------------------------------------------------------------- + * + * TkpDrawFrame -- + * + * This procedure draws the rectangular frame area. + * + * Results: + * None. + * + * Side effects: + * Draws inside the tkwin area. + * + *---------------------------------------------------------------------- + */ + +void +TkpDrawFrame( + Tk_Window tkwin, + Tk_3DBorder border, + int highlightWidth, + int borderWidth, + int relief) +{ + /* + * Legacy shim to allow for external callers. Internal ones use + * non-exposed TkpDrawFrameEx directly so they can use double-buffering. + */ + TkpDrawFrameEx(tkwin, Tk_WindowId(tkwin), border, + highlightWidth, borderWidth, relief); } /* *-------------------------------------------------------------- * @@ -2026,13 +2126,135 @@ if (framePtr->type != TYPE_TOPLEVEL) { return NULL; } return framePtr->tkwin; } + +/* + *---------------------------------------------------------------------- + * + * FrameBgImageProc -- + * + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size or contents of an image + * displayed on a frame's background. + * + * Results: + * None. + * + * Side effects: + * Arranges for the button to get redisplayed. + * + *---------------------------------------------------------------------- + */ + +static void +FrameBgImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (might be + * <= 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ +{ + register Frame *framePtr = clientData; + + /* + * Changing the background image never alters the dimensions of the frame. + */ + + if (framePtr->tkwin && Tk_IsMapped(framePtr->tkwin) && + !(framePtr->flags & REDRAW_PENDING)) { + Tcl_DoWhenIdle(DisplayFrame, framePtr); + framePtr->flags |= REDRAW_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawFrameBackground -- + * + * This function draws the background image of a rectangular frame area. + * + * Results: + * None. + * + * Side effects: + * Draws inside the tkwin area. + * + *---------------------------------------------------------------------- + */ + +static void +DrawFrameBackground( + Tk_Window tkwin, + Pixmap pixmap, + int highlightWidth, + int borderWidth, + Tk_Image bgimg, + int bgtile) +{ + int width, height; /* Area to paint on. */ + int imageWidth, imageHeight; /* Dimensions of image. */ + const int bw = highlightWidth + borderWidth; + + Tk_SizeOfImage(bgimg, &imageWidth, &imageHeight); + width = Tk_Width(tkwin) - 2*bw; + height = Tk_Height(tkwin) - 2*bw; + + if (bgtile) { + /* + * Draw the image tiled in the widget (inside the border). + */ + + int x, y; + + for (x = bw; x - bw < width; x += imageWidth) { + int w = imageWidth; + if (x - bw + imageWidth > width) { + w = (width + bw) - x; + } + for (y = bw; y < height + bw; y += imageHeight) { + int h = imageHeight; + if (y - bw + imageHeight > height) { + h = (height + bw) - y; + } + Tk_RedrawImage(bgimg, 0, 0, w, h, pixmap, x, y); + } + } + } else { + /* + * Draw the image centred in the widget (inside the border). + */ + + int x, y, xOff, yOff, w, h; + + if (width > imageWidth) { + x = 0; + xOff = (Tk_Width(tkwin) - imageWidth) / 2; + w = imageWidth; + } else { + x = (imageWidth - width) / 2; + xOff = bw; + w = width; + } + if (height > imageHeight) { + y = 0; + yOff = (Tk_Height(tkwin) - imageHeight) / 2; + h = imageHeight; + } else { + y = (imageHeight - height) / 2; + yOff = bw; + h = height; + } + Tk_RedrawImage(bgimg, x, y, w, h, pixmap, xOff, yOff); + } +} /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tkGC.c ================================================================== --- generic/tkGC.c +++ generic/tkGC.c @@ -21,11 +21,11 @@ */ typedef struct { GC gc; /* Graphics context. */ Display *display; /* Display to which gc belongs. */ - int refCount; /* Number of active uses of gc. */ + size_t refCount; /* Number of active uses of gc. */ Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting * this structure). */ } TkGC; typedef struct { @@ -305,17 +305,16 @@ */ return; } - idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc); + idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, gc); if (idHashPtr == NULL) { Tcl_Panic("Tk_FreeGC received unknown gc argument"); } gcPtr = Tcl_GetHashValue(idHashPtr); - gcPtr->refCount--; - if (gcPtr->refCount == 0) { + if (gcPtr->refCount-- <= 1) { XFreeGC(gcPtr->display, gcPtr->gc); Tcl_DeleteHashEntry(gcPtr->valueHashPtr); Tcl_DeleteHashEntry(idHashPtr); ckfree(gcPtr); } Index: generic/tkGeometry.c ================================================================== --- generic/tkGeometry.c +++ generic/tkGeometry.c @@ -325,27 +325,27 @@ * set. */ const char *master) /* The master identity. */ { register TkWindow *winPtr = (TkWindow *) tkwin; - if (winPtr->geometryMaster != NULL && - strcmp(winPtr->geometryMaster, master) == 0) { + if (winPtr->geomMgrName != NULL && + strcmp(winPtr->geomMgrName, master) == 0) { return TCL_OK; } - if (winPtr->geometryMaster != NULL) { + if (winPtr->geomMgrName != NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot use geometry manager %s inside %s which already" " has slaves managed by %s", - master, Tk_PathName(tkwin), winPtr->geometryMaster)); + master, Tk_PathName(tkwin), winPtr->geomMgrName)); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "FIGHT", NULL); } return TCL_ERROR; } - winPtr->geometryMaster = ckalloc(strlen(master) + 1); - strcpy(winPtr->geometryMaster, master); + winPtr->geomMgrName = ckalloc(strlen(master) + 1); + strcpy(winPtr->geomMgrName, master); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -370,18 +370,18 @@ * cleared. */ const char *master) /* The master identity. */ { register TkWindow *winPtr = (TkWindow *) tkwin; - if (winPtr->geometryMaster != NULL && - strcmp(winPtr->geometryMaster, master) != 0) { + if (winPtr->geomMgrName != NULL && + strcmp(winPtr->geomMgrName, master) != 0) { Tcl_Panic("Trying to free %s from geometry manager %s", - winPtr->geometryMaster, master); + winPtr->geomMgrName, master); } - if (winPtr->geometryMaster != NULL) { - ckfree(winPtr->geometryMaster); - winPtr->geometryMaster = NULL; + if (winPtr->geomMgrName != NULL) { + ckfree(winPtr->geomMgrName); + winPtr->geomMgrName = NULL; } } /* *---------------------------------------------------------------------- @@ -423,10 +423,13 @@ register MaintainSlave *slavePtr; int isNew, map; Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master; + + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master; if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, don't bother * setting up the extra infrastructure for management, just make a * call to Tk_MoveResizeWindow; the parent/child relationship will @@ -568,10 +571,13 @@ MaintainMaster *masterPtr; register MaintainSlave *slavePtr, *prevPtr; Tk_Window ancestor; TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; + ((TkWindow *)slave)->maintainerPtr = NULL; + + ((TkWindow *)slave)->maintainerPtr = NULL; if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, * Tk_MaintainGeometry will not have set up any of the extra * infrastructure. Don't even bother to look for it, just return. @@ -585,11 +591,11 @@ } if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) { Tk_UnmapWindow(slave); } - hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, (char *) master); + hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, master); if (hPtr == NULL) { return; } masterPtr = Tcl_GetHashValue(hPtr); slavePtr = masterPtr->slavePtr; Index: generic/tkGet.c ================================================================== --- generic/tkGet.c +++ generic/tkGet.c @@ -20,11 +20,11 @@ * data. In this case, it is used to house the Tk_Uid structs used by each * thread. The "dataKey" below is used to locate the ThreadSpecificData for * the current thread. */ -typedef struct ThreadSpecificData { +typedef struct { int initialized; Tcl_HashTable uidTable; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; Index: generic/tkGrab.c ================================================================== --- generic/tkGrab.c +++ generic/tkGrab.c @@ -132,21 +132,10 @@ * we generated. */ #define GENERATED_GRAB_EVENT_MAGIC ((Bool) 0x147321ac) -/* - * Mask that selects any of the state bits corresponding to buttons, plus - * masks that select individual buttons' bits: - */ - -#define ALL_BUTTONS \ - (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask) -static const unsigned int buttonStates[] = { - Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask -}; - /* * Forward declarations for functions declared later in this file: */ static void EatGrabEvents(TkDisplay *dispPtr, unsigned int serial); @@ -188,11 +177,11 @@ int globalGrab; Tk_Window tkwin; TkDisplay *dispPtr; const char *arg; int index; - int len; + TkSizeT len; static const char *const optionStrings[] = { "current", "release", "set", "status", NULL }; static const char *const flagStrings[] = { "-global", NULL @@ -225,11 +214,11 @@ /* * First check for a window name or "-global" as the first argument. */ - arg = Tcl_GetStringFromObj(objv[1], &len); + arg = TkGetStringFromObj(objv[1], &len); if (arg[0] == '.') { /* [grab window] */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-global? window"); return TCL_ERROR; @@ -879,12 +868,13 @@ } dispPtr->buttonWinPtr = winPtr; return 1; } } else { - if ((eventPtr->xbutton.state & ALL_BUTTONS) - == buttonStates[eventPtr->xbutton.button - Button1]) { + if (eventPtr->xbutton.button != AnyButton && + ((eventPtr->xbutton.state & ALL_BUTTONS) + == TkGetButtonMask(eventPtr->xbutton.button))) { ReleaseButtonGrab(dispPtr); /* Note 4. */ } } if (winPtr2 != winPtr) { TkChangeEventWindow(eventPtr, winPtr2); @@ -1379,11 +1369,11 @@ */ static int GrabWinEventProc( Tcl_Event *evPtr, /* Event of type NewGrabWinEvent. */ - int flags) /* Flags argument to Tk_DoOneEvent: indicates + int flags) /* Flags argument to Tcl_DoOneEvent: indicates * what kinds of events are being processed * right now. */ { NewGrabWinEvent *grabEvPtr = (NewGrabWinEvent *) evPtr; Index: generic/tkGrid.c ================================================================== --- generic/tkGrid.c +++ generic/tkGrid.c @@ -290,12 +290,12 @@ XEvent *eventPtr); static void GridLostSlaveProc(ClientData clientData, Tk_Window tkwin); static void GridReqProc(ClientData clientData, Tk_Window tkwin); static void InitMasterData(Gridder *masterPtr); -static Tcl_Obj * NewPairObj(int, int); -static Tcl_Obj * NewQuadObj(int, int, int, int); +static Tcl_Obj * NewPairObj(Tcl_WideInt, Tcl_WideInt); +static Tcl_Obj * NewQuadObj(Tcl_WideInt, Tcl_WideInt, Tcl_WideInt, Tcl_WideInt); static int ResolveConstraints(Gridder *gridPtr, int rowOrColumn, int maxOffset); static void SetGridSize(Gridder *gridPtr); static int SetSlaveColumn(Tcl_Interp *interp, Gridder *slavePtr, int column, int numCols); @@ -739,17 +739,17 @@ infoObj = Tcl_NewObj(); Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-in", -1), TkNewWindowObj(slavePtr->masterPtr->tkwin)); Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-column", -1), - Tcl_NewIntObj(slavePtr->column)); + Tcl_NewWideIntObj(slavePtr->column)); Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-row", -1), - Tcl_NewIntObj(slavePtr->row)); + Tcl_NewWideIntObj(slavePtr->row)); Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-columnspan", -1), - Tcl_NewIntObj(slavePtr->numCols)); + Tcl_NewWideIntObj(slavePtr->numCols)); Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-rowspan", -1), - Tcl_NewIntObj(slavePtr->numRows)); + Tcl_NewWideIntObj(slavePtr->numRows)); TkAppendPadAmount(infoObj, "-ipadx", slavePtr->iPadX/2, slavePtr->iPadX); TkAppendPadAmount(infoObj, "-ipady", slavePtr->iPadY/2, slavePtr->iPadY); TkAppendPadAmount(infoObj, "-padx", slavePtr->padLeft, slavePtr->padX); TkAppendPadAmount(infoObj, "-pady", slavePtr->padTop, slavePtr->padY); Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-sticky", -1), @@ -1053,21 +1053,21 @@ uniform = slotPtr[slot].uniform; } Tcl_ListObjAppendElement(interp, res, Tcl_NewStringObj("-minsize", -1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(minsize)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(minsize)); Tcl_ListObjAppendElement(interp, res, Tcl_NewStringObj("-pad", -1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(pad)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(pad)); Tcl_ListObjAppendElement(interp, res, Tcl_NewStringObj("-uniform", -1)); Tcl_ListObjAppendElement(interp, res, Tcl_NewStringObj(uniform == NULL ? "" : uniform, -1)); Tcl_ListObjAppendElement(interp, res, Tcl_NewStringObj("-weight", -1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(weight)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(weight)); Tcl_SetObjResult(interp, res); Tcl_DecrRefCount(listCopy); return TCL_OK; } @@ -1080,22 +1080,22 @@ sizeof(char *), "option", 0, &index) != TCL_OK) { Tcl_DecrRefCount(listCopy); return TCL_ERROR; } if (index == ROWCOL_MINSIZE) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( (ok == TCL_OK) ? slotPtr[slot].minSize : 0)); } else if (index == ROWCOL_WEIGHT) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( (ok == TCL_OK) ? slotPtr[slot].weight : 0)); } else if (index == ROWCOL_UNIFORM) { Tk_Uid value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; Tcl_SetObjResult(interp, Tcl_NewStringObj( (value == NULL) ? "" : value, -1)); } else if (index == ROWCOL_PAD) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( (ok == TCL_OK) ? slotPtr[slot].pad : 0)); } Tcl_DecrRefCount(listCopy); return TCL_OK; } @@ -1730,14 +1730,13 @@ int usedX, usedY; masterPtr->flags &= ~REQUESTED_RELAYOUT; /* - * If the master has no slaves anymore, then don't do anything at all: - * just leave the master's size as-is. Otherwise there is no way to - * "relinquish" control over the master so another geometry manager can - * take over. + * If the master has no slaves anymore, then don't change the master size. + * Otherwise there is no way to "relinquish" control over the master + * so another geometry manager can take over. */ if (masterPtr->slavePtr == NULL) { return; } @@ -1911,11 +1910,11 @@ int gridCount; /* The larger of slotCount and * constraintCount. */ GridLayout *layoutPtr; /* Temporary layout structure. */ int requiredSize; /* The natural size of the grid (pixels). * This is the minimum size needed to - * accomodate all of the slaves at their + * accommodate all of the slaves at their * requested sizes. */ int offset; /* The pixel offset of the right edge of the * current slot from the beginning of the * layout. */ int slot; /* The current slot. */ @@ -2484,11 +2483,11 @@ * None * * Side effects: * The width and height arguments are filled in the master data * structure. Additional space is allocated for the constraints to - * accomodate the offsets. + * accommodate the offsets. * *---------------------------------------------------------------------- */ static void @@ -2775,15 +2774,19 @@ slavePtr->masterPtr = NULL; /* * If we have emptied this master from slaves it means we are no longer * handling it and should mark it as free. + * + * Send the event "NoManagedChild" to the master to inform it about there + * being no managed children inside it. */ if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) { TkFreeGeometryMaster(masterPtr->tkwin, "grid"); masterPtr->flags &= ~ALLOCED_MASTER; + TkSendVirtualEvent(masterPtr->tkwin, "NoManagedChild", NULL); } } /* *---------------------------------------------------------------------- @@ -2880,11 +2883,11 @@ slavePtr->masterPtr = NULL; nextPtr = slavePtr->nextPtr; slavePtr->nextPtr = NULL; } Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable, - (char *) gridPtr->tkwin)); + gridPtr->tkwin)); if (gridPtr->flags & REQUESTED_RELAYOUT) { Tcl_CancelIdleCall(ArrangeGrid, gridPtr); } gridPtr->tkwin = NULL; Tcl_EventuallyFree(gridPtr, (Tcl_FreeProc *)DestroyGrid); @@ -2936,10 +2939,11 @@ * that there is at least one window name. */ { Gridder *masterPtr = NULL; Gridder *slavePtr; Tk_Window other, slave, parent, ancestor; + TkWindow *master; int i, j, tmp; int numWindows; int width; int defaultRow = -1; int defaultColumn = 0; /* Default column number */ @@ -2963,14 +2967,14 @@ * Count the number of windows, or window short-cuts. */ firstChar = 0; for (numWindows=0, i=0; i < objc; i++) { - int length; + TkSizeT length; char prevChar = firstChar; - string = Tcl_GetStringFromObj(objv[i], &length); + string = TkGetStringFromObj(objv[i], &length); firstChar = string[0]; if (firstChar == '.') { /* * Check that windows are valid, and locate the first slave's @@ -3350,21 +3354,27 @@ return TCL_ERROR; } } /* - * Try to make sure our master isn't managed by us. + * Check for management loops. */ - if (masterPtr->masterPtr == slavePtr) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( + for (master = (TkWindow *)masterPtr->tkwin; master != NULL; + master = (TkWindow *)TkGetGeomMaster(master)) { + if (master == (TkWindow *)slave) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't put %s inside %s, would cause management loop", - Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); - Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); - Unlink(slavePtr); - return TCL_ERROR; - } + Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); + Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); + Unlink(slavePtr); + return TCL_ERROR; + } + } + if (masterPtr->tkwin != Tk_Parent(slave)) { + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin; + } Tk_ManageGeometry(slave, &gridMgrType, slavePtr); if (!(masterPtr->flags & DONT_PROPAGATE)) { if (TkSetGeometryMaster(interp, masterPtr->tkwin, "grid") @@ -3507,15 +3517,19 @@ SetGridSize(masterPtr); /* * If we have emptied this master from slaves it means we are no longer * handling it and should mark it as free. + * + * Send the event "NoManagedChild" to the master to inform it about there + * being no managed children inside it. */ if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) { TkFreeGeometryMaster(masterPtr->tkwin, "grid"); masterPtr->flags &= ~ALLOCED_MASTER; + TkSendVirtualEvent(masterPtr->tkwin, "NoManagedChild", NULL); } return TCL_OK; } @@ -3622,16 +3636,16 @@ *---------------------------------------------------------------------- */ static Tcl_Obj * NewPairObj( - int val1, int val2) + Tcl_WideInt val1, Tcl_WideInt val2) { Tcl_Obj *ary[2]; - ary[0] = Tcl_NewIntObj(val1); - ary[1] = Tcl_NewIntObj(val2); + ary[0] = Tcl_NewWideIntObj(val1); + ary[1] = Tcl_NewWideIntObj(val2); return Tcl_NewListObj(2, ary); } /* *---------------------------------------------------------------------- @@ -3649,18 +3663,18 @@ *---------------------------------------------------------------------- */ static Tcl_Obj * NewQuadObj( - int val1, int val2, int val3, int val4) + Tcl_WideInt val1, Tcl_WideInt val2, Tcl_WideInt val3, Tcl_WideInt val4) { Tcl_Obj *ary[4]; - ary[0] = Tcl_NewIntObj(val1); - ary[1] = Tcl_NewIntObj(val2); - ary[2] = Tcl_NewIntObj(val3); - ary[3] = Tcl_NewIntObj(val4); + ary[0] = Tcl_NewWideIntObj(val1); + ary[1] = Tcl_NewWideIntObj(val2); + ary[2] = Tcl_NewWideIntObj(val3); + ary[3] = Tcl_NewWideIntObj(val4); return Tcl_NewListObj(4, ary); } /* * Local Variables: Index: generic/tkImage.c ================================================================== --- generic/tkImage.c +++ generic/tkImage.c @@ -64,11 +64,11 @@ int deleted; /* Flag set when image is being deleted. */ TkWindow *winPtr; /* Main window of interpreter (used to detect * when the world is falling apart.) */ } ImageMaster; -typedef struct ThreadSpecificData { +typedef struct { Tk_ImageType *imageTypeList;/* First in a list of all known image * types. */ Tk_ImageType *oldImageTypeList; /* First in a list of all known old-style * image types. */ @@ -472,11 +472,11 @@ * Now we read off the specific piece of data we were asked for. */ switch ((enum options) index) { case IMAGE_HEIGHT: - Tcl_SetObjResult(interp, Tcl_NewIntObj(masterPtr->height)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(masterPtr->height)); break; case IMAGE_INUSE: Tcl_SetObjResult(interp, Tcl_NewBooleanObj( masterPtr->typePtr && masterPtr->instancePtr)); break; @@ -485,11 +485,11 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj(masterPtr->typePtr->name, -1)); } break; case IMAGE_WIDTH: - Tcl_SetObjResult(interp, Tcl_NewIntObj(masterPtr->width)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(masterPtr->width)); break; default: Tcl_Panic("can't happen"); } break; Index: generic/tkImgBmap.c ================================================================== --- generic/tkImgBmap.c +++ generic/tkImgBmap.c @@ -47,11 +47,11 @@ * The following data structure represents all of the instances of an image * that lie within a particular window: */ typedef struct BitmapInstance { - int refCount; /* Number of instances that share this data + size_t refCount; /* Number of instances that share this data * structure. */ BitmapMaster *masterPtr; /* Pointer to master for image. */ Tk_Window tkwin; /* Window in which the instances will be * displayed. */ XColor *fg; /* Foreground color for displaying image. */ @@ -106,21 +106,21 @@ * Information used for parsing configuration specs: */ static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_UID, "-background", NULL, NULL, - "", Tk_Offset(BitmapMaster, bgUid), 0, NULL}, + "", offsetof(BitmapMaster, bgUid), 0, NULL}, {TK_CONFIG_STRING, "-data", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapMaster, dataString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_STRING, "-file", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapMaster, fileString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_UID, "-foreground", NULL, NULL, - "#000000", Tk_Offset(BitmapMaster, fgUid), 0, NULL}, + "#000000", offsetof(BitmapMaster, fgUid), 0, NULL}, {TK_CONFIG_STRING, "-maskdata", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_STRING, "-maskfile", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* * The following data structure is used to describe the state of parsing a @@ -949,12 +949,11 @@ Display *display) /* Display containing window that used image. */ { BitmapInstance *instancePtr = clientData; BitmapInstance *prevPtr; - instancePtr->refCount--; - if (instancePtr->refCount > 0) { + if (instancePtr->refCount-- > 1) { return; } /* * There are no more uses of the image within this widget. Free the @@ -1078,14 +1077,14 @@ static int GetByte( Tcl_Channel chan) /* The channel we read from. */ { char buffer; - int size; + size_t size; size = Tcl_Read(chan, &buffer, 1); - if (size <= 0) { + if ((size + 1) < 2) { return EOF; } else { return buffer; } } Index: generic/tkImgGIF.c ================================================================== --- generic/tkImgGIF.c +++ generic/tkImgGIF.c @@ -53,21 +53,21 @@ typedef struct mFile { unsigned char *data; /* mmencoded source string */ int c; /* bits left over from previous character */ int state; /* decoder state (0-4 or GIF_DONE) */ - int length; /* Total amount of bytes in data */ + size_t length; /* Total amount of bytes in data */ } MFile; /* * Non-ASCII encoding support: * Most data in a GIF image is binary and is treated as such. However, a few * key bits are stashed in ASCII. If we try to compare those pieces to the * char they represent, it will fail on any non-ASCII (eg, EBCDIC) system. To - * accomodate these systems, we test against the numeric value of the ASCII + * accommodate these systems, we test against the numeric value of the ASCII * characters instead of the characters themselves. This is encoding - * independant. + * independent. */ static const char GIF87a[] = { /* ASCII GIF87a */ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00 }; @@ -109,12 +109,12 @@ /* * Type of a function used to do the writing to a file or buffer when * serializing in the GIF format. */ -typedef int (WriteBytesFunc) (ClientData clientData, const char *bytes, - int byteCount); +typedef size_t (WriteBytesFunc) (ClientData clientData, const char *bytes, + size_t byteCount); /* * The format record for the GIF file format: */ @@ -185,18 +185,18 @@ /* * these are for the BASE64 image reader code only */ -static int Fread(GIFImageConfig *gifConfPtr, unsigned char *dst, +static size_t Fread(GIFImageConfig *gifConfPtr, unsigned char *dst, size_t size, size_t count, Tcl_Channel chan); -static int Mread(unsigned char *dst, size_t size, size_t count, +static size_t Mread(unsigned char *dst, size_t size, size_t count, MFile *handle); static int Mgetc(MFile *handle); static int char64(int c); static void mInit(unsigned char *string, MFile *handle, - int length); + size_t length); /* * Types, defines and variables needed to write and compress a GIF. */ @@ -755,14 +755,14 @@ int *widthPtr, /* where to put the string width */ int *heightPtr, /* where to put the string height */ Tcl_Interp *interp) /* not used */ { unsigned char *data, header[10]; - int got, length; + TkSizeT got, length; MFile handle; - data = Tcl_GetByteArrayFromObj(dataObj, &length); + data = TkGetByteArrayFromObj(dataObj, &length); /* * Header is a minimum of 10 bytes. */ @@ -824,13 +824,13 @@ int destX, int destY, /* The rectangular region of the */ int width, int height, /* image to copy */ int srcX, int srcY) { MFile handle, *hdlPtr = &handle; - int length; + TkSizeT length; const char *xferFormat; - unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length); + unsigned char *data = TkGetByteArrayFromObj(dataObj, &length); mInit(data, hdlPtr, length); /* * Check whether the data is Base64 encoded by doing a character-by- @@ -915,11 +915,11 @@ { int i; unsigned char rgb[3]; for (i = 0; i < number; ++i) { - if (Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) <= 0) { + if (((size_t)Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) + 1) < 2) { return 0; } if (buffer) { buffer[i][CM_RED] = rgb[0]; @@ -981,15 +981,15 @@ Tcl_Channel chan, unsigned char *buf) { unsigned char count; - if (Fread(gifConfPtr, &count, 1, 1, chan) <= 0) { + if (((size_t)Fread(gifConfPtr, &count, 1, 1, chan) + 1) < 2) { return -1; } - if ((count != 0) && (Fread(gifConfPtr, buf, count, 1, chan) <= 0)) { + if ((count != 0) && (((size_t)Fread(gifConfPtr, buf, count, 1, chan) + 1) < 2)) { return -1; } return count; } @@ -1032,11 +1032,11 @@ int srcX, int srcY, int interlace, int transparent) { unsigned char initialCodeSize; - int xpos = 0, ypos = 0, pass = 0, i; + int xpos = 0, ypos = 0, pass = 0, i, count; register unsigned char *pixelPtr; static const int interlaceStep[] = { 8, 8, 4, 2 }; static const int interlaceStart[] = { 0, 4, 2, 1 }; unsigned short prefix[(1 << MAX_LWZ_BITS)]; unsigned char append[(1 << MAX_LWZ_BITS)]; @@ -1047,11 +1047,11 @@ /* * Initialize the decoder */ - if (Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) <= 0) { + if (((size_t)Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) + 1) < 2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading GIF image: %s", Tcl_PosixError(interp))); return TCL_ERROR; } @@ -1250,10 +1250,29 @@ } else { ypos++; } pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3); } + + /* + * Now read until the final zero byte. + * It was observed that there might be 1 length blocks + * (test imgPhoto-14.1) which are not read. + * + * The field "stack" is abused for temporary buffer. it has 4096 bytes + * and we need 256. + * + * Loop until we hit a 0 length block which is the end sign. + */ + while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack))) + { + if (-1 == count ) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error reading GIF image: %s", Tcl_PosixError(interp))); + return TCL_ERROR; + } + } return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1371,11 +1390,11 @@ static void mInit( unsigned char *string, /* string containing initial mmencoded data */ MFile *handle, /* mmdecode "file" handle */ - int length) /* Number of bytes in string */ + size_t length) /* Number of bytes in string */ { handle->data = string; handle->state = 0; handle->c = 0; handle->length = length; @@ -1397,19 +1416,19 @@ * The base64 handle will change state. * *---------------------------------------------------------------------- */ -static int +static size_t Mread( unsigned char *dst, /* where to put the result */ size_t chunkSize, /* size of each transfer */ size_t numChunks, /* number of chunks */ MFile *handle) /* mmdecode "file" handle */ { - register int i, c; - int count = chunkSize * numChunks; + int c; + size_t i, count = chunkSize * numChunks; for (i=0; ifromData == INLINE_DATA_BINARY) { MFile *handle = (MFile *) chan; - if (handle->length <= 0 || (size_t) handle->length < hunk*count) { - return -1; + if ((handle->length + 1 < 2) || (handle->length < hunk*count)) { + return (size_t)-1; } - memcpy(dst, handle->data, (size_t) (hunk * count)); + memcpy(dst, handle->data, hunk * count); handle->data += hunk * count; handle->length -= hunk * count; - return (int)(hunk * count); + return hunk * count; } /* * Otherwise we've got a real file to read. */ - return Tcl_Read(chan, (char *) dst, (int) (hunk * count)); + return Tcl_Read(chan, (char *) dst, hunk * count); } /* * ChanWriteGIF - writes a image in GIF format. *------------------------------------------------------------------------- @@ -1652,26 +1671,26 @@ } Tcl_DecrRefCount(objPtr); return result; } -static int +static size_t WriteToChannel( ClientData clientData, const char *bytes, - int byteCount) + size_t byteCount) { Tcl_Channel handle = clientData; return Tcl_Write(handle, bytes, byteCount); } -static int +static size_t WriteToByteArray( ClientData clientData, const char *bytes, - int byteCount) + size_t byteCount) { Tcl_Obj *objPtr = clientData; Tcl_Obj *tmpObj = Tcl_NewByteArrayObj((unsigned char *) bytes, byteCount); Tcl_IncrRefCount(tmpObj); ADDED generic/tkImgListFormat.c Index: generic/tkImgListFormat.c ================================================================== --- /dev/null +++ generic/tkImgListFormat.c @@ -0,0 +1,1141 @@ +/* + * tkImgListFormat.c -- + * + * Implements the default image data format. I.e. the format used for + * [imageName data] and [imageName put] if no other format is specified. + * + * The default format consits of a list of scan lines (rows) with each + * list element being itself a list of pixels (or columns). For details, + * see the manpage photo.n + * + * This image format cannot read/write files, it is meant for string + * data only. + * + * + * Copyright (c) 1994 The Australian National University. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 2002-2003 Donal K. Fellows + * Copyright (c) 2003 ActiveState Corporation. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * Authors: + * Paul Mackerras (paulus@cs.anu.edu.au), + * Department of Computer Science, + * Australian National University. + * + * Simon Bachmann (simonbachmann@bluewin.ch) + */ + + +#include "tkImgPhoto.h" + +/* + * Message to generate when an attempt to allocate memory for an image fails. + */ + +#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \ + "not enough free memory for image buffer" + + +/* + * Color name length limit: do not attempt to parse as color strings that are + * longer than this limit + */ + +#define TK_PHOTO_MAX_COLOR_CHARS 99 + +/* + * Symbols for the different formats of a color string. + */ + +enum ColorFormatType { + COLORFORMAT_TKCOLOR, + COLORFORMAT_EMPTYSTRING, + COLORFORMAT_LIST, + COLORFORMAT_RGB1, + COLORFORMAT_RGB2, + COLORFORMAT_RGBA1, + COLORFORMAT_RGBA2 +}; + +/* + * Names for the color format types above. + * Order must match the one in enum ColorFormatType + */ + +static const char *const colorFormatNames[] = { + "tkcolor", + "emptystring", + "list", + "rgb-short", + "rgb", + "rgba-short", + "rgba", + NULL +}; + +/* + * The following data structure is used to return information from + * ParseFormatOptions: + */ + +struct FormatOptions { + int options; /* Individual bits indicate which options were + * specified - see below. */ + Tcl_Obj *formatName; /* Name specified without an option. */ + enum ColorFormatType colorFormat; + /* The color format type given with the + * -colorformat option */ +}; + +/* + * Bit definitions for use with ParseFormatOptions: each bit is set in the + * allowedOptions parameter on a call to ParseFormatOptions if that option + * is allowed for the current photo image subcommand. On return, the bit is + * set in the options field of the FormatOptions structure if that option + * was specified. + * + * OPT_COLORFORMAT: Set if -alpha option allowed/specified. + */ + +#define OPT_COLORFORMAT 1 + +/* + * List of format option names. The order here must match the order of + * declarations of the FMT_OPT_* constants above. + */ + +static const char *const formatOptionNames[] = { + "-colorformat", + NULL +}; + +/* + * Forward declarations + */ + +static int ParseFormatOptions(Tcl_Interp *interp, int allowedOptions, + int objc, Tcl_Obj *const objv[], int *indexPtr, + struct FormatOptions *optPtr); +static Tcl_Obj *GetBadOptMsg(const char *badValue, int allowedOpts); +static int StringMatchDef(Tcl_Obj *data, Tcl_Obj *formatString, + int *widthPtr, int *heightPtr, Tcl_Interp *interp); +static int StringReadDef(Tcl_Interp *interp, Tcl_Obj *data, + Tcl_Obj *formatString, Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, + int srcX, int srcY); +static int StringWriteDef(Tcl_Interp *interp, + Tcl_Obj *formatString, + Tk_PhotoImageBlock *blockPtr); +static int ParseColor(Tcl_Interp *interp, Tcl_Obj *specObj, + Display *display, Colormap colormap, unsigned char *redPtr, + unsigned char *greenPtr, unsigned char *bluePtr, + unsigned char *alphaPtr); +static int ParseColorAsList(Tcl_Interp *interp, const char *colorString, + int colorStrLen, unsigned char *redPtr, + unsigned char *greenPtr, unsigned char *bluePtr, + unsigned char *alphaPtr); +static int ParseColorAsHex(Tcl_Interp *interp, const char *colorString, + int colorStrLen, Display *display, Colormap colormap, + unsigned char *redPtr, unsigned char *greenPtr, + unsigned char *bluePtr, unsigned char *alphaPtr); +static int ParseColorAsStandard(Tcl_Interp *interp, + const char *colorString, int colorStrLen, + Display *display, Colormap colormap, + unsigned char *redPtr, unsigned char *greenPtr, + unsigned char *bluePtr, unsigned char *alphaPtr); + +/* + * The format record for the default image handler + */ + +Tk_PhotoImageFormat tkImgFmtDefault = { + "default", /* name */ + NULL, /* fileMatchProc: format doesn't support file ops */ + StringMatchDef, /* stringMatchProc */ + NULL, /* fileReadProc: format doesn't support file read */ + StringReadDef, /* stringReadProc */ + NULL, /* fileWriteProc: format doesn't support file write */ + StringWriteDef /* stringWriteProc */ +}; + +/* + *---------------------------------------------------------------------- + * + * ParseFormatOptions -- + * + * Parse the options passed to the image format handler. + * + * Results: + * On success, the structure pointed to by optPtr is filled with the + * values passed or with the defaults and TCL_OK returned. + * If an error occurs, leaves an error message in interp and returns + * TCL_ERROR. + * + * Side effects: + * The value in *indexPtr is updated to the index of the fist + * element in argv[] that does not look like an option/value, or to + * argc if parsing reached the end of argv[]. + * + *---------------------------------------------------------------------- + */ +static int +ParseFormatOptions( + Tcl_Interp *interp, /* For error messages */ + int allowedOptions, /* Bitfield specifying which options are + * to be considered allowed */ + int objc, /* Number of elements in argv[] */ + Tcl_Obj *const objv[], /* The arguments to parse */ + int *indexPtr, /* Index giving the first element to + * parse. The value is updated to the + * index where parsing ended */ + struct FormatOptions *optPtr) /* Parsed option values are written to + * this struct */ + +{ + int index, optIndex, typeIndex, first; + const char *option; + + first = 1; + + /* + * Fill in default values + */ + optPtr->options = 0; + optPtr->formatName = NULL; + optPtr->colorFormat = COLORFORMAT_RGB2; + for (index = *indexPtr; index < objc; *indexPtr = ++index) { + int optionExists; + + /* + * The first value can be the format handler's name. It goes to + * optPtr->name. + */ + option = Tcl_GetString(objv[index]); + if (option[0] != '-') { + if (first) { + optPtr->formatName = objv[index]; + first = 0; + continue; + } else { + break; + } + } + first = 0; + + /* + * Check if option is known and allowed + */ + + optionExists = 1; + if (Tcl_GetIndexFromObj(NULL, objv[index], formatOptionNames, + "format option", 0, &optIndex) != TCL_OK) { + optionExists = 0; + } + if (!optionExists || !((1 << optIndex) & allowedOptions)) { + Tcl_SetObjResult(interp, GetBadOptMsg(Tcl_GetString(objv[index]), + allowedOptions)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL); + return TCL_ERROR; + } + + /* + * Option-specific checks + */ + + switch (1 << optIndex) { + case OPT_COLORFORMAT: + *indexPtr = ++index; + if (index >= objc) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("the \"%s\" option " + "requires a value", Tcl_GetString(objv[index - 1]))); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "MISSING_VALUE", NULL); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(NULL, objv[index], colorFormatNames, "", + TCL_EXACT, &typeIndex) != TCL_OK + || (typeIndex != COLORFORMAT_LIST + && typeIndex != COLORFORMAT_RGB2 + && typeIndex != COLORFORMAT_RGBA2) ) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad color format " + "\"%s\": must be rgb, rgba, or list", + Tcl_GetString(objv[index]))); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "BAD_COLOR_FORMAT", NULL); + return TCL_ERROR; + } + optPtr->colorFormat = typeIndex; + break; + default: + Tcl_Panic("ParseFormatOptions: unexpected switch fallthrough"); + } + + /* + * Add option to bitfield in optPtr + */ + optPtr->options |= (1 << optIndex); + } + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GetBadOptMsg -- + * + * Build a Tcl_Obj containing an error message in the form "bad option + * "xx": must be y, or z", based on the bits set in allowedOpts. + * + * Results: + * A Tcl Object containig the error message. + * + * Side effects: + * None + *---------------------------------------------------------------------- + */ +static Tcl_Obj * +GetBadOptMsg( + const char *badValue, /* the erroneous option */ + int allowedOpts) /* bitfield specifying the allowed options */ +{ + int i, bit; + Tcl_Obj *resObj = Tcl_ObjPrintf("bad format option \"%s\": ", badValue); + + if (allowedOpts == 0) { + Tcl_AppendToObj(resObj, "no options allowed", -1); + } else { + Tcl_AppendToObj(resObj, "must be ", -1); + bit = 1; + for (i = 0; formatOptionNames[i] != NULL; i++) { + if (allowedOpts & bit) { + if (allowedOpts & (bit -1)) { + /* + * not the first option + */ + if (allowedOpts & ~((bit << 1) - 1)) { + /* + * not the last option + */ + Tcl_AppendToObj(resObj, ", ", -1); + } else { + Tcl_AppendToObj(resObj, ", or ", -1); + } + } + Tcl_AppendToObj(resObj, formatOptionNames[i], -1); + } + bit <<=1; + } + } + return resObj; +} + +/* + *---------------------------------------------------------------------- + * + * StringMatchDef -- + * + * Default string match function. Test if image data in string form + * appears to be in the default list-of-list-of-pixel-data format + * accepted by the " put" command. + * + * Results: + * If thte data is in the default format, writes the size of the image + * to widthPtr and heightPtr and returns 1. Otherwise, leaves an error + * message in interp (if not NULL) and returns 0. + * Note that this function does not parse all data points. A return + * value of 1 does not guarantee that the data can be read without + * errors. + * + * Side effects: + * None + *---------------------------------------------------------------------- + */ +static int +StringMatchDef( + Tcl_Obj *data, /* The data to check */ + Tcl_Obj *formatString, /* Value of the -format option, not used here */ + int *widthPtr, /* Width of image is written to this location */ + int *heightPtr, /* Height of image is written to this location */ + Tcl_Interp *interp) /* Error messages are left in this interpreter */ +{ + int y, rowCount, colCount, curColCount; + unsigned char dummy; + Tcl_Obj **rowListPtr, *pixelData; + + /* + * See if data can be parsed as a list, if every element is itself a valid + * list and all sublists have the same length. + */ + + if (Tcl_ListObjGetElements(interp, data, &rowCount, &rowListPtr) + != TCL_OK) { + return 0; + } + if (rowCount == 0) { + /* + * empty list is valid data + */ + + *widthPtr = 0; + *heightPtr = 0; + return 1; + } + colCount = -1; + for (y = 0; y < rowCount; y++) { + if (Tcl_ListObjLength(interp, rowListPtr[y], &curColCount) != TCL_OK) { + return 0; + } + if (colCount < 0) { + colCount = curColCount; + } else if (curColCount != colCount) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid row # %d: " + "all rows must have the same number of elements", y)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID_DATA", NULL); + } + return 0; + } + } + + /* + * Data in base64 encoding (or even binary data), might actually pass + * these tests. To avoid parsing it as list of lists format, check one + * pixel for validity. + */ + if (Tcl_ListObjIndex(interp, rowListPtr[0], 0, &pixelData) != TCL_OK) { + return 0; + } + if (Tcl_GetCharLength(pixelData) > TK_PHOTO_MAX_COLOR_CHARS) { + return 0; + } + if (ParseColor(interp, pixelData, Tk_Display(Tk_MainWindow(interp)), + Tk_Colormap(Tk_MainWindow(interp)), &dummy, &dummy, &dummy, &dummy) + != TCL_OK) { + return 0; + } + + /* + * Looks like we have valid data for this format. + * We do not check any pixel values - that's the job of ImgStringRead() + */ + + *widthPtr = colCount; + *heightPtr = rowCount; + + return 1; + +} + +/* + *---------------------------------------------------------------------- + * + * StringReadDef -- + * + * String read function for default format. (see manpage for details on + * the format). + * + * Results: + * A standard Tcl result. + * + * Side effects: + * If the data has valid format, write it to the image identified by + * imageHandle. + * If the image data cannot be parsed, an error message is left in + * interp. + * + *---------------------------------------------------------------------- +*/ + +static int +StringReadDef( + Tcl_Interp *interp, /* leave error messages here */ + Tcl_Obj *data, /* the data to parse */ + Tcl_Obj *formatString, /* value of the -format option */ + Tk_PhotoHandle imageHandle, /* write data to this image */ + int destX, int destY, /* start writing data at this point + * in destination image*/ + int width, int height, /* dimensions of area to write to */ + int srcX, int srcY) /* start reading source data at these + * coordinates */ +{ + Tcl_Obj **rowListPtr, **colListPtr; + Tcl_Obj **objv; + int objc; + unsigned char *curPixelPtr; + int x, y, rowCount, colCount, curColCount; + Tk_PhotoImageBlock srcBlock; + Display *display; + Colormap colormap; + struct FormatOptions opts; + int optIndex; + + /* + * Parse format suboptions + * We don't use any format suboptions, but we still need to provide useful + * error messages if suboptions were specified. + */ + + memset(&opts, 0, sizeof(opts)); + if (formatString != NULL) { + if (Tcl_ListObjGetElements(interp, formatString, &objc, &objv) + != TCL_OK) { + return TCL_ERROR; + } + optIndex = 0; + if (ParseFormatOptions(interp, 0, objc, objv, &optIndex, &opts) + != TCL_OK) { + return TCL_ERROR; + } + if (optIndex < objc) { + Tcl_SetObjResult(interp, + GetBadOptMsg(Tcl_GetString(objv[optIndex]), 0)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL); + return TCL_ERROR; + } + } + + /* + * Check input data + */ + + if (Tcl_ListObjGetElements(interp, data, &rowCount, &rowListPtr) + != TCL_OK ) { + return TCL_ERROR; + } + if ( rowCount > 0 && Tcl_ListObjLength(interp, rowListPtr[0], &colCount) + != TCL_OK) { + return TCL_ERROR; + } + if (width <= 0 || height <= 0 || rowCount == 0 || colCount == 0) { + /* + * No changes with zero sized input or zero sized output region + */ + + return TCL_OK; + } + if (srcX < 0 || srcY < 0 || srcX >= rowCount || srcY >= colCount) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("source coordinates out of range")); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES", NULL); + return TCL_ERROR; + } + + /* + * Memory allocation overflow protection. + * May not be able to trigger/ demo / test this. + */ + + if (colCount > (int)(UINT_MAX / 4 / rowCount)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "photo image dimensions exceed Tcl memory limits")); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "OVERFLOW", NULL); + return TCL_OK; + } + + /* + * Read data and put it to imageHandle + */ + + srcBlock.width = colCount - srcX; + srcBlock.height = rowCount - srcY; + srcBlock.pixelSize = 4; + srcBlock.pitch = srcBlock.width * 4; + srcBlock.offset[0] = 0; + srcBlock.offset[1] = 1; + srcBlock.offset[2] = 2; + srcBlock.offset[3] = 3; + srcBlock.pixelPtr = attemptckalloc(srcBlock.pitch * srcBlock.height); + if (srcBlock.pixelPtr == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf(TK_PHOTO_ALLOC_FAILURE_MESSAGE)); + Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); + return TCL_ERROR; + } + curPixelPtr = srcBlock.pixelPtr; + display = Tk_Display(Tk_MainWindow(interp)); + colormap = Tk_Colormap(Tk_MainWindow(interp)); + for (y = srcY; y < rowCount; y++) { + /* + * We don't test the length of row, as that's been done in + * ImgStringMatch() + */ + + if (Tcl_ListObjGetElements(interp, rowListPtr[y], &curColCount, + &colListPtr) != TCL_OK) { + goto errorExit; + } + for (x = srcX; x < colCount; x++) { + if (ParseColor(interp, colListPtr[x], display, colormap, + curPixelPtr, curPixelPtr + 1, curPixelPtr + 2, + curPixelPtr + 3) != TCL_OK) { + goto errorExit; + } + curPixelPtr += 4; + } + } + + /* + * Write image data to destHandle + */ + if (Tk_PhotoPutBlock(interp, imageHandle, &srcBlock, destX, destY, + width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) { + goto errorExit; + } + + ckfree(srcBlock.pixelPtr); + + return TCL_OK; + + errorExit: + ckfree(srcBlock.pixelPtr); + + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * StringWriteDef -- + * + * String write function for default image data format. See the user + * documentation for details. + * + * Results: + * The converted data is set as the result of interp. Returns a standard + * Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +StringWriteDef( + Tcl_Interp *interp, /* For the result and errors */ + Tcl_Obj *formatString, /* The value of the -format option */ + Tk_PhotoImageBlock *blockPtr) /* The image data to convert */ +{ + int greenOffset, blueOffset, alphaOffset, hasAlpha; + Tcl_Obj *result, **objv = NULL; + int objc, allowedOpts, optIndex; + struct FormatOptions opts; + + /* + * Parse format suboptions + */ + if (Tcl_ListObjGetElements(interp, formatString, &objc, &objv) + != TCL_OK) { + return TCL_ERROR; + } + allowedOpts = OPT_COLORFORMAT; + optIndex = 0; + if (ParseFormatOptions(interp, allowedOpts, objc, objv, &optIndex, &opts) + != TCL_OK) { + return TCL_ERROR; + } + if (optIndex < objc) { + Tcl_SetObjResult(interp, + GetBadOptMsg(Tcl_GetString(objv[optIndex]), allowedOpts)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL); + return TCL_ERROR; + } + + greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; + blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; + + /* + * A negative alpha offset signals that the image is fully opaque. + * That's not really documented anywhere, but it's the way it is! + */ + + if (blockPtr->offset[3] < 0) { + hasAlpha = 0; + alphaOffset = 0; + } else { + hasAlpha = 1; + alphaOffset = blockPtr->offset[3] - blockPtr->offset[0]; + } + + if ((blockPtr->width > 0) && (blockPtr->height > 0)) { + int row, col; + Tcl_DString data, line; + char colorBuf[11]; + unsigned char *pixelPtr; + unsigned char alphaVal = 255; + + Tcl_DStringInit(&data); + for (row=0; rowheight; row++) { + pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] + + row * blockPtr->pitch; + Tcl_DStringInit(&line); + for (col=0; colwidth; col++) { + if (hasAlpha) { + alphaVal = pixelPtr[alphaOffset]; + } + + /* + * We don't build lines as a list for #RGBA and #RGB. Since + * these color formats look like comments, the first element + * of the list would get quoted with an additional {} . + * While this is not a problem if the data is used as + * a list, it would cause problems if someone decides to parse + * it as a string (and it looks kinda strange) + */ + + switch (opts.colorFormat) { + case COLORFORMAT_RGB2: + sprintf(colorBuf, "#%02x%02x%02x ", pixelPtr[0], + pixelPtr[greenOffset], pixelPtr[blueOffset]); + Tcl_DStringAppend(&line, colorBuf, -1); + break; + case COLORFORMAT_RGBA2: + sprintf(colorBuf, "#%02x%02x%02x%02x ", + pixelPtr[0], pixelPtr[greenOffset], + pixelPtr[blueOffset], alphaVal); + Tcl_DStringAppend(&line, colorBuf, -1); + break; + case COLORFORMAT_LIST: + Tcl_DStringStartSublist(&line); + sprintf(colorBuf, "%d", pixelPtr[0]); + Tcl_DStringAppendElement(&line, colorBuf); + sprintf(colorBuf, "%d", pixelPtr[greenOffset]); + Tcl_DStringAppendElement(&line, colorBuf); + sprintf(colorBuf, "%d", pixelPtr[blueOffset]); + Tcl_DStringAppendElement(&line, colorBuf); + sprintf(colorBuf, "%d", alphaVal); + Tcl_DStringAppendElement(&line, colorBuf); + Tcl_DStringEndSublist(&line); + break; + default: + Tcl_Panic("unexpected switch fallthrough"); + } + pixelPtr += blockPtr->pixelSize; + } + if (opts.colorFormat != COLORFORMAT_LIST) { + /* + * For the #XXX formats, we need to remove the last + * whitespace. + */ + + *(Tcl_DStringValue(&line) + Tcl_DStringLength(&line) - 1) + = '\0'; + } + Tcl_DStringAppendElement(&data, Tcl_DStringValue(&line)); + Tcl_DStringFree(&line); + } + result = Tcl_NewStringObj(Tcl_DStringValue(&data), -1); + Tcl_DStringFree(&data); + } else { + result = Tcl_NewObj(); + } + + Tcl_SetObjResult(interp, result); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseColor -- + * + * This function extracts color and alpha values from a string. It + * understands standard Tk color formats, alpha suffixes and the color + * formats specific to photo images, which include alpha data. + * + * Results: + * On success, writes red, green, blue and alpha values to the + * corresponding pointers. If the color spec contains no alpha + * information, 255 is taken as transparency value. + * If the input cannot be parsed, leaves an error message in + * interp. Returns a standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static int +ParseColor( + Tcl_Interp *interp, /* error messages go there */ + Tcl_Obj *specObj, /* the color data to parse */ + Display *display, /* display of main window, needed to parse + * standard Tk colors */ + Colormap colormap, /* colormap of current display */ + unsigned char *redPtr, /* the result is written to these pointers */ + unsigned char *greenPtr, + unsigned char *bluePtr, + unsigned char *alphaPtr) +{ + const char *specString; + TkSizeT charCount; + + /* + * Find out which color format we have + */ + + specString = TkGetStringFromObj(specObj, &charCount); + + if (charCount == 0) { + /* Empty string */ + *redPtr = *greenPtr = *bluePtr = *alphaPtr = 0; + return TCL_OK; + } + if (charCount > TK_PHOTO_MAX_COLOR_CHARS) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid color")); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID_COLOR", NULL); + return TCL_ERROR; + } + if (specString[0] == '#') { + return ParseColorAsHex(interp, specString, charCount, display, + colormap, redPtr, greenPtr, bluePtr, alphaPtr); + } + if (ParseColorAsList(interp, specString, charCount, + redPtr, greenPtr, bluePtr, alphaPtr) == TCL_OK) { + return TCL_OK; + } + + /* + * Parsing the color as standard Tk color always is the last option tried + * because TkParseColor() is very slow with values it cannot parse. + */ + + Tcl_ResetResult(interp); + return ParseColorAsStandard(interp, specString, charCount, display, + colormap, redPtr, greenPtr, bluePtr, alphaPtr); + +} + +/* + *---------------------------------------------------------------------- + * + * ParseColorAsList -- + * + * This function extracts color and alpha values from a list of 3 or 4 + * integers (the list color format). + * + * Results: + * On success, writes red, green, blue and alpha values to the + * corresponding pointers. If the color spec contains no alpha + * information, 255 is taken as transparency value. + * Returns a standard Tcl result. + * + * Side effects: + * Does *not* leave error messages in interp. The reason is that + * it is not always possible to tell if the list format was even + * intended and thus it is hard to return meaningful messages. + * A general error message from the caller is probably the best + * alternative. + * + *---------------------------------------------------------------------- + */ +static int +ParseColorAsList( + Tcl_Interp *interp, /* not used */ + const char *colorString, /* the color data to parse */ + int colorStrLen, /* length of the color string */ + unsigned char *redPtr, /* the result is written to these pointers */ + unsigned char *greenPtr, + unsigned char *bluePtr, + unsigned char *alphaPtr) +{ + + /* + * This is kinda ugly. The code would be certainly nicer if it + * used Tcl_ListObjGetElements() and Tcl_GetIntFromObj(). But with + * strtol() it's *much* faster. + */ + + const char *curPos; + int values[4]; + int i; + + curPos = colorString; + i = 0; + + /* + * strtol can give false positives with a sequence of space chars. + * To avoid that, avance the pointer to the next non-blank char. + */ + + while(isspace(*curPos)) { + ++curPos; + } + while (i < 4 && *curPos != '\0') { + values[i] = strtol(curPos, (char **)&curPos, 0); + if (values[i] < 0 || values[i] > 255) { + return TCL_ERROR; + } + while(isspace(*curPos)) { + ++curPos; + } + ++i; + } + + if (i < 3 || *curPos != '\0') { + return TCL_ERROR; + } + if (i < 4) { + values[3] = 255; + } + + *redPtr = (unsigned char) values[0]; + *greenPtr = (unsigned char) values[1]; + *bluePtr = (unsigned char) values[2]; + *alphaPtr = (unsigned char) values[3]; + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseColorAsHex -- + * + * This function extracts color and alpha values from a string + * starting with '#', followed by hex digits. It undestands both + * the #RGBA form and the #RBG (with optional suffix) + * + * Results: + * On success, writes red, green, blue and alpha values to the + * corresponding pointers. If the color spec contains no alpha + * information, 255 is taken as transparency value. + * Returns a standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static int +ParseColorAsHex( + Tcl_Interp *interp, /* error messages are left here */ + const char *colorString, /* the color data to parse */ + int colorStrLen, /* length of the color string */ + Display *display, /* display of main window */ + Colormap colormap, /* colormap of current display */ + unsigned char *redPtr, /* the result is written to these pointers */ + unsigned char *greenPtr, + unsigned char *bluePtr, + unsigned char *alphaPtr) +{ + int i; + unsigned long int colorValue = 0; + + if (colorStrLen - 1 != 4 && colorStrLen - 1 != 8) { + return ParseColorAsStandard(interp, colorString, colorStrLen, + display, colormap, redPtr, greenPtr, bluePtr, alphaPtr); + } + for (i = 1; i < colorStrLen; i++) { + if (!isxdigit(UCHAR(colorString[i]))) { + /* + * There still is a chance that this is a Tk color with + * an alpha suffix + */ + + return ParseColorAsStandard(interp, colorString, colorStrLen, + display, colormap, redPtr, greenPtr, bluePtr, alphaPtr); + } + } + + colorValue = strtoul(colorString + 1, NULL, 16); + switch (colorStrLen - 1) { + case 4: + /* #RGBA format */ + *redPtr = (unsigned char) ((colorValue >> 12) * 0x11); + *greenPtr = (unsigned char) (((colorValue >> 8) & 0xf) * 0x11); + *bluePtr = (unsigned char) (((colorValue >> 4) & 0xf) * 0x11); + *alphaPtr = (unsigned char) ((colorValue & 0xf) * 0x11); + return TCL_OK; + case 8: + /* #RRGGBBAA format */ + *redPtr = (unsigned char) (colorValue >> 24); + *greenPtr = (unsigned char) ((colorValue >> 16) & 0xff); + *bluePtr = (unsigned char) ((colorValue >> 8) & 0xff); + *alphaPtr = (unsigned char) (colorValue & 0xff); + return TCL_OK; + default: + Tcl_Panic("unexpected switch fallthrough"); + } + + /* Shouldn't get here */ + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * ParseColorAsStandard -- + * + * This function tries to split a color stirng in a color and a + * suffix part and to extract color and alpha values from them. The + * color part is treated as regular Tk color. + * + * Results: + * On success, writes red, green, blue and alpha values to the + * corresponding pointers. If the color spec contains no alpha + * information, 255 is taken as transparency value. + * Returns a standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static int +ParseColorAsStandard( + Tcl_Interp *interp, /* error messages are left here */ + const char *specString, /* the color data to parse */ + int specStrLen, /* length of the color string */ + Display *display, /* display of main window */ + Colormap colormap, /* colormap of current display */ + unsigned char *redPtr, /* the result is written to these pointers */ + unsigned char *greenPtr, + unsigned char *bluePtr, + unsigned char *alphaPtr) +{ + XColor parsedColor; + const char *suffixString, *colorString; + char colorBuffer[TK_PHOTO_MAX_COLOR_CHARS + 1]; + char *tmpString; + double fracAlpha; + unsigned int suffixAlpha; + int i; + + /* + * Split color data string in color and suffix parts + */ + + if ((suffixString = strrchr(specString, '@')) == NULL + && ((suffixString = strrchr(specString, '#')) == NULL + || suffixString == specString)) { + suffixString = specString + specStrLen; + colorString = specString; + } else { + strncpy(colorBuffer, specString, suffixString - specString); + colorBuffer[suffixString - specString] = '\0'; + colorString = (const char*)colorBuffer; + } + + /* + * Try to parse as standard Tk color. + * + * We don't use Tk_GetColor() et al. here, as those functions + * migth return a color that does not exaxtly match the given name + * if the colormap is full. Also, we don't really want the color to be + * added to the colormap. + */ + + if ( ! TkParseColor(display, colormap, colorString, &parsedColor)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid color name \"%s\"", specString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID_COLOR", NULL); + return TCL_ERROR; + } + + /* + * parse the Suffix + */ + + switch (suffixString[0]) { + case '\0': + suffixAlpha = 255; + break; + case '@': + fracAlpha = strtod(suffixString + 1, &tmpString); + if (*tmpString != '\0') { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid alpha " + "suffix \"%s\": expected floating-point value", + suffixString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID COLOR", NULL); + return TCL_ERROR; + } + if (fracAlpha < 0 || fracAlpha > 1) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid alpha suffix" + " \"%s\": value must be in the range from 0 to 1", + suffixString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID_COLOR", NULL); + return TCL_ERROR; + } + suffixAlpha = (unsigned int) floor(fracAlpha * 255 + 0.5); + break; + case '#': + if (strlen(suffixString + 1) < 1 || strlen(suffixString + 1)> 2) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid alpha suffix \"%s\"", suffixString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID_COLOR", NULL); + return TCL_ERROR; + } + for (i = 1; i <= (int)strlen(suffixString + 1); i++) { + if ( ! isxdigit(UCHAR(suffixString[i]))) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid alpha suffix \"%s\": expected hex digit", + suffixString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "INVALID_COLOR", NULL); + return TCL_ERROR; + } + } + if (strlen(suffixString + 1) == 1) { + sscanf(suffixString, "#%1x", &suffixAlpha); + suffixAlpha *= 0x11; + } else { + sscanf(suffixString, "#%2x", &suffixAlpha); + } + break; + default: + Tcl_Panic("unexpected switch fallthrough"); + } + + *redPtr = (unsigned char) (parsedColor.red >> 8); + *greenPtr = (unsigned char) (parsedColor.green >> 8); + *bluePtr = (unsigned char) (parsedColor.blue >> 8); + *alphaPtr = (unsigned char) suffixAlpha; + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkDebugStringMatchDef -- + * + * Debugging function for StringMatchDef. Basically just an alias for + * that function, intended to expose it directly to tests, as + * StirngMatchDef cannot be sufficiently tested otherwise. + * + * Results: + * See StringMatchDef. + * + * Side effects: + * None + *---------------------------------------------------------------------- + */ +int +TkDebugPhotoStringMatchDef( + Tcl_Interp *interp, /* Error messages are left in this interpreter */ + Tcl_Obj *data, /* The data to check */ + Tcl_Obj *formatString, /* Value of the -format option, not used here */ + int *widthPtr, /* Width of image is written to this location */ + int *heightPtr) /* Height of image is written to this location */ +{ + return StringMatchDef(data, formatString, widthPtr, heightPtr, interp); +} + + +/* Local Variables: */ +/* mode: c */ +/* fill-column: 78 */ +/* c-basic-offset: 4 */ +/* tab-width: 8 */ +/* indent-tabs-mode: nil */ +/* End: */ Index: generic/tkImgPNG.c ================================================================== --- generic/tkImgPNG.c +++ generic/tkImgPNG.c @@ -8,11 +8,10 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "assert.h" #include "tkInt.h" #define PNG_INT32(a,b,c,d) \ (((long)(a) << 24) | ((long)(b) << 16) | ((long)(c) << 8) | (long)(d)) #define PNG_BLOCK_SZ 1024 /* Process up to 1k at a time. */ @@ -125,11 +124,11 @@ */ Tcl_Channel channel; /* Channel for from-file reads. */ Tcl_Obj *objDataPtr; unsigned char *strDataBuf; /* Raw source data for from-string reads. */ - int strDataLen; /* Length of source data. */ + TkSizeT strDataLen; /* Length of source data. */ unsigned char *base64Data; /* base64 encoded string data. */ unsigned char base64Bits; /* Remaining bits from last base64 read. */ unsigned char base64State; /* Current state of base64 decoder. */ double alpha; /* Alpha from -format option. */ @@ -213,20 +212,20 @@ Tcl_Channel chan, Tcl_Obj *objPtr, int dir); static inline unsigned char Paeth(int a, int b, int c); static int ParseFormat(Tcl_Interp *interp, Tcl_Obj *fmtObj, PNGImage *pngPtr); static int ReadBase64(Tcl_Interp *interp, PNGImage *pngPtr, - unsigned char *destPtr, int destSz, + unsigned char *destPtr, size_t destSz, unsigned long *crcPtr); static int ReadByteArray(Tcl_Interp *interp, PNGImage *pngPtr, - unsigned char *destPtr, int destSz, + unsigned char *destPtr, size_t destSz, unsigned long *crcPtr); static int ReadData(Tcl_Interp *interp, PNGImage *pngPtr, - unsigned char *destPtr, int destSz, + unsigned char *destPtr, size_t destSz, unsigned long *crcPtr); static int ReadChunkHeader(Tcl_Interp *interp, PNGImage *pngPtr, - int *sizePtr, unsigned long *typePtr, + size_t *sizePtr, unsigned long *typePtr, unsigned long *crcPtr); static int ReadIDAT(Tcl_Interp *interp, PNGImage *pngPtr, int chunkSz, unsigned long crc); static int ReadIHDR(Tcl_Interp *interp, PNGImage *pngPtr); static inline int ReadInt32(Tcl_Interp *interp, PNGImage *pngPtr, @@ -249,13 +248,13 @@ static int UnfilterLine(Tcl_Interp *interp, PNGImage *pngPtr); static inline int WriteByte(Tcl_Interp *interp, PNGImage *pngPtr, unsigned char c, unsigned long *crcPtr); static inline int WriteChunk(Tcl_Interp *interp, PNGImage *pngPtr, unsigned long chunkType, - const unsigned char *dataPtr, int dataSize); + const unsigned char *dataPtr, size_t dataSize); static int WriteData(Tcl_Interp *interp, PNGImage *pngPtr, - const unsigned char *srcPtr, int srcSz, + const unsigned char *srcPtr, size_t srcSz, unsigned long *crcPtr); static int WriteExtraChunks(Tcl_Interp *interp, PNGImage *pngPtr); static int WriteIHDR(Tcl_Interp *interp, PNGImage *pngPtr, Tk_PhotoImageBlock *blockPtr); @@ -318,11 +317,11 @@ if (objPtr) { Tcl_IncrRefCount(objPtr); pngPtr->objDataPtr = objPtr; pngPtr->strDataBuf = - Tcl_GetByteArrayFromObj(objPtr, &pngPtr->strDataLen); + TkGetByteArrayFromObj(objPtr, &pngPtr->strDataLen); } /* * Initialize the palette transparency table to fully opaque. */ @@ -429,11 +428,11 @@ static int ReadBase64( Tcl_Interp *interp, PNGImage *pngPtr, unsigned char *destPtr, - int destSz, + size_t destSz, unsigned long *crcPtr) { static const unsigned char from64[] = { 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80, 0x80, 0x83, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, @@ -554,26 +553,26 @@ static int ReadByteArray( Tcl_Interp *interp, PNGImage *pngPtr, unsigned char *destPtr, - int destSz, + size_t destSz, unsigned long *crcPtr) { /* * Check to make sure the number of requested bytes are available. */ - if (pngPtr->strDataLen < destSz) { + if ((size_t)pngPtr->strDataLen < destSz) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unexpected end of image data", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EARLY_END", NULL); return TCL_ERROR; } while (destSz) { - int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ); + size_t blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ); memcpy(destPtr, pngPtr->strDataBuf, blockSz); pngPtr->strDataBuf += blockSz; pngPtr->strDataLen -= blockSz; @@ -612,24 +611,24 @@ static int ReadData( Tcl_Interp *interp, PNGImage *pngPtr, unsigned char *destPtr, - int destSz, + size_t destSz, unsigned long *crcPtr) { if (pngPtr->base64Data) { return ReadBase64(interp, pngPtr, destPtr, destSz, crcPtr); } else if (pngPtr->strDataBuf) { return ReadByteArray(interp, pngPtr, destPtr, destSz, crcPtr); } while (destSz) { - int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ); + size_t blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ); - blockSz = Tcl_Read(pngPtr->channel, (char *)destPtr, blockSz); - if (blockSz < 0) { + blockSz = (size_t)Tcl_Read(pngPtr->channel, (char *)destPtr, blockSz); + if (blockSz == (size_t)-1) { /* TODO: failure info... */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel read failed: %s", Tcl_PosixError(interp))); return TCL_ERROR; } @@ -857,11 +856,11 @@ static int ReadChunkHeader( Tcl_Interp *interp, PNGImage *pngPtr, - int *sizePtr, + size_t *sizePtr, unsigned long *typePtr, unsigned long *crcPtr) { unsigned long chunkType = 0; int chunkSz = 0; @@ -1238,11 +1237,11 @@ Tcl_Interp *interp, PNGImage *pngPtr) { unsigned char sigBuf[PNG_SIG_SZ]; unsigned long chunkType; - int chunkSz; + size_t chunkSz; unsigned long crc; unsigned long width, height; int mismatch; /* @@ -1262,11 +1261,11 @@ /* * If reading from string, reset position and try base64 decode. */ if (mismatch && pngPtr->strDataBuf) { - pngPtr->strDataBuf = Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, + pngPtr->strDataBuf = TkGetByteArrayFromObj(pngPtr->objDataPtr, &pngPtr->strDataLen); pngPtr->base64Data = pngPtr->strDataBuf; if (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) { return TCL_ERROR; @@ -2096,11 +2095,11 @@ /* * Process IDAT contents until there is no more in this chunk. */ while (chunkSz && !Tcl_ZlibStreamEof(pngPtr->stream)) { - int len1, len2; + TkSizeT len1, len2; /* * Read another block of input into the zlib stream if data remains. */ @@ -2145,18 +2144,18 @@ * Inflate, processing each output buffer's worth as a line of pixels, * until we cannot fill the buffer any more. */ getNextLine: - Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len1); + TkGetByteArrayFromObj(pngPtr->thisLineObj, &len1); if (Tcl_ZlibStreamGet(pngPtr->stream, pngPtr->thisLineObj, pngPtr->phaseSize - len1) == TCL_ERROR) { return TCL_ERROR; } - Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len2); + TkGetByteArrayFromObj(pngPtr->thisLineObj, &len2); - if (len2 == pngPtr->phaseSize) { + if (len2 == (TkSizeT)pngPtr->phaseSize) { if (pngPtr->phase > 7) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra data after final scan line of final phase", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EXTRA_DATA", @@ -2381,11 +2380,11 @@ Tk_PhotoHandle imageHandle, int destX, int destY) { unsigned long chunkType; - int chunkSz; + size_t chunkSz; unsigned long crc; /* * Parse the PNG signature and IHDR (header) chunk. */ @@ -2766,11 +2765,11 @@ PNGImage png; int match = 0; InitPNGImage(NULL, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE); - png.strDataBuf = Tcl_GetByteArrayFromObj(pObjData, &png.strDataLen); + png.strDataBuf = TkGetByteArrayFromObj(pObjData, &png.strDataLen); if (ReadIHDR(interp, &png) == TCL_OK) { *widthPtr = png.block.width; *heightPtr = png.block.height; match = 1; @@ -2844,11 +2843,11 @@ static int WriteData( Tcl_Interp *interp, PNGImage *pngPtr, const unsigned char *srcPtr, - int srcSz, + size_t srcSz, unsigned long *crcPtr) { if (!srcPtr || !srcSz) { return TCL_OK; } @@ -2861,16 +2860,16 @@ * TODO: is Tcl_AppendObjToObj faster here? i.e., does Tcl join the * objects immediately or store them in a multi-object rep? */ if (pngPtr->objDataPtr) { - int objSz; + TkSizeT objSz; unsigned char *destPtr; - Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, &objSz); + TkGetByteArrayFromObj(pngPtr->objDataPtr, &objSz); - if (objSz > INT_MAX - srcSz) { + if (objSz + srcSz > INT_MAX) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "image too large to store completely in byte array", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "TOO_LARGE", NULL); return TCL_ERROR; } @@ -2883,11 +2882,11 @@ Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); return TCL_ERROR; } memcpy(destPtr+objSz, srcPtr, srcSz); - } else if (Tcl_Write(pngPtr->channel, (const char *) srcPtr, srcSz) < 0) { + } else if (Tcl_Write(pngPtr->channel, (const char *) srcPtr, srcSz) == TCL_IO_FAILURE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write to channel failed: %s", Tcl_PosixError(interp))); return TCL_ERROR; } @@ -2959,11 +2958,11 @@ WriteChunk( Tcl_Interp *interp, PNGImage *pngPtr, unsigned long chunkType, const unsigned char *dataPtr, - int dataSize) + size_t dataSize) { unsigned long crc = Tcl_ZlibCRC32(0, NULL, 0); int result = TCL_OK; /* @@ -3130,13 +3129,14 @@ WriteIDAT( Tcl_Interp *interp, PNGImage *pngPtr, Tk_PhotoImageBlock *blockPtr) { - int rowNum, flush = TCL_ZLIB_NO_FLUSH, outputSize, result; + int rowNum, flush = TCL_ZLIB_NO_FLUSH, result; Tcl_Obj *outputObj; unsigned char *outputBytes; + TkSizeT outputSize; /* * Filter and compress each row one at a time. */ @@ -3224,11 +3224,11 @@ * Now get the compressed data and write it as one big IDAT chunk. */ outputObj = Tcl_NewObj(); (void) Tcl_ZlibStreamGet(pngPtr->stream, outputObj, -1); - outputBytes = Tcl_GetByteArrayFromObj(outputObj, &outputSize); + outputBytes = TkGetByteArrayFromObj(outputObj, &outputSize); result = WriteChunk(interp, pngPtr, CHUNK_IDAT, outputBytes, outputSize); Tcl_DecrRefCount(outputObj); return result; } Index: generic/tkImgPPM.c ================================================================== --- generic/tkImgPPM.c +++ generic/tkImgPPM.c @@ -139,11 +139,12 @@ * written to. */ int srcX, int srcY) /* Coordinates of top-left pixel to be used in * image being read. */ { int fileWidth, fileHeight, maxIntensity; - int nLines, nBytes, h, type, count, bytesPerChannel = 1; + int nLines, h, type, bytesPerChannel = 1; + size_t nBytes, count; unsigned char *pixelPtr; Tk_PhotoImageBlock block; type = ReadPPMFileHeader(chan, &fileWidth, &fileHeight, &maxIntensity); if (type == 0) { @@ -283,11 +284,12 @@ const char *fileName, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr) { Tcl_Channel chan; - int w, h, greenOffset, blueOffset, nBytes; + int w, h, greenOffset, blueOffset; + size_t nBytes; unsigned char *pixelPtr, *pixLinePtr; char header[16 + TCL_INTEGER_SPACE * 2]; chan = Tcl_OpenFileChannel(interp, fileName, "w", 0666); if (chan == NULL) { @@ -313,20 +315,20 @@ blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3) && (blockPtr->pitch == (blockPtr->width * 3))) { nBytes = blockPtr->height * blockPtr->pitch; - if (Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) { + if ((size_t)Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) { goto writeerror; } } else { for (h = blockPtr->height; h > 0; h--) { pixelPtr = pixLinePtr; for (w = blockPtr->width; w > 0; w--) { - if ( Tcl_Write(chan,(char *)&pixelPtr[0], 1) == -1 || - Tcl_Write(chan,(char *)&pixelPtr[greenOffset],1)==-1 || - Tcl_Write(chan,(char *)&pixelPtr[blueOffset],1) ==-1) { + if (Tcl_Write(chan,(char *)&pixelPtr[0], 1) == TCL_IO_FAILURE || + Tcl_Write(chan,(char *)&pixelPtr[greenOffset],1) == TCL_IO_FAILURE || + Tcl_Write(chan,(char *)&pixelPtr[blueOffset],1) == TCL_IO_FAILURE) { goto writeerror; } pixelPtr += blockPtr->pixelSize; } pixLinePtr += blockPtr->pitch; @@ -760,14 +762,15 @@ unsigned char **dataBufferPtr, int *dataSizePtr) { #define BUFFER_SIZE 1000 char buffer[BUFFER_SIZE], c; - int i, numFields, dataSize, type = 0; + int i, numFields, type = 0; + TkSizeT dataSize; unsigned char *dataBuffer; - dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize); + dataBuffer = TkGetByteArrayFromObj(dataPtr, &dataSize); /* * Read 4 space-separated fields from the string, ignoring comments (any * line that starts with "#"). */ Index: generic/tkImgPhInstance.c ================================================================== --- generic/tkImgPhInstance.c +++ generic/tkImgPhInstance.c @@ -113,11 +113,11 @@ /* * Free up our old color table, and get a new one. */ if (colorTablePtr != NULL) { - colorTablePtr->liveRefCount -= 1; + colorTablePtr->liveRefCount--; FreeColorTable(colorTablePtr, 0); } GetColorTable(instancePtr); /* @@ -743,11 +743,11 @@ * structure. */ colorPtr = instancePtr->colorTablePtr; if (colorPtr != NULL) { - colorPtr->liveRefCount -= 1; + colorPtr->liveRefCount--; } Tcl_DoWhenIdle(TkImgDisposeInstance, instancePtr); } @@ -865,12 +865,12 @@ */ if (masterPtr->width == instancePtr->width) { offset = validBox.y * masterPtr->width * 3; memcpy(newError + offset, instancePtr->error + offset, - (size_t) (validBox.height - * masterPtr->width * 3 * sizeof(schar))); + (size_t) validBox.height + * masterPtr->width * 3 * sizeof(schar)); } else if (validBox.width > 0 && validBox.height > 0) { errDestPtr = newError + (validBox.y * masterPtr->width + validBox.x) * 3; errSrcPtr = instancePtr->error + @@ -1126,12 +1126,11 @@ FreeColorTable( ColorTable *colorPtr, /* Pointer to the color table which is no * longer required by an instance. */ int force) /* Force free to happen immediately. */ { - colorPtr->refCount--; - if (colorPtr->refCount > 0) { + if (colorPtr->refCount-- > 1) { return; } if (force) { if (colorPtr->flags & DISPOSE_PENDING) { @@ -1460,11 +1459,11 @@ Tk_FreeColormap(colorPtr->id.display, colorPtr->id.colormap); } ckfree(colorPtr->pixelMap); } - entry = Tcl_FindHashEntry(&imgPhotoColorHash, (char *) &colorPtr->id); + entry = Tcl_FindHashEntry(&imgPhotoColorHash, &colorPtr->id); if (entry == NULL) { Tcl_Panic("DisposeColorTable couldn't find hash entry"); } Tcl_DeleteHashEntry(entry); @@ -1981,12 +1980,12 @@ TkImgResetDither( PhotoInstance *instancePtr) { if (instancePtr->error) { memset(instancePtr->error, 0, - /*(size_t)*/ (instancePtr->masterPtr->width - * instancePtr->masterPtr->height * 3 * sizeof(schar))); + (size_t) instancePtr->masterPtr->width + * instancePtr->masterPtr->height * 3 * sizeof(schar)); } } /* * Local Variables: Index: generic/tkImgPhoto.c ================================================================== --- generic/tkImgPhoto.c +++ generic/tkImgPhoto.c @@ -46,45 +46,51 @@ * allowedOptions parameter on a call to ParseSubcommandOptions if that option * is allowed for the current photo image subcommand. On return, the bit is * set in the options field of the SubcommandOptions structure if that option * was specified. * + * OPT_ALPHA: Set if -alpha option allowed/specified. * OPT_BACKGROUND: Set if -format option allowed/specified. * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd. * OPT_FORMAT: Set if -format option allowed/specified. * OPT_FROM: Set if -from option allowed/specified. * OPT_GRAYSCALE: Set if -grayscale option allowed/specified. * OPT_SHRINK: Set if -shrink option allowed/specified. * OPT_SUBSAMPLE: Set if -subsample option allowed/spec'd. * OPT_TO: Set if -to option allowed/specified. + * OPT_WITHALPHA: Set if -withalpha option allowed/specified. * OPT_ZOOM: Set if -zoom option allowed/specified. */ -#define OPT_BACKGROUND 1 -#define OPT_COMPOSITE 2 -#define OPT_FORMAT 4 -#define OPT_FROM 8 -#define OPT_GRAYSCALE 0x10 -#define OPT_SHRINK 0x20 -#define OPT_SUBSAMPLE 0x40 -#define OPT_TO 0x80 -#define OPT_ZOOM 0x100 +#define OPT_ALPHA 1 +#define OPT_BACKGROUND 2 +#define OPT_COMPOSITE 4 +#define OPT_FORMAT 8 +#define OPT_FROM 0x10 +#define OPT_GRAYSCALE 0x20 +#define OPT_SHRINK 0x40 +#define OPT_SUBSAMPLE 0x80 +#define OPT_TO 0x100 +#define OPT_WITHALPHA 0x200 +#define OPT_ZOOM 0x400 /* * List of option names. The order here must match the order of declarations * of the OPT_* constants above. */ static const char *const optionNames[] = { + "-alpha", "-background", "-compositingrule", "-format", "-from", "-grayscale", "-shrink", "-subsample", "-to", + "-withalpha", "-zoom", NULL }; /* @@ -123,11 +129,11 @@ ImgPhotoPostscript, /* postscriptProc */ NULL, /* nextPtr */ NULL }; -typedef struct ThreadSpecificData { +typedef struct { Tk_PhotoImageFormat *formatList; /* Pointer to the first in the list of known * photo image formats.*/ Tk_PhotoImageFormat *oldFormatList; /* Pointer to the first in the list of known @@ -150,19 +156,19 @@ * Information used for parsing configuration specifications: */ static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_STRING, "-file", NULL, NULL, - NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(PhotoMaster, fileString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_DOUBLE, "-gamma", NULL, NULL, - DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0, NULL}, + DEF_PHOTO_GAMMA, offsetof(PhotoMaster, gamma), 0, NULL}, {TK_CONFIG_INT, "-height", NULL, NULL, - DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0, NULL}, + DEF_PHOTO_HEIGHT, offsetof(PhotoMaster, userHeight), 0, NULL}, {TK_CONFIG_UID, "-palette", NULL, NULL, - DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0, NULL}, + DEF_PHOTO_PALETTE, offsetof(PhotoMaster, palette), 0, NULL}, {TK_CONFIG_INT, "-width", NULL, NULL, - DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0, NULL}, + DEF_PHOTO_WIDTH, offsetof(PhotoMaster, userWidth), 0, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* * Forward declarations @@ -180,13 +186,10 @@ PhotoMaster *masterPtr, int objc, Tcl_Obj *const objv[], int flags); static int ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr); static int ImgPhotoSetSize(PhotoMaster *masterPtr, int width, int height); -static int ImgStringWrite(Tcl_Interp *interp, - Tcl_Obj *formatString, - Tk_PhotoImageBlock *blockPtr); static char * ImgGetPhoto(PhotoMaster *masterPtr, Tk_PhotoImageBlock *blockPtr, struct SubcommandOptions *optPtr); static int MatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan, const char *fileName, Tcl_Obj *formatString, @@ -400,18 +403,16 @@ PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS, PHOTO_WRITE }; PhotoMaster *masterPtr = clientData; - int result, index, x, y, width, height, dataWidth, dataHeight, listObjc; + int result, index, x, y, width, height; struct SubcommandOptions options; - Tcl_Obj **listObjv, **srcObjv; unsigned char *pixelPtr; Tk_PhotoImageBlock block; - Tk_Window tkwin; Tk_PhotoImageFormat *imageFormat; - size_t length; + TkSizeT length; int imageWidth, imageHeight, matched, oldformat = 0; Tcl_Channel chan; Tk_PhotoHandle srcHandle; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -445,12 +446,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); return TCL_ERROR; } - arg = Tcl_GetString(objv[2]); - length = objv[2]->length; + arg = TkGetStringFromObj(objv[2], &length); if (strncmp(arg,"-data", length) == 0) { if (masterPtr->dataString) { Tcl_SetObjResult(interp, masterPtr->dataString); } } else if (strncmp(arg,"-format", length) == 0) { @@ -495,13 +495,12 @@ Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp)); Tcl_SetObjResult(interp, obj); return TCL_OK; } else if (objc == 3) { - const char *arg = Tcl_GetString(objv[2]); + const char *arg = TkGetStringFromObj(objv[2], &length); - length = objv[2]->length; if (length > 1 && !strncmp(arg, "-data", length)) { Tcl_AppendResult(interp, "-data {} {} {}", NULL); if (masterPtr->dataString) { /* * TODO: Modifying result is bad! @@ -666,19 +665,20 @@ Tk_FreeColor(options.background); } return result; case PHOTO_DATA: { - char *data; + char *data = NULL; + Tcl_Obj *freeObj = NULL; /* * photo data command - first parse and check any options given. */ Tk_ImageStringWriteProc *stringWriteProc = NULL; - index = 2; + index = 1; memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; options.fromX = 0; options.fromY = 0; @@ -685,11 +685,11 @@ if (ParseSubcommandOptions(&options, interp, OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND, &index, objc, objv) != TCL_OK) { return TCL_ERROR; } - if ((options.name != NULL) || (index < objc)) { + if ((options.name == NULL) || (index < objc)) { Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?"); return TCL_ERROR; } if ((options.fromX > masterPtr->width) || (options.fromY > masterPtr->height) @@ -707,54 +707,54 @@ if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) { options.fromX2 = masterPtr->width; options.fromY2 = masterPtr->height; } + if (!(options.options & OPT_FORMAT)) { + options.format = Tcl_NewStringObj("default", -1); + freeObj = options.format; + } /* * Search for an appropriate image string format handler. */ - if (options.options & OPT_FORMAT) { - matched = 0; - for (imageFormat = tsdPtr->formatList; imageFormat != NULL; - imageFormat = imageFormat->nextPtr) { - if ((strncasecmp(Tcl_GetString(options.format), - imageFormat->name, strlen(imageFormat->name)) == 0)) { - matched = 1; - if (imageFormat->stringWriteProc != NULL) { - stringWriteProc = imageFormat->stringWriteProc; - break; - } - } - } - if (stringWriteProc == NULL) { - oldformat = 1; - for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL; - imageFormat = imageFormat->nextPtr) { - if ((strncasecmp(Tcl_GetString(options.format), - imageFormat->name, - strlen(imageFormat->name)) == 0)) { - matched = 1; - if (imageFormat->stringWriteProc != NULL) { - stringWriteProc = imageFormat->stringWriteProc; - break; - } - } - } - } - if (stringWriteProc == NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "image string format \"%s\" is %s", - Tcl_GetString(options.format), - (matched ? "not supported" : "unknown"))); - Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT", - Tcl_GetString(options.format), NULL); - return TCL_ERROR; - } - } else { - stringWriteProc = ImgStringWrite; + matched = 0; + for (imageFormat = tsdPtr->formatList; imageFormat != NULL; + imageFormat = imageFormat->nextPtr) { + if ((strncasecmp(Tcl_GetString(options.format), + imageFormat->name, strlen(imageFormat->name)) == 0)) { + matched = 1; + if (imageFormat->stringWriteProc != NULL) { + stringWriteProc = imageFormat->stringWriteProc; + break; + } + } + } + if (stringWriteProc == NULL) { + oldformat = 1; + for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL; + imageFormat = imageFormat->nextPtr) { + if ((strncasecmp(Tcl_GetString(options.format), + imageFormat->name, + strlen(imageFormat->name)) == 0)) { + matched = 1; + if (imageFormat->stringWriteProc != NULL) { + stringWriteProc = imageFormat->stringWriteProc; + break; + } + } + } + } + if (stringWriteProc == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "image string format \"%s\" is %s", + Tcl_GetString(options.format), + (matched ? "not supported" : "unknown"))); + Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT", + Tcl_GetString(options.format), NULL); + goto dataErrorExit; } /* * Call the handler's string write function to write out the image. */ @@ -787,24 +787,51 @@ Tk_FreeColor(options.background); } if (data) { ckfree(data); } + if (freeObj != NULL) { + Tcl_DecrRefCount(freeObj); + } return result; + + dataErrorExit: + if (options.background) { + Tk_FreeColor(options.background); + } + if (data) { + ckfree(data); + } + if (freeObj != NULL) { + Tcl_DecrRefCount(freeObj); + } + return TCL_ERROR; } case PHOTO_GET: { /* * photo get command - first parse and check parameters. */ - Tcl_Obj *channels[3]; + Tcl_Obj *channels[4]; + int channelCount = 3; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "x y"); + index = 3; + memset(&options, 0, sizeof(options)); + options.name = NULL; + if (ParseSubcommandOptions(&options, interp, OPT_WITHALPHA, + &index, objc, objv) != TCL_OK) { + return TCL_ERROR; + } + if (options.name == NULL || index < objc) { + Tcl_WrongNumArgs(interp, 2, objv, "x y ?-withalpha?"); return TCL_ERROR; } + if (options.options & OPT_WITHALPHA) { + channelCount = 4; + } + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { return TCL_ERROR; } if ((x < 0) || (x >= masterPtr->width) @@ -816,206 +843,86 @@ NULL); return TCL_ERROR; } /* - * Extract the value of the desired pixel and format it as a string. + * Extract the value of the desired pixel and format it as a list. */ pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; - channels[0] = Tcl_NewIntObj(pixelPtr[0]); - channels[1] = Tcl_NewIntObj(pixelPtr[1]); - channels[2] = Tcl_NewIntObj(pixelPtr[2]); - Tcl_SetObjResult(interp, Tcl_NewListObj(3, channels)); + channels[0] = Tcl_NewWideIntObj(pixelPtr[0]); + channels[1] = Tcl_NewWideIntObj(pixelPtr[1]); + channels[2] = Tcl_NewWideIntObj(pixelPtr[2]); + channels[3] = Tcl_NewWideIntObj(pixelPtr[3]); + Tcl_SetObjResult(interp, Tcl_NewListObj(channelCount, channels)); return TCL_OK; } - case PHOTO_PUT: + case PHOTO_PUT: { + Tcl_Obj *format, *data; + /* - * photo put command - first parse the options and colors specified. + * photo put command - first parse the options. */ index = 2; memset(&options, 0, sizeof(options)); options.name = NULL; + options.format = NULL; if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT, &index, objc, objv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < objc)) { Tcl_WrongNumArgs(interp, 2, objv, "data ?-option value ...?"); return TCL_ERROR; } - if (MatchStringFormat(interp, options.name ? objv[2]:NULL, - options.format, &imageFormat, &imageWidth, - &imageHeight, &oldformat) == TCL_OK) { - Tcl_Obj *format, *data; - - if (!(options.options & OPT_TO) || (options.toX2 < 0)) { - options.toX2 = options.toX + imageWidth; - options.toY2 = options.toY + imageHeight; - } - if (imageWidth > options.toX2 - options.toX) { - imageWidth = options.toX2 - options.toX; - } - if (imageHeight > options.toY2 - options.toY) { - imageHeight = options.toY2 - options.toY; - } - format = options.format; - data = objv[2]; - if (oldformat) { - if (format) { - format = (Tcl_Obj *) Tcl_GetString(format); - } - data = (Tcl_Obj *) Tcl_GetString(data); - } - if (imageFormat->stringReadProc(interp, data, format, - (Tk_PhotoHandle) masterPtr, options.toX, options.toY, - imageWidth, imageHeight, 0, 0) != TCL_OK) { - return TCL_ERROR; - } - masterPtr->flags |= IMAGE_CHANGED; - return TCL_OK; - } - if (options.options & OPT_FORMAT) { - return TCL_ERROR; - } - Tcl_ResetResult(interp); - if (Tcl_ListObjGetElements(interp, options.name, - &dataHeight, &srcObjv) != TCL_OK) { - return TCL_ERROR; - } - tkwin = Tk_MainWindow(interp); - block.pixelPtr = NULL; - dataWidth = 0; - pixelPtr = NULL; - for (y = 0; y < dataHeight; ++y) { - if (Tcl_ListObjGetElements(interp, srcObjv[y], - &listObjc, &listObjv) != TCL_OK) { - break; - } - - if (y == 0) { - if (listObjc == 0) { - /* - * Lines must be non-empty... - */ - - break; - } - dataWidth = listObjc; - /* - * Memory allocation overflow protection. - * May not be able to trigger/ demo / test this. - */ - - if (dataWidth > (int)((UINT_MAX/3) / dataHeight)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "photo image dimensions exceed Tcl memory limits", -1)); - Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", - "OVERFLOW", NULL); - break; - } - - pixelPtr = ckalloc(dataWidth * dataHeight * 3); - block.pixelPtr = pixelPtr; - } else if (listObjc != dataWidth) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "all elements of color list must have the same" - " number of elements", -1)); - Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", - "NON_RECTANGULAR", NULL); - break; - } - - for (x = 0; x < dataWidth; ++x) { - const char *colorString = Tcl_GetString(listObjv[x]); - XColor color; - int tmpr, tmpg, tmpb; - - /* - * We do not use Tk_GetColorFromObj() because we absolutely do - * not want to invoke the fallback code. - */ - - if (colorString[0] == '#') { - if (isxdigit(UCHAR(colorString[1])) && - isxdigit(UCHAR(colorString[2])) && - isxdigit(UCHAR(colorString[3]))) { - if (colorString[4] == '\0') { - /* Got #rgb */ - sscanf(colorString+1, "%1x%1x%1x", - &tmpr, &tmpg, &tmpb); - *pixelPtr++ = tmpr * 0x11; - *pixelPtr++ = tmpg * 0x11; - *pixelPtr++ = tmpb * 0x11; - continue; - } else if (isxdigit(UCHAR(colorString[4])) && - isxdigit(UCHAR(colorString[5])) && - isxdigit(UCHAR(colorString[6])) && - colorString[7] == '\0') { - /* Got #rrggbb */ - sscanf(colorString+1, "%2x%2x%2x", - &tmpr, &tmpg, &tmpb); - *pixelPtr++ = tmpr; - *pixelPtr++ = tmpg; - *pixelPtr++ = tmpb; - continue; - } - } - } - - if (!TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), - colorString, &color)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't parse color \"%s\"", colorString)); - Tcl_SetErrorCode(interp, "TK", "VALUE", "COLOR", NULL); - break; - } - *pixelPtr++ = color.red >> 8; - *pixelPtr++ = color.green >> 8; - *pixelPtr++ = color.blue >> 8; - } - if (x < dataWidth) { - break; - } - } - if (y < dataHeight || dataHeight == 0 || dataWidth == 0) { - if (block.pixelPtr != NULL) { - ckfree(block.pixelPtr); - } - if (y < dataHeight) { - return TCL_ERROR; - } - return TCL_OK; - } - - /* - * Fill in default values for the -to option, then copy the block in - * using Tk_PhotoPutBlock. - */ - - if (!(options.options & OPT_TO) || (options.toX2 < 0)) { - options.toX2 = options.toX + dataWidth; - options.toY2 = options.toY + dataHeight; - } - block.width = dataWidth; - block.height = dataHeight; - block.pitch = dataWidth * 3; - block.pixelSize = 3; - block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; - block.offset[3] = 0; - result = Tk_PhotoPutBlock(interp, masterPtr, &block, - options.toX, options.toY, options.toX2 - options.toX, - options.toY2 - options.toY, - TK_PHOTO_COMPOSITE_SET); - ckfree(block.pixelPtr); - return result; - + /* + * See if there's a format that can read the data + */ + + if (MatchStringFormat(interp, objv[2], options.format, &imageFormat, + &imageWidth, &imageHeight, &oldformat) != TCL_OK) { + return TCL_ERROR; + } + + if (!(options.options & OPT_TO) || (options.toX2 < 0)) { + options.toX2 = options.toX + imageWidth; + options.toY2 = options.toY + imageHeight; + } + if (imageWidth > options.toX2 - options.toX) { + imageWidth = options.toX2 - options.toX; + } + if (imageHeight > options.toY2 - options.toY) { + imageHeight = options.toY2 - options.toY; + } + format = options.format; + data = objv[2]; + if (oldformat) { + if (format) { + format = (Tcl_Obj *) Tcl_GetString(format); + } + data = (Tcl_Obj *) Tcl_GetString(data); + } + + if (imageFormat->stringReadProc(interp, data, format, + (Tk_PhotoHandle) masterPtr, options.toX, options.toY, + options.toX2 - options.toX, + options.toY2 - options.toY, 0, 0) != TCL_OK) { + return TCL_ERROR; + } + /* + * SB: is the next line really needed? The stringReadProc + * writes image data with Tk_PhotoPutBlock(), which in turn + * takes care to notify the changed image and to set/unset the + * IMAGE_CHANGED bit. + */ + masterPtr->flags |= IMAGE_CHANGED; + + return TCL_OK; + } case PHOTO_READ: { Tcl_Obj *format; /* * photo read command - first parse the options specified. @@ -1181,21 +1088,44 @@ return TCL_ERROR; } switch ((enum transOptions) index) { case PHOTO_TRANS_GET: { - XRectangle testBox; - TkRegion testRegion; + int boolMode; - if (objc != 5) { - Tcl_WrongNumArgs(interp, 3, objv, "x y"); + /* + * parse fixed args and option + */ + + if (objc > 6 || objc < 5) { + Tcl_WrongNumArgs(interp, 3, objv, "x y ?-option?"); return TCL_ERROR; } if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) { return TCL_ERROR; } + + index = 4; + memset(&options, 0, sizeof(options)); + if (ParseSubcommandOptions(&options, interp, + OPT_ALPHA, &index, objc, objv) != TCL_OK) { + return TCL_ERROR; + } + if (index < objc) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "unknown option \"%s\": must be -alpha", + Tcl_GetString(objv[index]))); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", + NULL); + return TCL_ERROR; + } + boolMode = 1; + if (options.options & OPT_ALPHA) { + boolMode = 0; + } + if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s transparency get: coordinates out of range", Tcl_GetString(objv[0]))); @@ -1202,82 +1132,116 @@ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES", NULL); return TCL_ERROR; } - testBox.x = x; - testBox.y = y; - testBox.width = 1; - testBox.height = 1; - /* What a way to do a test! */ - testRegion = TkCreateRegion(); - TkUnionRectWithRegion(&testBox, testRegion, testRegion); - TkIntersectRegion(testRegion, masterPtr->validRegion, testRegion); - TkClipBox(testRegion, &testBox); - TkDestroyRegion(testRegion); - - Tcl_SetObjResult(interp, Tcl_NewBooleanObj( - testBox.width==0 && testBox.height==0)); + /* + * Extract and return the desired value + */ + pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; + if (boolMode) { + Tcl_SetObjResult(interp, Tcl_NewBooleanObj( ! pixelPtr[3])); + } else { + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pixelPtr[3])); + } return TCL_OK; } case PHOTO_TRANS_SET: { - int transFlag; + int newVal, boolMode; XRectangle setBox; + TkRegion modRegion; - if (objc != 6) { - Tcl_WrongNumArgs(interp, 3, objv, "x y boolean"); + /* + * Parse args and option, check for valid values + */ + + if (objc < 6 || objc > 7) { + Tcl_WrongNumArgs(interp, 3, objv, "x y newVal ?-option?"); return TCL_ERROR; } if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) - || (Tcl_GetBooleanFromObj(interp, objv[5], - &transFlag) != TCL_OK)) { + || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) { + return TCL_ERROR; + } + + index = 5; + memset(&options, 0, sizeof(options)); + if (ParseSubcommandOptions(&options, interp, + OPT_ALPHA, &index, objc, objv) != TCL_OK) { + return TCL_ERROR; + } + if (index < objc) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "unknown option \"%s\": must be -alpha", + Tcl_GetString(objv[index]))); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", + NULL); return TCL_ERROR; } + boolMode = 1; + if (options.options & OPT_ALPHA) { + boolMode = 0; + } + if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s transparency set: coordinates out of range", Tcl_GetString(objv[0]))); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES", NULL); return TCL_ERROR; } + + if (boolMode) { + if (Tcl_GetBooleanFromObj(interp, objv[5], &newVal) != TCL_OK) { + return TCL_ERROR; + } + } else { + if (Tcl_GetIntFromObj(interp, objv[5], &newVal) != TCL_OK) { + return TCL_ERROR; + } + if (newVal < 0 || newVal > 255) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid alpha value \"%d\": " + "must be integer between 0 and 255", newVal)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "BAD_VALUE", NULL); + return TCL_ERROR; + } + } + + /* + * Set new alpha value for the pixel + */ + + pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; + if (boolMode) { + pixelPtr[3] = newVal ? 0 : 255; + } else { + pixelPtr[3] = newVal; + } + + /* + * Update the validRegion of the image + */ setBox.x = x; setBox.y = y; setBox.width = 1; setBox.height = 1; - pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; - - if (transFlag) { - /* - * Make pixel transparent. - */ - - TkRegion clearRegion = TkCreateRegion(); - - TkUnionRectWithRegion(&setBox, clearRegion, clearRegion); - TkSubtractRegion(masterPtr->validRegion, clearRegion, - masterPtr->validRegion); - TkDestroyRegion(clearRegion); - - /* - * Set the alpha value correctly. - */ - - pixelPtr[3] = 0; - } else { - /* - * Make pixel opaque. - */ - + modRegion = TkCreateRegion(); + TkUnionRectWithRegion(&setBox, modRegion, modRegion); + if (pixelPtr[3]) { TkUnionRectWithRegion(&setBox, masterPtr->validRegion, masterPtr->validRegion); - pixelPtr[3] = 255; + } else { + TkSubtractRegion(masterPtr->validRegion, modRegion, + masterPtr->validRegion); } + TkDestroyRegion(modRegion); /* * Inform the generic image code that the image * has (potentially) changed. */ @@ -1475,17 +1439,22 @@ * * ParseSubcommandOptions -- * * This function is invoked to process one of the options which may be * specified for the photo image subcommands, namely, -from, -to, -zoom, - * -subsample, -format, -shrink, and -compositingrule. + * -subsample, -format, -shrink, -compositingrule, -alpha, -boolean and + * -withalpha. + * Parsing starts at the index in *optIndexPtr and stops at the end of + * objv[] or at the first value that does not belong to an option. * * Results: * A standard Tcl result. * * Side effects: - * Fields in *optPtr get filled in. + * Fields in *optPtr get filled in. The value of optIndexPtr is updated + * to contain the index of the first element in argv[] that was not + * parsed, or argc if the end of objv[] was reached. * *---------------------------------------------------------------------- */ static int @@ -1505,11 +1474,11 @@ static const char *const compositingRules[] = { "overlay", "set", /* Note that these must match the * TK_PHOTO_COMPOSITE_* constants. */ NULL }; - size_t length; + TkSizeT length; int index, c, bit, currentBit; int values[4], numValues, maxValues, argIndex; const char *option, *expandedOption, *needed; const char *const *listPtr; Tcl_Obj *msgObj; @@ -1518,12 +1487,11 @@ /* * We can have one value specified without an option; it goes into * optPtr->name. */ - expandedOption = option = Tcl_GetString(objv[index]); - length = objv[index]->length; + expandedOption = option = TkGetStringFromObj(objv[index], &length); if (option[0] != '-') { if (optPtr->name == NULL) { optPtr->name = objv[index]; continue; } @@ -1606,11 +1574,12 @@ "compositing rule", 0, &optPtr->compositingRule) != TCL_OK) { return TCL_ERROR; } *optIndexPtr = index; - } else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) { + } else if (bit == OPT_TO || bit == OPT_FROM + || bit == OPT_SUBSAMPLE || bit == OPT_ZOOM) { const char *val; maxValues = ((bit == OPT_FROM) || (bit == OPT_TO)) ? 4 : 2; argIndex = index + 1; for (numValues = 0; numValues < maxValues; ++numValues) { @@ -1787,21 +1756,20 @@ { PhotoInstance *instancePtr; const char *oldFileString, *oldPaletteString; Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL; Tcl_Obj *tempdata, *tempformat; - size_t length; + TkSizeT length; int i, j, result, imageWidth, imageHeight, oldformat; double oldGamma; Tcl_Channel chan; Tk_PhotoImageFormat *imageFormat; const char **args; args = ckalloc((objc + 1) * sizeof(char *)); for (i = 0, j = 0; i < objc; i++,j++) { - args[j] = Tcl_GetString(objv[i]); - length = objv[i]->length; + args[j] = TkGetStringFromObj(objv[i], &length); if ((length > 1) && (args[j][0] == '-')) { if ((args[j][1] == 'd') && !strncmp(args[j], "-data", length)) { if (++i < objc) { data = objv[i]; @@ -1876,13 +1844,13 @@ if (data) { /* * Force into ByteArray format, which most (all) image handlers will * use anyway. Empty length means ignore the -data option. */ - int bytesize; + TkSizeT bytesize; - (void) Tcl_GetByteArrayFromObj(data, &bytesize); + (void) TkGetByteArrayFromObj(data, &bytesize); if (bytesize) { Tcl_IncrRefCount(data); } else { data = NULL; } @@ -2562,11 +2530,11 @@ /* The dimensions of the image are returned * here. */ int *oldformat) /* Returns 1 if the old image API is used. */ { int matched = 0, useoldformat = 0; - Tk_PhotoImageFormat *formatPtr; + Tk_PhotoImageFormat *formatPtr, *defaultFormatPtr = NULL; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); const char *formatString = NULL; if (formatObj) { @@ -2578,10 +2546,20 @@ * handle the image. */ for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { + /* + * To keep the behaviour of older versions (Tk <= 8.6), the default + * list-of-lists string format is checked last. Remember its position. + */ + + if (strncasecmp("default", formatPtr->name, strlen(formatPtr->name)) + == 0) { + defaultFormatPtr = formatPtr; + } + if (formatObj != NULL) { if (strncasecmp(formatString, formatPtr->name, strlen(formatPtr->name)) != 0) { continue; } @@ -2593,10 +2571,20 @@ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "NOT_DATA_FORMAT", NULL); return TCL_ERROR; } } + + /* + * If this is the default format, and it was not passed as -format + * option, skip the stringMatchProc test. It'll be done later + */ + + if (formatObj == NULL && formatPtr == defaultFormatPtr) { + continue; + } + if ((formatPtr->stringMatchProc != NULL) && (formatPtr->stringReadProc != NULL) && formatPtr->stringMatchProc(data, formatObj, widthPtr, heightPtr, interp)) { break; @@ -2630,27 +2618,59 @@ widthPtr, heightPtr, interp)) { break; } } } + if (formatPtr == NULL) { - if ((formatObj != NULL) && !matched) { + /* + * Try the default format as last resort (only if no -format option + * was passed). + */ + + if ( formatObj == NULL && defaultFormatPtr == NULL) { + Tcl_Panic("default image format handler not registered"); + } + if ( formatObj == NULL + && defaultFormatPtr->stringMatchProc != NULL + && defaultFormatPtr->stringReadProc != NULL + && defaultFormatPtr->stringMatchProc(data, formatObj, + widthPtr, heightPtr, interp) != 0) { + useoldformat = 0; + formatPtr = defaultFormatPtr; + } else if ((formatObj != NULL) && !matched) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "image format \"%s\" is not supported", formatString)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT", formatString, NULL); + return TCL_ERROR; } else { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "couldn't recognize image data", -1)); - Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", - "UNRECOGNIZED_DATA", NULL); + + /* + * Some lower level routine (stringMatchProc) may have already set + * a specific error message, so just return this. Otherwise return + * a generic image data error. + */ + + if (Tcl_GetString(Tcl_GetObjResult(interp))[0] == '\0') { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't recognize image data", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "UNRECOGNIZED_DATA", NULL); + } + return TCL_ERROR; } - return TCL_ERROR; } *imageFormatPtr = formatPtr; *oldformat = useoldformat; + + /* + * Some stringMatchProc might have left error messages and error codes in + * interp. Clear them before return. + */ + Tcl_ResetResult(interp); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -3938,61 +3958,10 @@ } /* *---------------------------------------------------------------------- * - * ImgStringWrite -- - * - * Default string write function. The data is formatted in the default - * format as accepted by the " put" command. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *---------------------------------------------------------------------- - */ - -static int -ImgStringWrite( - Tcl_Interp *interp, - Tcl_Obj *formatString, - Tk_PhotoImageBlock *blockPtr) -{ - int greenOffset, blueOffset; - Tcl_Obj *data; - - greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; - blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; - - data = Tcl_NewObj(); - if ((blockPtr->width > 0) && (blockPtr->height > 0)) { - int row, col; - - for (row=0; rowheight; row++) { - Tcl_Obj *line = Tcl_NewObj(); - unsigned char *pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] - + row * blockPtr->pitch; - - for (col=0; colwidth; col++) { - Tcl_AppendPrintfToObj(line, "%s#%02x%02x%02x", - col ? " " : "", *pixelPtr, - pixelPtr[greenOffset], pixelPtr[blueOffset]); - pixelPtr += blockPtr->pixelSize; - } - Tcl_ListObjAppendElement(NULL, data, line); - } - } - Tcl_SetObjResult(interp, data); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * * Tk_PhotoGetImage -- * * This function is called to obtain image data from a photo image. This * function fills in the Tk_PhotoImageBlock structure pointed to by * `blockPtr' with details of the address and layout of the image data in @@ -4031,11 +4000,11 @@ } /* *-------------------------------------------------------------- * - * TkPostscriptPhoto -- + * ImgPostscriptPhoto -- * * This function is called to output the contents of a photo image in * Postscript by calling the Tk_PostscriptPhoto function. * * Results: @@ -4076,11 +4045,11 @@ * always "overlay" and the function always panics on memory-allocation * failure. * *---------------------------------------------------------------------- */ - +#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 void Tk_PhotoPutBlock_NoComposite( Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height) @@ -4162,13 +4131,15 @@ { if (Tk_PhotoSetSize(NULL, handle, width, height) != TCL_OK) { Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); } } +#endif /* TK_NO_DEPRECATED */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 + * tab-width: 8 * End: */ Index: generic/tkImgPhoto.h ================================================================== --- generic/tkImgPhoto.h +++ generic/tkImgPhoto.h @@ -91,14 +91,21 @@ */ struct ColorTable { ColorTableId id; /* Information used in selecting this color * table. */ +#if TCL_MAJOR_VERSION > 8 + size_t refCount; /* Number of instances using this map. */ + size_t liveRefCount; /* Number of instances which are actually in + * use, using this map. */ + int flags; /* See below. */ +#else int flags; /* See below. */ - int refCount; /* Number of instances using this map. */ - int liveRefCount; /* Number of instances which are actually in + unsigned int refCount; /* Number of instances using this map. */ + unsigned int liveRefCount; /* Number of instances which are actually in * use, using this map. */ +#endif int numColors; /* Number of colors allocated for this map. */ XVisualInfo visualInfo; /* Information about the visual for windows * using this color table. */ @@ -199,11 +206,15 @@ Display *display; /* Display for windows using this instance. */ Colormap colormap; /* The image may only be used in windows with * this particular colormap. */ PhotoInstance *nextPtr; /* Pointer to the next instance in the list of * instances associated with this master. */ - int refCount; /* Number of instances using this structure. */ +#if TCL_MAJOR_VERSION > 8 + size_t refCount; /* Number of instances using this structure. */ +#else + unsigned int refCount; /* Number of instances using this structure. */ +#endif Tk_Uid palette; /* Palette for these particular instances. */ double gamma; /* Gamma value for these instances. */ Tk_Uid defaultPalette; /* Default palette to use if a palette is not * specified for the master. */ ColorTable *colorTablePtr; /* Pointer to information about colors ADDED generic/tkImgSVGnano.c Index: generic/tkImgSVGnano.c ================================================================== --- /dev/null +++ generic/tkImgSVGnano.c @@ -0,0 +1,698 @@ +/* + * tkImgSVGnano.c + * + * A photo file handler for SVG files. + * + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * Copyright (c) 2018 Christian Gollwitzer auriocus@gmx.de + * Copyright (c) 2018 Rene Zaumseil r.zaumseil@freenet.de + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * This handler is build using the original nanosvg library files from + * https://github.com/memononen/nanosvg and the tcl extension files from + * https://github.com/auriocus/tksvg + * + */ + +#include "tkInt.h" +#define NANOSVG_malloc ckalloc +#define NANOSVG_realloc ckrealloc +#define NANOSVG_free ckfree +#define NANOSVG_SCOPE MODULE_SCOPE +#define NANOSVG_ALL_COLOR_KEYWORDS +#define NANOSVG_IMPLEMENTATION +#include "nanosvg.h" +#define NANOSVGRAST_IMPLEMENTATION +#include "nanosvgrast.h" + +/* Additional parameters to nsvgRasterize() */ + +typedef struct { + double x; + double y; + double scale; +} RastOpts; + +/* + * Per interp cache of last NSVGimage which was matched to + * be immediately rasterized after the match. This helps to + * eliminate double parsing of the SVG file/string. + */ + +typedef struct { + ClientData dataOrChan; + Tcl_DString formatString; + NSVGimage *nsvgImage; + RastOpts ropts; +} NSVGcache; + +static int FileMatchSVG(Tcl_Channel chan, const char *fileName, + Tcl_Obj *format, int *widthPtr, int *heightPtr, + Tcl_Interp *interp); +static int FileReadSVG(Tcl_Interp *interp, Tcl_Channel chan, + const char *fileName, Tcl_Obj *format, + Tk_PhotoHandle imageHandle, int destX, int destY, + int width, int height, int srcX, int srcY); +static int StringMatchSVG(Tcl_Obj *dataObj, Tcl_Obj *format, + int *widthPtr, int *heightPtr, Tcl_Interp *interp); +static int StringReadSVG(Tcl_Interp *interp, Tcl_Obj *dataObj, + Tcl_Obj *format, Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, + int srcX, int srcY); +static NSVGimage * ParseSVGWithOptions(Tcl_Interp *interp, + const char *input, TkSizeT length, Tcl_Obj *format, + RastOpts *ropts); +static int RasterizeSVG(Tcl_Interp *interp, + Tk_PhotoHandle imageHandle, NSVGimage *nsvgImage, + int destX, int destY, int width, int height, + int srcX, int srcY, RastOpts *ropts); +static NSVGcache * GetCachePtr(Tcl_Interp *interp); +static int CacheSVG(Tcl_Interp *interp, ClientData dataOrChan, + Tcl_Obj *formatObj, NSVGimage *nsvgImage, + RastOpts *ropts); +static NSVGimage * GetCachedSVG(Tcl_Interp *interp, ClientData dataOrChan, + Tcl_Obj *formatObj, RastOpts *ropts); +static void CleanCache(Tcl_Interp *interp); +static void FreeCache(ClientData clientData, Tcl_Interp *interp); + +/* + * The format record for the SVG nano file format: + */ + +Tk_PhotoImageFormat tkImgFmtSVGnano = { + "svg", /* name */ + FileMatchSVG, /* fileMatchProc */ + StringMatchSVG, /* stringMatchProc */ + FileReadSVG, /* fileReadProc */ + StringReadSVG, /* stringReadProc */ + NULL, /* fileWriteProc */ + NULL, /* stringWriteProc */ + NULL +}; + +/* + *---------------------------------------------------------------------- + * + * FileMatchSVG -- + * + * This function is invoked by the photo image type to see if a file + * contains image data in SVG format. + * + * Results: + * The return value is >0 if the file can be successfully parsed, + * and 0 otherwise. + * + * Side effects: + * The file is saved in the internal cache for further use. + * + *---------------------------------------------------------------------- + */ + +static int +FileMatchSVG( + Tcl_Channel chan, + const char *fileName, + Tcl_Obj *formatObj, + int *widthPtr, int *heightPtr, + Tcl_Interp *interp) +{ + TkSizeT length; + Tcl_Obj *dataObj = Tcl_NewObj(); + const char *data; + RastOpts ropts; + NSVGimage *nsvgImage; + + CleanCache(interp); + if (Tcl_ReadChars(chan, dataObj, -1, 0) == TCL_IO_FAILURE) { + /* in case of an error reading the file */ + Tcl_DecrRefCount(dataObj); + return 0; + } + data = TkGetStringFromObj(dataObj, &length); + nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, &ropts); + Tcl_DecrRefCount(dataObj); + if (nsvgImage != NULL) { + *widthPtr = (int) ceil(nsvgImage->width * ropts.scale); + *heightPtr = (int) ceil(nsvgImage->height * ropts.scale); + if ((*widthPtr <= 0) || (*heightPtr <= 0)) { + nsvgDelete(nsvgImage); + return 0; + } + if (!CacheSVG(interp, chan, formatObj, nsvgImage, &ropts)) { + nsvgDelete(nsvgImage); + } + return 1; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * FileReadSVG -- + * + * This function is called by the photo image type to read SVG format + * data from a file and write it into a given photo image. + * + * Results: + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. + * + * Side effects: + * The access position in file f is changed, and new data is added to the + * image given by imageHandle. + * + *---------------------------------------------------------------------- + */ + +static int +FileReadSVG( + Tcl_Interp *interp, + Tcl_Channel chan, + const char *fileName, + Tcl_Obj *formatObj, + Tk_PhotoHandle imageHandle, + int destX, int destY, + int width, int height, + int srcX, int srcY) +{ + TkSizeT length; + const char *data; + RastOpts ropts; + NSVGimage *nsvgImage = GetCachedSVG(interp, chan, formatObj, &ropts); + + if (nsvgImage == NULL) { + Tcl_Obj *dataObj = Tcl_NewObj(); + + if (Tcl_ReadChars(chan, dataObj, -1, 0) == TCL_IO_FAILURE) { + /* in case of an error reading the file */ + Tcl_DecrRefCount(dataObj); + Tcl_SetObjResult(interp, Tcl_NewStringObj("read error", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "READ_ERROR", NULL); + return TCL_ERROR; + } + data = TkGetStringFromObj(dataObj, &length); + nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, + &ropts); + Tcl_DecrRefCount(dataObj); + if (nsvgImage == NULL) { + return TCL_ERROR; + } + } + return RasterizeSVG(interp, imageHandle, nsvgImage, destX, destY, + width, height, srcX, srcY, &ropts); +} + +/* + *---------------------------------------------------------------------- + * + * StringMatchSVG -- + * + * This function is invoked by the photo image type to see if a string + * contains image data in SVG format. + * + * Results: + * The return value is >0 if the file can be successfully parsed, + * and 0 otherwise. + * + * Side effects: + * The file is saved in the internal cache for further use. + * + *---------------------------------------------------------------------- + */ + +static int +StringMatchSVG( + Tcl_Obj *dataObj, + Tcl_Obj *formatObj, + int *widthPtr, int *heightPtr, + Tcl_Interp *interp) +{ + TkSizeT length; + const char *data; + RastOpts ropts; + NSVGimage *nsvgImage; + + CleanCache(interp); + data = TkGetStringFromObj(dataObj, &length); + nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, &ropts); + if (nsvgImage != NULL) { + *widthPtr = (int) ceil(nsvgImage->width * ropts.scale); + *heightPtr = (int) ceil(nsvgImage->height * ropts.scale); + if ((*widthPtr <= 0) || (*heightPtr <= 0)) { + nsvgDelete(nsvgImage); + return 0; + } + if (!CacheSVG(interp, dataObj, formatObj, nsvgImage, &ropts)) { + nsvgDelete(nsvgImage); + } + return 1; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * StringReadSVG -- + * + * This function is called by the photo image type to read SVG format + * data from a string and write it into a given photo image. + * + * Results: + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. + * + * Side effects: + * New data is added to the image given by imageHandle. + * + *---------------------------------------------------------------------- + */ + +static int +StringReadSVG( + Tcl_Interp *interp, + Tcl_Obj *dataObj, + Tcl_Obj *formatObj, + Tk_PhotoHandle imageHandle, + int destX, int destY, + int width, int height, + int srcX, int srcY) +{ + TkSizeT length; + const char *data; + RastOpts ropts; + NSVGimage *nsvgImage = GetCachedSVG(interp, dataObj, formatObj, &ropts); + + if (nsvgImage == NULL) { + data = TkGetStringFromObj(dataObj, &length); + nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, + &ropts); + } + if (nsvgImage == NULL) { + return TCL_ERROR; + } + return RasterizeSVG(interp, imageHandle, nsvgImage, destX, destY, + width, height, srcX, srcY, &ropts); +} + +/* + *---------------------------------------------------------------------- + * + * ParseSVGWithOptions -- + * + * This function is called to parse the given input string as SVG. + * + * Results: + * Return a newly create NSVGimage on success, and NULL otherwise. + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +static NSVGimage * +ParseSVGWithOptions( + Tcl_Interp *interp, + const char *input, + TkSizeT length, + Tcl_Obj *formatObj, + RastOpts *ropts) +{ + Tcl_Obj **objv = NULL; + int objc = 0; + double dpi = 96.0; + char unit[3], *p; + char *inputCopy = NULL; + NSVGimage *nsvgImage; + static const char *const fmtOptions[] = { + "-dpi", "-scale", "-unit", NULL + }; + enum fmtOptions { + OPT_DPI, OPT_SCALE, OPT_UNIT + }; + + /* + * The parser destroys the original input string, + * therefore first duplicate. + */ + + inputCopy = attemptckalloc(length+1); + if (inputCopy == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot alloc data buffer", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "OUT_OF_MEMORY", NULL); + goto error; + } + memcpy(inputCopy, input, length); + inputCopy[length] = '\0'; + + /* + * Process elements of format specification as a list. + */ + + strcpy(unit, "px"); + ropts->x = ropts->y = 0.0; + ropts->scale = 1.0; + if ((formatObj != NULL) && + Tcl_ListObjGetElements(interp, formatObj, &objc, &objv) != TCL_OK) { + goto error; + } + for (; objc > 0 ; objc--, objv++) { + int optIndex; + + /* + * Ignore the "svg" part of the format specification. + */ + + if (!strcasecmp(Tcl_GetString(objv[0]), "svg")) { + continue; + } + + if (Tcl_GetIndexFromObjStruct(interp, objv[0], fmtOptions, + sizeof(char *), "option", 0, &optIndex) == TCL_ERROR) { + goto error; + } + + if (objc < 2) { + ckfree(inputCopy); + inputCopy = NULL; + Tcl_WrongNumArgs(interp, 1, objv, "value"); + goto error; + } + + objc--; + objv++; + + switch ((enum fmtOptions) optIndex) { + case OPT_DPI: + if (Tcl_GetDoubleFromObj(interp, objv[0], &dpi) == TCL_ERROR) { + goto error; + } + if (dpi < 0.0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "-dpi value must be positive", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_DPI", + NULL); + goto error; + } + break; + case OPT_SCALE: + if (Tcl_GetDoubleFromObj(interp, objv[0], &ropts->scale) == + TCL_ERROR) { + goto error; + } + if (ropts->scale <= 0.0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "-scale value must be positive", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_SCALE", + NULL); + goto error; + } + break; + case OPT_UNIT: + p = Tcl_GetString(objv[0]); + if ((p != NULL) && (p[0])) { + strncpy(unit, p, 3); + unit[2] = '\0'; + } + break; + } + } + + nsvgImage = nsvgParse(inputCopy, unit, (float) dpi); + if (nsvgImage == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot parse SVG image", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "PARSE_ERROR", NULL); + goto error; + } + ckfree(inputCopy); + return nsvgImage; + +error: + if (inputCopy != NULL) { + ckfree(inputCopy); + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * RasterizeSVG -- + * + * This function is called to rasterize the given nsvgImage and + * fill the imageHandle with data. + * + * Results: + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. + * + * + * Side effects: + * On error the given nsvgImage will be deleted. + * + *---------------------------------------------------------------------- + */ + +static int +RasterizeSVG( + Tcl_Interp *interp, + Tk_PhotoHandle imageHandle, + NSVGimage *nsvgImage, + int destX, int destY, + int width, int height, + int srcX, int srcY, + RastOpts *ropts) +{ + int w, h, c; + NSVGrasterizer *rast; + unsigned char *imgData; + Tk_PhotoImageBlock svgblock; + + w = (int) ceil(nsvgImage->width * ropts->scale); + h = (int) ceil(nsvgImage->height * ropts->scale); + rast = nsvgCreateRasterizer(); + if (rast == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot initialize rasterizer", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "RASTERIZER_ERROR", + NULL); + goto cleanAST; + } + imgData = attemptckalloc(w * h *4); + if (imgData == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot alloc image buffer", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "OUT_OF_MEMORY", NULL); + goto cleanRAST; + } + nsvgRasterize(rast, nsvgImage, (float) ropts->x, (float) ropts->y, + (float) ropts->scale, imgData, w, h, w * 4); + /* transfer the data to a photo block */ + svgblock.pixelPtr = imgData; + svgblock.width = w; + svgblock.height = h; + svgblock.pitch = w * 4; + svgblock.pixelSize = 4; + for (c = 0; c <= 3; c++) { + svgblock.offset[c] = c; + } + if (Tk_PhotoExpand(interp, imageHandle, + destX + width, destY + height) != TCL_OK) { + goto cleanRAST; + } + if (Tk_PhotoPutBlock(interp, imageHandle, &svgblock, destX, destY, + width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) { + goto cleanimg; + } + ckfree(imgData); + nsvgDeleteRasterizer(rast); + nsvgDelete(nsvgImage); + return TCL_OK; + +cleanimg: + ckfree(imgData); + +cleanRAST: + nsvgDeleteRasterizer(rast); + +cleanAST: + nsvgDelete(nsvgImage); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * GetCachePtr -- + * + * This function is called to get the per interpreter used + * svg image cache. + * + * Results: + * Return a pointer to the used cache. + * + * Side effects: + * Initialize the cache on the first call. + * + *---------------------------------------------------------------------- + */ + +static NSVGcache * +GetCachePtr( + Tcl_Interp *interp +) { + NSVGcache *cachePtr = Tcl_GetAssocData(interp, "tksvgnano", NULL); + if (cachePtr == NULL) { + cachePtr = ckalloc(sizeof(NSVGcache)); + cachePtr->dataOrChan = NULL; + Tcl_DStringInit(&cachePtr->formatString); + cachePtr->nsvgImage = NULL; + Tcl_SetAssocData(interp, "tksvgnano", FreeCache, cachePtr); + } + return cachePtr; +} + +/* + *---------------------------------------------------------------------- + * + * CacheSVG -- + * + * Add the given svg image informations to the cache for further usage. + * + * Results: + * Return 1 on success, and 0 otherwise. + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +static int +CacheSVG( + Tcl_Interp *interp, + ClientData dataOrChan, + Tcl_Obj *formatObj, + NSVGimage *nsvgImage, + RastOpts *ropts) +{ + TkSizeT length; + const char *data; + NSVGcache *cachePtr = GetCachePtr(interp); + + if (cachePtr != NULL) { + cachePtr->dataOrChan = dataOrChan; + if (formatObj != NULL) { + data = TkGetStringFromObj(formatObj, &length); + Tcl_DStringAppend(&cachePtr->formatString, data, length); + } + cachePtr->nsvgImage = nsvgImage; + cachePtr->ropts = *ropts; + return 1; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * GetCachedSVG -- + * + * Try to get the NSVGimage from the internal cache. + * + * Results: + * Return the found NSVGimage on success, and NULL otherwise. + * + * Side effects: + * Calls the CleanCache() function. + * + *---------------------------------------------------------------------- + */ + +static NSVGimage * +GetCachedSVG( + Tcl_Interp *interp, + ClientData dataOrChan, + Tcl_Obj *formatObj, + RastOpts *ropts) +{ + TkSizeT length; + const char *data; + NSVGcache *cachePtr = GetCachePtr(interp); + NSVGimage *nsvgImage = NULL; + + if ((cachePtr != NULL) && (cachePtr->nsvgImage != NULL) && + (cachePtr->dataOrChan == dataOrChan)) { + if (formatObj != NULL) { + data = TkGetStringFromObj(formatObj, &length); + if (strcmp(data, Tcl_DStringValue(&cachePtr->formatString)) == 0) { + nsvgImage = cachePtr->nsvgImage; + *ropts = cachePtr->ropts; + cachePtr->nsvgImage = NULL; + } + } else if (Tcl_DStringLength(&cachePtr->formatString) == 0) { + nsvgImage = cachePtr->nsvgImage; + *ropts = cachePtr->ropts; + cachePtr->nsvgImage = NULL; + } + } + CleanCache(interp); + return nsvgImage; +} + +/* + *---------------------------------------------------------------------- + * + * CleanCache -- + * + * Reset the cache and delete the saved image in it. + * + * Results: + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +static void +CleanCache(Tcl_Interp *interp) +{ + NSVGcache *cachePtr = GetCachePtr(interp); + + if (cachePtr != NULL) { + cachePtr->dataOrChan = NULL; + Tcl_DStringSetLength(&cachePtr->formatString, 0); + if (cachePtr->nsvgImage != NULL) { + nsvgDelete(cachePtr->nsvgImage); + cachePtr->nsvgImage = NULL; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * FreeCache -- + * + * This function is called to clean up the internal cache data. + * + * Results: + * + * Side effects: + * Existing image data in the cache and the cache will be deleted. + * + *---------------------------------------------------------------------- + */ + +static void +FreeCache(ClientData clientData, Tcl_Interp *interp) +{ + NSVGcache *cachePtr = clientData; + + Tcl_DStringFree(&cachePtr->formatString); + if (cachePtr->nsvgImage != NULL) { + nsvgDelete(cachePtr->nsvgImage); + } + ckfree(cachePtr); +} + Index: generic/tkInt.decls ================================================================== --- generic/tkInt.decls +++ generic/tkInt.decls @@ -97,11 +97,11 @@ declare 21 { int TkFindStateNum(Tcl_Interp *interp, const char *option, const TkStateMap *mapPtr, const char *strKey) } declare 22 { - CONST86 char *TkFindStateString(const TkStateMap *mapPtr, int numKey) + const char *TkFindStateString(const TkStateMap *mapPtr, int numKey) } declare 23 { void TkFocusDeadWindow(TkWindow *winPtr) } declare 24 { @@ -180,11 +180,11 @@ } declare 45 { void TkInstallFrameMenu(Tk_Window tkwin) } declare 46 { - CONST86 char *TkKeysymToString(KeySym keysym) + const char *TkKeysymToString(KeySym keysym) } declare 47 { int TkLineToArea(double end1Ptr[], double end2Ptr[], double rectPtr[]) } declare 48 { @@ -387,11 +387,11 @@ declare 108 { int TkGetWindowFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr) } declare 109 { - CONST86 char *TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr) + const char *TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr) } declare 110 { void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont) } declare 111 { @@ -568,51 +568,51 @@ declare 169 { int TkStateParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 170 { - CONST86 char *TkStatePrintProc(ClientData clientData, Tk_Window tkwin, + const char *TkStatePrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } declare 171 { int TkCanvasDashParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 172 { - CONST86 char *TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin, + const char *TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } declare 173 { int TkOffsetParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 174 { - CONST86 char *TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin, + const char *TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } declare 175 { int TkPixelParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 176 { - CONST86 char *TkPixelPrintProc(ClientData clientData, Tk_Window tkwin, + const char *TkPixelPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } declare 177 { int TkOrientParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 178 { - CONST86 char *TkOrientPrintProc(ClientData clientData, Tk_Window tkwin, + const char *TkOrientPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } declare 179 { int TkSmoothParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset) } declare 180 { - CONST86 char *TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin, + const char *TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) } # Angled text API, exposed for Emiliano Gavilán's RBC work. declare 181 { @@ -632,10 +632,17 @@ declare 184 { void TkDrawAngledChars(Display *display,Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, double x, double y, double angle) } + +# Debugging / testing functions for photo images +declare 185 { + int TkDebugPhotoStringMatchDef(Tcl_Interp *inter, Tcl_Obj *data, + Tcl_Obj *formatString, int *widthPtr, int *heightPtr) +} + ############################################################################## # Define the platform specific internal Tcl interface. These functions are # only available on the designated platform. @@ -1007,11 +1014,11 @@ } declare 47 aqua { Tk_Window TkMacOSXGetCapture(void) } declare 49 aqua { - Window TkGetTransientMaster(TkWindow *winPtr) + Tk_Window TkGetTransientMaster(TkWindow *winPtr) } declare 50 aqua { int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state) } declare 51 aqua { @@ -1491,10 +1498,16 @@ declare 137 win { int XPutImage(Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h) } +declare 138 win { + Region XPolygonRegion(XPoint *pts, int n, int rule) +} +declare 139 win { + int XPointInRegion(Region rgn, int x, int y) +} ################################ # X functions for Aqua declare 0 aqua { Index: generic/tkInt.h ================================================================== --- generic/tkInt.h +++ generic/tkInt.h @@ -23,11 +23,10 @@ * Ensure WORDS_BIGENDIAN is defined correctly: * Needs to happen here in addition to configure to work with fat compiles on * Darwin (where configure runs only once for multiple architectures). */ -#include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_PARAM_H # include @@ -57,34 +56,56 @@ # else # define MODULE_SCOPE extern # endif #endif +#ifndef TkSizeT +# if TCL_MAJOR_VERSION > 8 +# define TkSizeT size_t +# else +# define TkSizeT int +# endif +#endif + /* * Macros used to cast between pointers and integers (e.g. when storing an int * in ClientData), on 64-bit architectures they avoid gcc warning about "cast * to/from pointer from/to integer of different size". */ #if !defined(INT2PTR) && !defined(PTR2INT) # if defined(HAVE_INTPTR_T) || defined(intptr_t) # define INT2PTR(p) ((void*)(intptr_t)(p)) -# define PTR2INT(p) ((int)(intptr_t)(p)) +# define PTR2INT(p) ((intptr_t)(p)) # else # define INT2PTR(p) ((void*)(p)) -# define PTR2INT(p) ((int)(p)) +# define PTR2INT(p) ((long)(p)) # endif #endif #if !defined(UINT2PTR) && !defined(PTR2UINT) # if defined(HAVE_UINTPTR_T) || defined(uintptr_t) # define UINT2PTR(p) ((void*)(uintptr_t)(p)) -# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) +# define PTR2UINT(p) ((uintptr_t)(p)) # else # define UINT2PTR(p) ((void*)(p)) -# define PTR2UINT(p) ((unsigned int)(p)) +# define PTR2UINT(p) ((unsigned long)(p)) +# endif +#endif + +#ifndef TCL_AUTO_LENGTH +# define TCL_AUTO_LENGTH (-1) +#endif + +#ifndef TCL_Z_MODIFIER +# if defined(_WIN64) +# define TCL_Z_MODIFIER "I" +# elif defined(__GNUC__) && !defined(_WIN32) +# define TCL_Z_MODIFIER "z" +# else +# define TCL_Z_MODIFIER "" # endif -#endif +#endif /* !TCL_Z_MODIFIER */ /* * Opaque type declarations: */ @@ -105,20 +126,20 @@ typedef struct TkCursor { Tk_Cursor cursor; /* System specific identifier for cursor. */ Display *display; /* Display containing cursor. Needed for * disposal and retrieval of cursors. */ - int resourceRefCount; /* Number of active uses of this cursor (each + TkSizeT resourceRefCount; /* Number of active uses of this cursor (each * active use corresponds to a call to * Tk_AllocPreserveFromObj or Tk_Preserve). If * this count is 0, then this structure is no * longer valid and it isn't present in a hash * table: it is being kept around only because * there are objects referring to it. The * structure is freed when resourceRefCount * and objRefCount are both 0. */ - int objRefCount; /* Number of Tcl objects that reference this + TkSizeT objRefCount; /* Number of Tcl objects that reference this * structure.. */ Tcl_HashTable *otherTable; /* Second table (other than idTable) used to * index this entry. */ Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure * (needed when deleting). */ @@ -264,11 +285,11 @@ struct TkErrorHandler *errorPtr; /* First in list of error handlers for this * display. NULL means no handlers exist at * present. */ - int deleteCount; /* Counts # of handlers deleted since last + TkSizeT deleteCount; /* Counts # of handlers deleted since last * time inactive handlers were garbage- * collected. When this number gets big, * handlers get cleaned up. */ /* @@ -320,10 +341,13 @@ Tcl_HashTable maintainHashTable; /* Hash table that maps from a master's * Tk_Window token to a list of slaves managed * by that master. */ int geomInit; + +#define TkGetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ + ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr) /* * Information used by tkGet.c only: */ @@ -477,23 +501,30 @@ XIMStyle inputStyle; /* Input style selected for this display. */ XFontSet inputXfs; /* XFontSet cached for over-the-spot XIM. */ #endif /* TK_USE_INPUT_METHODS */ Tcl_HashTable winTable; /* Maps from X window ids to TkWindow ptrs. */ - int refCount; /* Reference count of how many Tk applications + TkSizeT refCount; /* Reference count of how many Tk applications * are using this display. Used to clean up * the display when we no longer have any Tk * applications using it. */ /* * The following field were all added for Tk8.3 */ +#if TCL_MAJOR_VERSION < 9 +#if !defined(TK_NO_DEPRECATED) int mouseButtonState; /* Current mouse button state for this - * display. */ + * display. NOT USED as of 8.6.10 */ Window mouseButtonWindow; /* Window the button state was set in, added * in Tk 8.4. */ +#else + int notused1; + XID notused2; +#endif /* !TK_NO_DEPRECATED */ +#endif Tk_Window warpWindow; Tk_Window warpMainwin; /* For finding the root window for warping * purposes. */ int warpX; int warpY; @@ -581,11 +612,11 @@ * by a call to TkCreateMainWindow). It stores information that is shared by * all of the windows associated with a particular main window. */ typedef struct TkMainInfo { - int refCount; /* Number of windows whose "mainPtr" fields + TkSizeT refCount; /* Number of windows whose "mainPtr" fields * point here. When this becomes zero, can * free up the structure (the reference count * is zero because windows can get deleted in * almost any order; the main window isn't * necessarily the last one deleted). */ @@ -592,11 +623,15 @@ struct TkWindow *winPtr; /* Pointer to main window. */ Tcl_Interp *interp; /* Interpreter associated with application. */ Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow * structs for all windows related to this * main window. Managed by tkWindow.c. */ - long deletionEpoch; /* Incremented by window deletions. */ +#if TCL_MAJOR_VERSION > 8 + size_t deletionEpoch; /* Incremented by window deletions. */ +#else + long deletionEpoch; +#endif Tk_BindingTable bindingTable; /* Used in conjunction with "bind" command to * bind events to Tcl commands. */ TkBindInfo bindInfo; /* Information used by tkBind.c on a per * application basis. */ @@ -810,29 +845,33 @@ int internalBorderTop; int internalBorderBottom; int minReqWidth; /* Minimum requested width. */ int minReqHeight; /* Minimum requested height. */ - char *geometryMaster; #ifdef TK_USE_INPUT_METHODS int ximGeneration; /* Used to invalidate XIC */ #endif /* TK_USE_INPUT_METHODS */ + char *geomMgrName; /* Records the name of the geometry manager. */ + struct TkWindow *maintainerPtr; + /* The geometry master for this window. The + * value is NULL if the window has no master or + * if its master is its parent. */ } TkWindow; /* * Real definition of some events. Note that these events come from outside * but have internally generated pieces added to them. */ typedef struct { - XKeyEvent keyEvent; /* The real event from X11. */ - char *charValuePtr; /* A pointer to a string that holds the key's + XKeyEvent keyEvent; /* The real event from X11. */ + char *charValuePtr; /* A pointer to a string that holds the key's * %A substitution text (before backslash * adding), or NULL if that has not been * computed yet. If non-NULL, this string was * allocated with ckalloc(). */ - int charValueLen; /* Length of string in charValuePtr when that + TkSizeT charValueLen; /* Length of string in charValuePtr when that * is non-NULL. */ KeySym keysym; /* Key symbol computed after input methods * have been invoked */ } TkKeyEvent; @@ -841,10 +880,19 @@ */ #define TK_MAKE_MENU_TEAROFF 0 /* Only non-transient case. */ #define TK_MAKE_MENU_POPUP 1 #define TK_MAKE_MENU_DROPDOWN 2 + +/* See TIP #494 */ +#ifndef TCL_IO_FAILURE +# define TCL_IO_FAILURE (-1) +#endif +/* See TIP #537 */ +#ifndef TCL_INDEX_NONE +# define TCL_INDEX_NONE (-1) +#endif /* * The following structure is used with TkMakeEnsemble to create ensemble * commands and optionally to create sub-ensembles. */ @@ -922,10 +970,42 @@ #define META_MASK (AnyModifier<<1) #define ALT_MASK (AnyModifier<<2) #define EXTENDED_MASK (AnyModifier<<3) +#ifndef Button8 +# define Button8 8 +#endif +#ifndef Button9 +# define Button9 9 +#endif + +#ifndef Button6Mask +# define Button6Mask (1<<13) +#endif +#ifndef Button7Mask +# define Button7Mask (1<<14) +#endif +#ifndef Button8Mask +# define Button8Mask (AnyModifier<<4) +#endif +#ifndef Button9Mask +# define Button9Mask (AnyModifier<<5) +#endif + +/* + * Mask that selects any of the state bits corresponding to buttons, plus + * masks that select individual buttons' bits: + */ + +#define ALL_BUTTONS \ + (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask \ + |Button6Mask|Button7Mask|Button8Mask|Button9Mask) + + +MODULE_SCOPE unsigned long TkGetButtonMask(unsigned int); + /* * Object types not declared in tkObj.c need to be mentioned here so they can * be properly registered with Tcl: */ @@ -944,12 +1024,14 @@ MODULE_SCOPE const Tk_SmoothMethod tkBezierSmoothMethod; MODULE_SCOPE Tk_ImageType tkBitmapImageType; MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtGIF; MODULE_SCOPE void (*tkHandleEventProc) (XEvent* eventPtr); +MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtDefault; MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPNG; MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPPM; +MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtSVGnano; MODULE_SCOPE TkMainInfo *tkMainWindowList; MODULE_SCOPE Tk_ImageType tkPhotoImageType; MODULE_SCOPE Tcl_HashTable tkPredefBitmapTable; MODULE_SCOPE const char *const tkWebColors[20]; @@ -975,11 +1057,10 @@ #if __has_feature(attribute_analyzer_noreturn) && \ !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED) void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn)); #endif #if !defined(CLANG_ASSERT) -#include #define CLANG_ASSERT(x) assert(x) #endif #elif !defined(CLANG_ASSERT) #define CLANG_ASSERT(x) #endif /* PURIFY && __clang__ */ @@ -1202,10 +1283,13 @@ Drawable drawable, GC gc, Tk_Font tkfont, const char *string, int numBytes, int x, int y, int firstByte, int lastByte); MODULE_SCOPE void TkpGetFontAttrsForChar(Tk_Window tkwin, Tk_Font tkfont, int c, struct TkFontAttributes *faPtr); +MODULE_SCOPE void TkpDrawFrameEx(Tk_Window tkwin, Drawable drawable, + Tk_3DBorder border, int highlightWidth, + int borderWidth, int relief); MODULE_SCOPE Tcl_Obj * TkNewWindowObj(Tk_Window tkwin); MODULE_SCOPE void TkpShowBusyWindow(TkBusy busy); MODULE_SCOPE void TkpHideBusyWindow(TkBusy busy); MODULE_SCOPE void TkpMakeTransparentWindowExist(Tk_Window tkwin, Window parent); @@ -1221,15 +1305,20 @@ ClientData clientData, const TkEnsemble *map); MODULE_SCOPE int TkInitTkCmd(Tcl_Interp *interp, ClientData clientData); MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp, ClientData clientData); +MODULE_SCOPE void TkInitEmbeddedConfigurationInformation( + Tcl_Interp *interp); MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr); MODULE_SCOPE void TkpCancelWarp(TkDisplay *dispPtr); MODULE_SCOPE int TkListCreateFrame(ClientData clientData, Tcl_Interp *interp, Tcl_Obj *listObj, int toplevel, Tcl_Obj *nameObj); +MODULE_SCOPE void TkRotatePoint(double originX, double originY, + double sine, double cosine, double *xPtr, + double *yPtr); #ifdef _WIN32 #define TkParseColor XParseColor #else MODULE_SCOPE Status TkParseColor (Display * display, @@ -1239,16 +1328,28 @@ #ifdef HAVE_XFT MODULE_SCOPE void TkUnixSetXftClipRegion(TkRegion clipRegion); #endif #if TCL_UTF_MAX > 4 -# define TkUtfToUniChar Tcl_UtfToUniChar -# define TkUniCharToUtf Tcl_UniCharToUtf +# define TkUtfToUniChar (size_t)Tcl_UtfToUniChar +# define TkUniCharToUtf (size_t)Tcl_UniCharToUtf +#else + MODULE_SCOPE size_t TkUtfToUniChar(const char *, int *); + MODULE_SCOPE size_t TkUniCharToUtf(int, char *); +#endif + +#if TCL_MAJOR_VERSION > 8 +#define TkGetStringFromObj(objPtr, lenPtr) \ + (((objPtr)->bytes ? 0 : Tcl_GetString(objPtr)), \ + *(lenPtr) = (objPtr)->length, (objPtr)->bytes) +MODULE_SCOPE unsigned char *TkGetByteArrayFromObj(Tcl_Obj *objPtr, + size_t *lengthPtr); #else - MODULE_SCOPE int TkUtfToUniChar(const char *, int *); - MODULE_SCOPE int TkUniCharToUtf(int, char *); +#define TkGetStringFromObj Tcl_GetStringFromObj +#define TkGetByteArrayFromObj Tcl_GetByteArrayFromObj #endif + /* * Unsupported commands. */ Index: generic/tkIntDecls.h ================================================================== --- generic/tkIntDecls.h +++ generic/tkIntDecls.h @@ -102,11 +102,11 @@ /* 21 */ EXTERN int TkFindStateNum(Tcl_Interp *interp, const char *option, const TkStateMap *mapPtr, const char *strKey); /* 22 */ -EXTERN CONST86 char * TkFindStateString(const TkStateMap *mapPtr, +EXTERN const char * TkFindStateString(const TkStateMap *mapPtr, int numKey); /* 23 */ EXTERN void TkFocusDeadWindow(TkWindow *winPtr); /* 24 */ EXTERN int TkFocusFilterEvent(TkWindow *winPtr, @@ -165,11 +165,11 @@ TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position); /* 45 */ EXTERN void TkInstallFrameMenu(Tk_Window tkwin); /* 46 */ -EXTERN CONST86 char * TkKeysymToString(KeySym keysym); +EXTERN const char * TkKeysymToString(KeySym keysym); /* 47 */ EXTERN int TkLineToArea(double end1Ptr[], double end2Ptr[], double rectPtr[]); /* 48 */ EXTERN double TkLineToPoint(double end1Ptr[], double end2Ptr[], @@ -322,11 +322,11 @@ /* 108 */ EXTERN int TkGetWindowFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr); /* 109 */ -EXTERN CONST86 char * TkpGetString(TkWindow *winPtr, XEvent *eventPtr, +EXTERN const char * TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 110 */ EXTERN void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont); /* 111 */ EXTERN Tcl_Obj * TkpGetSystemDefault(Tk_Window tkwin, @@ -486,51 +486,51 @@ /* 169 */ EXTERN int TkStateParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 170 */ -EXTERN CONST86 char * TkStatePrintProc(ClientData clientData, +EXTERN const char * TkStatePrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 171 */ EXTERN int TkCanvasDashParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 172 */ -EXTERN CONST86 char * TkCanvasDashPrintProc(ClientData clientData, +EXTERN const char * TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 173 */ EXTERN int TkOffsetParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 174 */ -EXTERN CONST86 char * TkOffsetPrintProc(ClientData clientData, +EXTERN const char * TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 175 */ EXTERN int TkPixelParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 176 */ -EXTERN CONST86 char * TkPixelPrintProc(ClientData clientData, +EXTERN const char * TkPixelPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 177 */ EXTERN int TkOrientParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 178 */ -EXTERN CONST86 char * TkOrientPrintProc(ClientData clientData, +EXTERN const char * TkOrientPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 179 */ EXTERN int TkSmoothParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 180 */ -EXTERN CONST86 char * TkSmoothPrintProc(ClientData clientData, +EXTERN const char * TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 181 */ EXTERN void TkDrawAngledTextLayout(Display *display, Drawable drawable, GC gc, @@ -548,10 +548,14 @@ /* 184 */ EXTERN void TkDrawAngledChars(Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, double x, double y, double angle); +/* 185 */ +EXTERN int TkDebugPhotoStringMatchDef(Tcl_Interp *inter, + Tcl_Obj *data, Tcl_Obj *formatString, + int *widthPtr, int *heightPtr); typedef struct TkIntStubs { int magic; void *hooks; @@ -575,11 +579,11 @@ void (*tkDoConfigureNotify) (TkWindow *winPtr); /* 17 */ void (*tkDrawInsetFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding); /* 18 */ void (*tkEventDeadWindow) (TkWindow *winPtr); /* 19 */ void (*tkFillPolygon) (Tk_Canvas canvas, double *coordPtr, int numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC); /* 20 */ int (*tkFindStateNum) (Tcl_Interp *interp, const char *option, const TkStateMap *mapPtr, const char *strKey); /* 21 */ - CONST86 char * (*tkFindStateString) (const TkStateMap *mapPtr, int numKey); /* 22 */ + const char * (*tkFindStateString) (const TkStateMap *mapPtr, int numKey); /* 22 */ void (*tkFocusDeadWindow) (TkWindow *winPtr); /* 23 */ int (*tkFocusFilterEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 24 */ TkWindow * (*tkFocusKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 25 */ void (*tkFontPkgInit) (TkMainInfo *mainPtr); /* 26 */ void (*tkFontPkgFree) (TkMainInfo *mainPtr); /* 27 */ @@ -599,11 +603,11 @@ void (*tkGrabDeadWindow) (TkWindow *winPtr); /* 41 */ int (*tkGrabState) (TkWindow *winPtr); /* 42 */ void (*tkIncludePoint) (Tk_Item *itemPtr, double *pointPtr); /* 43 */ void (*tkInOutEvents) (XEvent *eventPtr, TkWindow *sourcePtr, TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position); /* 44 */ void (*tkInstallFrameMenu) (Tk_Window tkwin); /* 45 */ - CONST86 char * (*tkKeysymToString) (KeySym keysym); /* 46 */ + const char * (*tkKeysymToString) (KeySym keysym); /* 46 */ int (*tkLineToArea) (double end1Ptr[], double end2Ptr[], double rectPtr[]); /* 47 */ double (*tkLineToPoint) (double end1Ptr[], double end2Ptr[], double pointPtr[]); /* 48 */ int (*tkMakeBezierCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 49 */ void (*tkMakeBezierPostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 50 */ void (*tkOptionClassChanged) (TkWindow *winPtr); /* 51 */ @@ -662,11 +666,11 @@ int (*tkFindStateNumObj) (Tcl_Interp *interp, Tcl_Obj *optionPtr, const TkStateMap *mapPtr, Tcl_Obj *keyPtr); /* 104 */ Tcl_HashTable * (*tkGetBitmapPredefTable) (void); /* 105 */ TkDisplay * (*tkGetDisplayList) (void); /* 106 */ TkMainInfo * (*tkGetMainInfoList) (void); /* 107 */ int (*tkGetWindowFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr); /* 108 */ - CONST86 char * (*tkpGetString) (TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 109 */ + const char * (*tkpGetString) (TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 109 */ void (*tkpGetSubFonts) (Tcl_Interp *interp, Tk_Font tkfont); /* 110 */ Tcl_Obj * (*tkpGetSystemDefault) (Tk_Window tkwin, const char *dbName, const char *className); /* 111 */ void (*tkpMenuThreadInit) (void); /* 112 */ void (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */ TkRegion (*tkCreateRegion) (void); /* 114 */ @@ -750,25 +754,26 @@ int (*tkTextXviewCmd) (struct TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 165 */ void (*tkTextChanged) (struct TkSharedText *sharedTextPtr, struct TkText *textPtr, const struct TkTextIndex *index1Ptr, const struct TkTextIndex *index2Ptr); /* 166 */ int (*tkBTreeNumLines) (TkTextBTree tree, const struct TkText *textPtr); /* 167 */ void (*tkTextInsertDisplayProc) (struct TkText *textPtr, struct TkTextDispChunk *chunkPtr, int x, int y, int height, int baseline, Display *display, Drawable dst, int screenY); /* 168 */ int (*tkStateParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 169 */ - CONST86 char * (*tkStatePrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 170 */ + const char * (*tkStatePrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 170 */ int (*tkCanvasDashParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 171 */ - CONST86 char * (*tkCanvasDashPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 172 */ + const char * (*tkCanvasDashPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 172 */ int (*tkOffsetParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 173 */ - CONST86 char * (*tkOffsetPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 174 */ + const char * (*tkOffsetPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 174 */ int (*tkPixelParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 175 */ - CONST86 char * (*tkPixelPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 176 */ + const char * (*tkPixelPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 176 */ int (*tkOrientParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 177 */ - CONST86 char * (*tkOrientPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 178 */ + const char * (*tkOrientPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 178 */ int (*tkSmoothParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 179 */ - CONST86 char * (*tkSmoothPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 180 */ + const char * (*tkSmoothPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 180 */ void (*tkDrawAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int firstChar, int lastChar); /* 181 */ void (*tkUnderlineAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int underline); /* 182 */ int (*tkIntersectAngledTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height, double angle); /* 183 */ void (*tkDrawAngledChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, double x, double y, double angle); /* 184 */ + int (*tkDebugPhotoStringMatchDef) (Tcl_Interp *inter, Tcl_Obj *data, Tcl_Obj *formatString, int *widthPtr, int *heightPtr); /* 185 */ } TkIntStubs; extern const TkIntStubs *tkIntStubsPtr; #ifdef __cplusplus @@ -1137,10 +1142,12 @@ (tkIntStubsPtr->tkUnderlineAngledTextLayout) /* 182 */ #define TkIntersectAngledTextLayout \ (tkIntStubsPtr->tkIntersectAngledTextLayout) /* 183 */ #define TkDrawAngledChars \ (tkIntStubsPtr->tkDrawAngledChars) /* 184 */ +#define TkDebugPhotoStringMatchDef \ + (tkIntStubsPtr->tkDebugPhotoStringMatchDef) /* 185 */ #endif /* defined(USE_TK_STUBS) */ /* !END!: Do not edit above this line. */ Index: generic/tkIntPlatDecls.h ================================================================== --- generic/tkIntPlatDecls.h +++ generic/tkIntPlatDecls.h @@ -241,11 +241,11 @@ EXTERN int TkpIsWindowFloating(void *window); /* 47 */ EXTERN Tk_Window TkMacOSXGetCapture(void); /* Slot 48 is reserved */ /* 49 */ -EXTERN Window TkGetTransientMaster(TkWindow *winPtr); +EXTERN Tk_Window TkGetTransientMaster(TkWindow *winPtr); /* 50 */ EXTERN int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state); /* 51 */ EXTERN void TkGenWMDestroyEvent(Tk_Window tkwin); @@ -390,11 +390,11 @@ MacDrawable * (*tkMacOSXGetHostToplevel) (TkWindow *winPtr); /* 44 */ void (*tkMacOSXPreprocessMenu) (void); /* 45 */ int (*tkpIsWindowFloating) (void *window); /* 46 */ Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */ void (*reserved48)(void); - Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */ + Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */ int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */ void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */ void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */ unsigned long (*tkpGetMS) (void); /* 53 */ void * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */ @@ -662,6 +662,9 @@ /* !END!: Do not edit above this line. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT +#undef TkWinGetPlatformId +#define TkWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */ + #endif /* _TKINTPLATDECLS */ Index: generic/tkIntXlibDecls.h ================================================================== --- generic/tkIntXlibDecls.h +++ generic/tkIntXlibDecls.h @@ -20,10 +20,14 @@ */ #ifndef _TCL # include #endif + +#ifndef EXTERN +# define EXTERN extern TCL_STORAGE_CLASS +#endif /* Some (older) versions of X11/Xutil.h have a wrong signature of those two functions, so move them out of the way temporarly. */ #define XOffsetRegion _XOffsetRegion #define XUnionRegion _XUnionRegion @@ -30,12 +34,16 @@ #include "X11/Xutil.h" #undef XOffsetRegion #undef XUnionRegion #ifdef BUILD_tk -#undef TCL_STORAGE_CLASS -#define TCL_STORAGE_CLASS DLLEXPORT +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifndef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT +# endif #endif typedef int (*XAfterFunction) ( /* WARNING, this type not in Xlib spec */ Display* /* display */ ); @@ -411,10 +419,14 @@ int x, int y); /* 137 */ EXTERN int XPutImage(Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); +/* 138 */ +EXTERN Region XPolygonRegion(XPoint *pts, int n, int rule); +/* 139 */ +EXTERN int XPointInRegion(Region rgn, int x, int y); #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ /* 0 */ EXTERN int XSetDashes(Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); @@ -820,10 +832,12 @@ int (*xDrawSegments) (Display *d, Drawable dr, GC gc, XSegment *s, int n); /* 133 */ int (*xDrawPoint) (Display *d, Drawable dr, GC gc, int x, int y); /* 134 */ int (*xDrawPoints) (Display *d, Drawable dr, GC gc, XPoint *p, int n, int m); /* 135 */ int (*xReparentWindow) (Display *d, Window w, Window p, int x, int y); /* 136 */ int (*xPutImage) (Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); /* 137 */ + Region (*xPolygonRegion) (XPoint *pts, int n, int rule); /* 138 */ + int (*xPointInRegion) (Region rgn, int x, int y); /* 139 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ int (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */ XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */ XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */ @@ -1194,10 +1208,14 @@ (tkIntXlibStubsPtr->xDrawPoints) /* 135 */ #define XReparentWindow \ (tkIntXlibStubsPtr->xReparentWindow) /* 136 */ #define XPutImage \ (tkIntXlibStubsPtr->xPutImage) /* 137 */ +#define XPolygonRegion \ + (tkIntXlibStubsPtr->xPolygonRegion) /* 138 */ +#define XPointInRegion \ + (tkIntXlibStubsPtr->xPointInRegion) /* 139 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ #define XSetDashes \ (tkIntXlibStubsPtr->xSetDashes) /* 0 */ #define XGetModifierMapping \ Index: generic/tkListbox.c ================================================================== --- generic/tkListbox.c +++ generic/tkListbox.c @@ -10,12 +10,12 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" +#include "default.h" #ifdef _WIN32 #include "tkWinInt.h" #endif @@ -237,82 +237,82 @@ * listbox widget. */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING_TABLE, "-activestyle", "activeStyle", "ActiveStyle", - DEF_LISTBOX_ACTIVE_STYLE, -1, Tk_Offset(Listbox, activeStyle), + DEF_LISTBOX_ACTIVE_STYLE, -1, offsetof(Listbox, activeStyle), 0, activeStyleStrings, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_LISTBOX_BG_COLOR, -1, Tk_Offset(Listbox, normalBorder), + DEF_LISTBOX_BG_COLOR, -1, offsetof(Listbox, normalBorder), 0, DEF_LISTBOX_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_LISTBOX_BORDER_WIDTH, -1, Tk_Offset(Listbox, borderWidth), + DEF_LISTBOX_BORDER_WIDTH, -1, offsetof(Listbox, borderWidth), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_LISTBOX_CURSOR, -1, Tk_Offset(Listbox, cursor), + DEF_LISTBOX_CURSOR, -1, offsetof(Listbox, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_LISTBOX_DISABLED_FG, -1, - Tk_Offset(Listbox, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, + offsetof(Listbox, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, -1, - Tk_Offset(Listbox, exportSelection), 0, 0, 0}, + offsetof(Listbox, exportSelection), 0, 0, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_LISTBOX_FONT, -1, Tk_Offset(Listbox, tkfont), 0, 0, 0}, + DEF_LISTBOX_FONT, -1, offsetof(Listbox, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_LISTBOX_FG, -1, Tk_Offset(Listbox, fgColorPtr), 0, 0, 0}, + DEF_LISTBOX_FG, -1, offsetof(Listbox, fgColorPtr), 0, 0, 0}, {TK_OPTION_INT, "-height", "height", "Height", - DEF_LISTBOX_HEIGHT, -1, Tk_Offset(Listbox, height), 0, 0, 0}, + DEF_LISTBOX_HEIGHT, -1, offsetof(Listbox, height), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1, - Tk_Offset(Listbox, highlightBgColorPtr), 0, 0, 0}, + offsetof(Listbox, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(Listbox, highlightColorPtr), + DEF_LISTBOX_HIGHLIGHT, -1, offsetof(Listbox, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1, - Tk_Offset(Listbox, highlightWidth), 0, 0, 0}, + offsetof(Listbox, highlightWidth), 0, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_LISTBOX_JUSTIFY, -1, Tk_Offset(Listbox, justify), 0, 0, 0}, + DEF_LISTBOX_JUSTIFY, -1, offsetof(Listbox, justify), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0}, + DEF_LISTBOX_RELIEF, -1, offsetof(Listbox, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_LISTBOX_SELECT_COLOR, -1, Tk_Offset(Listbox, selBorder), + DEF_LISTBOX_SELECT_COLOR, -1, offsetof(Listbox, selBorder), 0, DEF_LISTBOX_SELECT_MONO, 0}, {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_LISTBOX_SELECT_BD, -1, - Tk_Offset(Listbox, selBorderWidth), 0, 0, 0}, + offsetof(Listbox, selBorderWidth), 0, 0, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_LISTBOX_SELECT_FG_COLOR, -1, Tk_Offset(Listbox, selFgColorPtr), + DEF_LISTBOX_SELECT_FG_COLOR, -1, offsetof(Listbox, selFgColorPtr), TK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0}, {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode", - DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(Listbox, selectMode), + DEF_LISTBOX_SELECT_MODE, -1, offsetof(Listbox, selectMode), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid", - DEF_LISTBOX_SET_GRID, -1, Tk_Offset(Listbox, setGrid), 0, 0, 0}, + DEF_LISTBOX_SET_GRID, -1, offsetof(Listbox, setGrid), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_LISTBOX_STATE, -1, Tk_Offset(Listbox, state), + DEF_LISTBOX_STATE, -1, offsetof(Listbox, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(Listbox, takeFocus), + DEF_LISTBOX_TAKE_FOCUS, -1, offsetof(Listbox, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-width", "width", "Width", - DEF_LISTBOX_WIDTH, -1, Tk_Offset(Listbox, width), 0, 0, 0}, + DEF_LISTBOX_WIDTH, -1, offsetof(Listbox, width), 0, 0, 0}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, xScrollCmd), + DEF_LISTBOX_SCROLL_COMMAND, -1, offsetof(Listbox, xScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, yScrollCmd), + DEF_LISTBOX_SCROLL_COMMAND, -1, offsetof(Listbox, yScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-listvariable", "listVariable", "Variable", - DEF_LISTBOX_LIST_VARIABLE, -1, Tk_Offset(Listbox, listVarName), + DEF_LISTBOX_LIST_VARIABLE, -1, offsetof(Listbox, listVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* @@ -320,26 +320,26 @@ * listbox items. */ static const Tk_OptionSpec itemAttrOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", - NULL, -1, Tk_Offset(ItemAttr, border), + NULL, -1, offsetof(ItemAttr, border), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, DEF_LISTBOX_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - NULL, -1, Tk_Offset(ItemAttr, fgColor), + NULL, -1, offsetof(ItemAttr, fgColor), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - NULL, -1, Tk_Offset(ItemAttr, selBorder), + NULL, -1, offsetof(ItemAttr, selBorder), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, DEF_LISTBOX_SELECT_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", - NULL, -1, Tk_Offset(ItemAttr, selFgColor), + NULL, -1, offsetof(ItemAttr, selFgColor), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, DEF_LISTBOX_SELECT_FG_MONO, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; @@ -565,11 +565,11 @@ Tk_CreateEventHandler(listPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, ListboxEventProc, listPtr); Tk_CreateSelHandler(listPtr->tkwin, XA_PRIMARY, XA_STRING, ListboxFetchSelection, listPtr, XA_STRING); - if (Tk_InitOptions(interp, (char *)listPtr, + if (Tk_InitOptions(interp, listPtr, optionTables->listboxOptionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(listPtr->tkwin); return TCL_ERROR; } @@ -680,11 +680,11 @@ Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; break; } - objPtr = Tk_GetOptionValue(interp, (char *) listPtr, + objPtr = Tk_GetOptionValue(interp, listPtr, listPtr->optionTable, objv[2], listPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; break; } @@ -692,11 +692,11 @@ result = TCL_OK; break; case COMMAND_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) listPtr, + objPtr = Tk_GetOptionInfo(interp, listPtr, listPtr->optionTable, (objc == 3) ? objv[2] : NULL, listPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; break; @@ -726,11 +726,11 @@ */ objPtr = Tcl_NewObj(); for (i = 0; i < listPtr->nElements; i++) { if (Tcl_FindHashEntry(listPtr->selection, KEY(i))) { - Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(i)); + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj(i)); } } Tcl_SetObjResult(interp, objPtr); result = TCL_OK; break; @@ -839,11 +839,11 @@ } result = GetListboxIndex(interp, listPtr, objv[2], 1, &index); if (result != TCL_OK) { break; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index)); result = TCL_OK; break; case COMMAND_INSERT: if (objc < 3) { @@ -924,11 +924,11 @@ break; } attrPtr = ListboxGetItemAttributes(interp, listPtr, index); if (objc <= 4) { - objPtr = Tk_GetOptionInfo(interp, (char *) attrPtr, + objPtr = Tk_GetOptionInfo(interp, attrPtr, listPtr->itemAttrOptionTable, (objc == 4) ? objv[3] : NULL, listPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; break; @@ -954,11 +954,11 @@ result = Tcl_GetIntFromObj(interp, objv[2], &y); if (result != TCL_OK) { break; } index = NearestListboxElement(listPtr, y); - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index)); result = TCL_OK; break; } case COMMAND_SCAN: { @@ -1042,11 +1042,11 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); result = TCL_ERROR; break; } - Tcl_SetObjResult(interp, Tcl_NewIntObj(listPtr->nElements)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(listPtr->nElements)); result = TCL_OK; break; case COMMAND_XVIEW: result = ListboxXviewSubCmd(interp, listPtr, objc, objv); break; @@ -1100,11 +1100,12 @@ */ if ((listPtr->topIndex <= index) && (index < lastVisibleIndex)) { Tcl_Obj *el, *results[4]; const char *stringRep; - int pixelWidth, stringLen, x, y, result; + int pixelWidth, x, y, result; + TkSizeT stringLen; Tk_FontMetrics fm; /* * Compute the pixel width of the requested element. */ @@ -1112,11 +1113,11 @@ result = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el); if (result != TCL_OK) { return result; } - stringRep = Tcl_GetStringFromObj(el, &stringLen); + stringRep = TkGetStringFromObj(el, &stringLen); Tk_GetFontMetrics(listPtr->tkfont, &fm); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); if (listPtr->justify == TK_JUSTIFY_LEFT) { x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset; @@ -1127,14 +1128,14 @@ x = (Tk_Width(tkwin) - pixelWidth)/2 - listPtr->xOffset + GetMaxOffset(listPtr)/2; } y = ((index - listPtr->topIndex)*listPtr->lineHeight) + listPtr->inset + listPtr->selBorderWidth; - results[0] = Tcl_NewIntObj(x); - results[1] = Tcl_NewIntObj(y); - results[2] = Tcl_NewIntObj(pixelWidth); - results[3] = Tcl_NewIntObj(fm.linespace); + results[0] = Tcl_NewWideIntObj(x); + results[1] = Tcl_NewWideIntObj(y); + results[2] = Tcl_NewWideIntObj(pixelWidth); + results[3] = Tcl_NewWideIntObj(fm.linespace); Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); } return TCL_OK; } @@ -1413,11 +1414,11 @@ attrs = ckalloc(sizeof(ItemAttr)); attrs->border = NULL; attrs->selBorder = NULL; attrs->fgColor = NULL; attrs->selFgColor = NULL; - Tk_InitOptions(interp, (char *)attrs, listPtr->itemAttrOptionTable, + Tk_InitOptions(interp, attrs, listPtr->itemAttrOptionTable, listPtr->tkwin); Tcl_SetHashValue(entry, attrs); } else { attrs = Tcl_GetHashValue(entry); } @@ -1576,11 +1577,11 @@ if (!error) { /* * First pass: set options to new values. */ - if (Tk_SetOptions(interp, (char *) listPtr, + if (Tk_SetOptions(interp, listPtr, listPtr->optionTable, objc, objv, listPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -1722,11 +1723,11 @@ Tcl_Obj *const objv[], /* Arguments. */ int index) /* Index of the listbox item being configure */ { Tk_SavedOptions savedOptions; - if (Tk_SetOptions(interp, (char *)attrs, + if (Tk_SetOptions(interp, attrs, listPtr->itemAttrOptionTable, objc, objv, listPtr->tkwin, &savedOptions, NULL) != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } @@ -1838,11 +1839,12 @@ ClientData clientData) /* Information about window. */ { register Listbox *listPtr = clientData; register Tk_Window tkwin = listPtr->tkwin; GC gc; - int i, limit, x, y, prevSelected, freeGC, stringLen; + int i, limit, x, y, prevSelected, freeGC; + TkSizeT stringLen; Tk_FontMetrics fm; Tcl_Obj *curElement; Tcl_HashEntry *entry; const char *stringRep; ItemAttr *attrs; @@ -2072,11 +2074,11 @@ /* * Draw the actual text of this item. */ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement); - stringRep = Tcl_GetStringFromObj(curElement, &stringLen); + stringRep = TkGetStringFromObj(curElement, &stringLen); textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); Tk_GetFontMetrics(listPtr->tkfont, &fm); y += fm.ascent + listPtr->selBorderWidth; @@ -2234,11 +2236,12 @@ * must be 1. */ int updateGrid) /* Non-zero means call Tk_SetGrid or * Tk_UnsetGrid to update gridding for the * window. */ { - int width, height, pixelWidth, pixelHeight, textLength, i, result; + int width, height, pixelWidth, pixelHeight, i, result; + TkSizeT textLength; Tk_FontMetrics fm; Tcl_Obj *element; const char *text; if (fontChanged || maxIsStale) { @@ -2255,11 +2258,11 @@ result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element); if (result != TCL_OK) { continue; } - text = Tcl_GetStringFromObj(element, &textLength); + text = TkGetStringFromObj(element, &textLength); Tk_GetFontMetrics(listPtr->tkfont, &fm); pixelWidth = Tk_TextWidth(listPtr->tkfont, text, textLength); if (pixelWidth > listPtr->maxWidth) { listPtr->maxWidth = pixelWidth; } @@ -2321,11 +2324,12 @@ int index, /* Add the new elements before this * element. */ int objc, /* Number of new elements to add. */ Tcl_Obj *const objv[]) /* New elements (one per entry). */ { - int i, oldMaxWidth, pixelWidth, result, length; + int i, oldMaxWidth, pixelWidth, result; + TkSizeT length; Tcl_Obj *newListObj; const char *stringRep; oldMaxWidth = listPtr->maxWidth; for (i = 0; i < objc; i++) { @@ -2332,11 +2336,11 @@ /* * Check if any of the new elements are wider than the current widest; * if so, update our notion of "widest." */ - stringRep = Tcl_GetStringFromObj(objv[i], &length); + stringRep = TkGetStringFromObj(objv[i], &length); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length); if (pixelWidth > listPtr->maxWidth) { listPtr->maxWidth = pixelWidth; } } @@ -2435,11 +2439,12 @@ ListboxDeleteSubCmd( register Listbox *listPtr, /* Listbox widget to modify. */ int first, /* Index of first element to delete. */ int last) /* Index of last element to delete. */ { - int count, i, widthChanged, length, result, pixelWidth; + int count, i, widthChanged, result, pixelWidth; + TkSizeT length; Tcl_Obj *newListObj, *element; const char *stringRep; Tcl_HashEntry *entry; /* @@ -2490,11 +2495,11 @@ * element to disappear for us to have to recompute the width. */ if (widthChanged == 0) { Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element); - stringRep = Tcl_GetStringFromObj(element, &length); + stringRep = TkGetStringFromObj(element, &length); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length); if (pixelWidth == listPtr->maxWidth) { widthChanged = 1; } } @@ -3120,11 +3125,12 @@ * not including terminating NULL * character. */ { register Listbox *listPtr = clientData; Tcl_DString selection; - int length, count, needNewline, stringLen, i; + int count, needNewline, i; + TkSizeT length, stringLen; Tcl_Obj *curElement; const char *stringRep; Tcl_HashEntry *entry; if ((!listPtr->exportSelection) || Tcl_IsSafe(listPtr->interp)) { @@ -3143,11 +3149,11 @@ if (needNewline) { Tcl_DStringAppend(&selection, "\n", 1); } Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement); - stringRep = Tcl_GetStringFromObj(curElement, &stringLen); + stringRep = TkGetStringFromObj(curElement, &stringLen); Tcl_DStringAppend(&selection, stringRep, stringLen); needNewline = 1; } } @@ -3158,18 +3164,18 @@ /* * Copy the requested portion of the selection to the buffer. */ - count = length - offset; - if (count <= 0) { + if (length <= (TkSizeT)offset) { count = 0; } else { + count = length - offset; if (count > maxBytes) { count = maxBytes; } - memcpy(buffer, Tcl_DStringValue(&selection) + offset, (size_t) count); + memcpy(buffer, Tcl_DStringValue(&selection) + offset, count); } buffer[count] = '\0'; Tcl_DStringFree(&selection); return count; } @@ -3429,38 +3435,46 @@ static char * ListboxListVarProc( ClientData clientData, /* Information about button. */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Name of variable. */ - const char *name2, /* Second part of variable name. */ + const char *name1, /* Not used. */ + const char *name2, /* Not used. */ int flags) /* Information about what happened. */ { Listbox *listPtr = clientData; Tcl_Obj *oldListObj, *varListObj; int oldLength, i; Tcl_HashEntry *entry; - /* - * See ticket [5d991b82]. - */ - - if (listPtr->listVarName == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - ListboxListVarProc, clientData); - } - return NULL; - } - /* * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable! */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + + if (!Tcl_InterpDeleted(interp) && listPtr->listVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + listPtr->listVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ListboxListVarProc, probe); + if (probe == (ClientData)listPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * listVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, listPtr->listObj, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, listPtr->listVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, clientData); Index: generic/tkMacWinMenu.c ================================================================== --- generic/tkMacWinMenu.c +++ generic/tkMacWinMenu.c @@ -11,11 +11,11 @@ */ #include "tkInt.h" #include "tkMenu.h" -typedef struct ThreadSpecificData { +typedef struct { int postCommandGeneration; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; static int PreprocessMenu(TkMenu *menuPtr); @@ -64,11 +64,11 @@ * When we get through without doing any, we are done. */ do { finished = 1; - for (index = 0; index < menuPtr->numEntries; index++) { + for (index = 0; index < (int)menuPtr->numEntries; index++) { register TkMenuEntry *entryPtr = menuPtr->entries[index]; if ((entryPtr->type == CASCADE_ENTRY) && (entryPtr->namePtr != NULL) && (entryPtr->childMenuRefPtr != NULL) Index: generic/tkMain.c ================================================================== --- generic/tkMain.c +++ generic/tkMain.c @@ -28,18 +28,10 @@ # define _UNICODE # endif #endif #include "tkInt.h" -#include -#include -#include -#ifdef NO_STDLIB_H -# include "../compat/stdlib.h" -#else -# include -#endif extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *); /* * The default prompt used when the user has not overridden it. @@ -77,26 +69,35 @@ #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #endif /* - * Further on, in UNICODE mode, we need to use Tcl_NewUnicodeObj, - * while otherwise NewNativeObj is needed (which provides proper - * conversion from native encoding to UTF-8). + * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise + * NewNativeObj is needed (which provides proper conversion from native + * encoding to UTF-8). */ + +static inline Tcl_Obj * +NewNativeObj( + TCHAR *string, + int length) +{ + Tcl_Obj *obj; + Tcl_DString ds; + #ifdef UNICODE -# define NewNativeObj Tcl_NewUnicodeObj -#else /* !UNICODE */ - static Tcl_Obj *NewNativeObj(char *string, int length) { - Tcl_Obj *obj; - Tcl_DString ds; - Tcl_ExternalToUtfDString(NULL, string, length, &ds); - obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); - Tcl_DStringFree(&ds); - return obj; -} -#endif /* !UNICODE */ + if (length > 0) { + length *= sizeof(WCHAR); + } + Tcl_WinTCharToUtf(string, length, &ds); +#else + Tcl_ExternalToUtfDString(NULL, (char *) string, length, &ds); +#endif + obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + return obj; +} /* * Declarations for various library functions and variables (don't want to * include tkInt.h or tkPort.h here, because people might copy this file out * of the Tk source directory to make their own modified versions). Note: do @@ -194,11 +195,11 @@ /* * Ensure that we are getting a compatible version of Tcl. */ - if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) { if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { abort(); } else { Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp))); } @@ -233,11 +234,11 @@ is.interp = interp; is.gotPartial = 0; Tcl_Preserve(interp); -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) #if !defined(STATIC_BUILD) /* If compiled for Win32 but running on Cygwin, don't use console */ if (!tclStubsPtr->reserved9) #endif Tk_InitConsoleChannels(interp); @@ -295,11 +296,11 @@ } Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY); argc--; argv++; - Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY); argvPtr = Tcl_NewListObj(0, NULL); while (argc--) { Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++, -1)); } @@ -322,11 +323,11 @@ nullStdin = fstat(0, &st) || (S_ISCHR(st.st_mode) && !st.st_blocks); } #endif Tcl_SetVar2Ex(interp, "tcl_interactive", NULL, - Tcl_NewIntObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY); + Tcl_NewWideIntObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY); /* * Invoke application-specific initialization. */ @@ -422,18 +423,19 @@ StdinProc( ClientData clientData, /* The state of interactive cmd line */ int mask) /* Not used. */ { char *cmd; - int code, count; + int code; + size_t count; InteractiveState *isPtr = clientData; Tcl_Channel chan = isPtr->input; Tcl_Interp *interp = isPtr->interp; count = Tcl_Gets(chan, &isPtr->line); - if (count < 0 && !isPtr->gotPartial) { + if (count == (size_t)-1 && !isPtr->gotPartial) { if (isPtr->tty) { Tcl_Exit(0); } else { Tcl_DeleteChannelHandler(chan, StdinProc, isPtr); } Index: generic/tkMenu.c ================================================================== --- generic/tkMenu.c +++ generic/tkMenu.c @@ -36,11 +36,11 @@ * * To handle all of the constraints, Tk menubars and tearoff menus are * implemented using menu clones. Menu clones are full menus in their own * right; they have a Tk window and pathname associated with them; they have a * TkMenu structure and array of entries. However, they are linked with the - * original menu that they were cloned from. The reflect the attributes of the + * original menu that they were cloned from. They reflect the attributes of the * original, or "master", menu. So if an item is added to a menu, and that * menu has clones, then the item must be added to all of its clones also. * Menus are cloned when a menu is torn-off or when a menu is assigned as a * menubar using the "-menu" option of the toplevel's pathname configure * subcommand. When a clone is destroyed, only the clone is destroyed, but @@ -75,11 +75,11 @@ #include "tkInt.h" #include "tkMenu.h" #define MENU_HASH_KEY "tkMenus" -typedef struct ThreadSpecificData { +typedef struct { int menusInitialized; /* Flag indicates whether thread-specific * elements of the Windows Menu module have * been initialized. */ Tk_OptionTable menuOptionTable; /* The option table for menus. */ @@ -88,11 +88,11 @@ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following flag indicates whether the process-wide state for the Menu - * module has been intialized. The Mutex protects access to that flag. + * module has been initialized. The Mutex protects access to that flag. */ static int menusInitialized; TCL_DECLARE_MUTEX(menuMutex) @@ -116,121 +116,121 @@ "bottom", "center", "left", "none", "right", "top", NULL }; static const Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = { {TK_OPTION_BORDER, "-activebackground", NULL, NULL, - DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1, + DEF_MENU_ENTRY_ACTIVE_BG, offsetof(TkMenuEntry, activeBorderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_COLOR, "-activeforeground", NULL, NULL, DEF_MENU_ENTRY_ACTIVE_FG, - Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-accelerator", NULL, NULL, DEF_MENU_ENTRY_ACCELERATOR, - Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_BORDER, "-background", NULL, NULL, DEF_MENU_ENTRY_BG, - Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_BITMAP, "-bitmap", NULL, NULL, DEF_MENU_ENTRY_BITMAP, - Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_BOOLEAN, "-columnbreak", NULL, NULL, DEF_MENU_ENTRY_COLUMN_BREAK, - -1, Tk_Offset(TkMenuEntry, columnBreak), 0, NULL, 0}, + -1, offsetof(TkMenuEntry, columnBreak), 0, NULL, 0}, {TK_OPTION_STRING, "-command", NULL, NULL, DEF_MENU_ENTRY_COMMAND, - Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0, + DEF_MENU_ENTRY_COMPOUND, -1, offsetof(TkMenuEntry, compound), 0, (ClientData) compoundStrings, 0}, {TK_OPTION_FONT, "-font", NULL, NULL, DEF_MENU_ENTRY_FONT, - Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_COLOR, "-foreground", NULL, NULL, DEF_MENU_ENTRY_FG, - Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_BOOLEAN, "-hidemargin", NULL, NULL, DEF_MENU_ENTRY_HIDE_MARGIN, - -1, Tk_Offset(TkMenuEntry, hideMargin), 0, NULL, 0}, + -1, offsetof(TkMenuEntry, hideMargin), 0, NULL, 0}, {TK_OPTION_STRING, "-image", NULL, NULL, DEF_MENU_ENTRY_IMAGE, - Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-label", NULL, NULL, DEF_MENU_ENTRY_LABEL, - Tk_Offset(TkMenuEntry, labelPtr), -1, 0, NULL, 0}, + offsetof(TkMenuEntry, labelPtr), -1, 0, NULL, 0}, {TK_OPTION_STRING_TABLE, "-state", NULL, NULL, DEF_MENU_ENTRY_STATE, - -1, Tk_Offset(TkMenuEntry, state), 0, + -1, offsetof(TkMenuEntry, state), 0, (ClientData) menuStateStrings, 0}, {TK_OPTION_INT, "-underline", NULL, NULL, - DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline), 0, NULL, 0}, + DEF_MENU_ENTRY_UNDERLINE, -1, offsetof(TkMenuEntry, underline), 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0} }; static const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = { {TK_OPTION_BORDER, "-background", NULL, NULL, DEF_MENU_ENTRY_BG, - Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0} }; static const Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = { {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL, DEF_MENU_ENTRY_INDICATOR, - -1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0}, + -1, offsetof(TkMenuEntry, indicatorOn), 0, NULL, 0}, {TK_OPTION_STRING, "-offvalue", NULL, NULL, DEF_MENU_ENTRY_OFF_VALUE, - Tk_Offset(TkMenuEntry, offValuePtr), -1, 0, NULL, 0}, + offsetof(TkMenuEntry, offValuePtr), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-onvalue", NULL, NULL, DEF_MENU_ENTRY_ON_VALUE, - Tk_Offset(TkMenuEntry, onValuePtr), -1, 0, NULL, 0}, + offsetof(TkMenuEntry, onValuePtr), -1, 0, NULL, 0}, {TK_OPTION_COLOR, "-selectcolor", NULL, NULL, DEF_MENU_ENTRY_SELECT, - Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-selectimage", NULL, NULL, DEF_MENU_ENTRY_SELECT_IMAGE, - Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-variable", NULL, NULL, DEF_MENU_ENTRY_CHECK_VARIABLE, - Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0} }; static const Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = { {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL, DEF_MENU_ENTRY_INDICATOR, - -1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0}, + -1, offsetof(TkMenuEntry, indicatorOn), 0, NULL, 0}, {TK_OPTION_COLOR, "-selectcolor", NULL, NULL, DEF_MENU_ENTRY_SELECT, - Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-selectimage", NULL, NULL, DEF_MENU_ENTRY_SELECT_IMAGE, - Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-value", NULL, NULL, DEF_MENU_ENTRY_VALUE, - Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-variable", NULL, NULL, DEF_MENU_ENTRY_RADIO_VARIABLE, - Tk_Offset(TkMenuEntry, namePtr), -1, 0, NULL, 0}, + offsetof(TkMenuEntry, namePtr), -1, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0} }; static const Tk_OptionSpec tkCascadeEntryConfigSpecs[] = { {TK_OPTION_STRING, "-menu", NULL, NULL, DEF_MENU_ENTRY_MENU, - Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0} }; static const Tk_OptionSpec tkTearoffEntryConfigSpecs[] = { {TK_OPTION_BORDER, "-background", NULL, NULL, DEF_MENU_ENTRY_BG, - Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING_TABLE, "-state", NULL, NULL, - DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0, + DEF_MENU_ENTRY_STATE, -1, offsetof(TkMenuEntry, state), 0, (ClientData) menuStateStrings, 0}, {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0} }; static const Tk_OptionSpec *specsArray[] = { @@ -248,63 +248,66 @@ }; static const Tk_OptionSpec tkMenuConfigSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", DEF_MENU_ACTIVE_BG_COLOR, - Tk_Offset(TkMenu, activeBorderPtr), -1, 0, + offsetof(TkMenu, activeBorderPtr), -1, 0, (ClientData) DEF_MENU_ACTIVE_BG_MONO, 0}, {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth", "BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH, - Tk_Offset(TkMenu, activeBorderWidthPtr), -1, 0, NULL, 0}, + offsetof(TkMenu, activeBorderWidthPtr), -1, 0, NULL, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", DEF_MENU_ACTIVE_FG_COLOR, - Tk_Offset(TkMenu, activeFgPtr), -1, 0, + offsetof(TkMenu, activeFgPtr), -1, 0, (ClientData) DEF_MENU_ACTIVE_FG_MONO, 0}, + {TK_OPTION_RELIEF, "-activerelief", "activeRelief", "Relief", + DEF_MENU_ACTIVE_RELIEF, offsetof(TkMenu, activeReliefPtr), + -1, 0, NULL, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0, + DEF_MENU_BG_COLOR, offsetof(TkMenu, borderPtr), -1, 0, (ClientData) DEF_MENU_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_MENU_BORDER_WIDTH, - Tk_Offset(TkMenu, borderWidthPtr), -1, 0, NULL, 0}, + offsetof(TkMenu, borderWidthPtr), -1, 0, NULL, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_MENU_CURSOR, - Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_MENU_DISABLED_FG_COLOR, - Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK, + offsetof(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK, (ClientData) DEF_MENU_DISABLED_FG_MONO, 0}, {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1, 0, NULL, 0}, + DEF_MENU_FONT, offsetof(TkMenu, fontPtr), -1, 0, NULL, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1, 0, NULL, 0}, + DEF_MENU_FG, offsetof(TkMenu, fgPtr), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-postcommand", "postCommand", "Command", DEF_MENU_POST_COMMAND, - Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1, 0, NULL, 0}, + DEF_MENU_RELIEF, offsetof(TkMenu, reliefPtr), -1, 0, NULL, 0}, {TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background", - DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0, + DEF_MENU_SELECT_COLOR, offsetof(TkMenu, indicatorFgPtr), -1, 0, (ClientData) DEF_MENU_SELECT_MONO, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_MENU_TAKE_FOCUS, - Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff", - DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff), 0, NULL, 0}, + DEF_MENU_TEAROFF, -1, offsetof(TkMenu, tearoff), 0, NULL, 0}, {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand", "TearOffCommand", DEF_MENU_TEAROFF_CMD, - Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, + offsetof(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-title", "title", "Title", - DEF_MENU_TITLE, Tk_Offset(TkMenu, titlePtr), -1, + DEF_MENU_TITLE, offsetof(TkMenu, titlePtr), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING_TABLE, "-type", "type", "Type", - DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK, + DEF_MENU_TYPE, offsetof(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK, (ClientData) menuTypeStrings, 0}, {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0} }; /* @@ -341,22 +344,22 @@ int first, int last); static void DestroyMenuHashTable(ClientData clientData, Tcl_Interp *interp); static void DestroyMenuInstance(TkMenu *menuPtr); static void DestroyMenuEntry(void *memPtr); -static int GetIndexFromCoords(Tcl_Interp *interp, +static TkSizeT GetIndexFromCoords(Tcl_Interp *interp, TkMenu *menuPtr, const char *string, - int *indexPtr); + TkSizeT *indexPtr); static int MenuDoYPosition(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *objPtr); static int MenuDoXPosition(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *objPtr); static int MenuAddOrInsert(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc, Tcl_Obj *const objv[]); static void MenuCmdDeletedProc(ClientData clientData); -static TkMenuEntry * MenuNewEntry(TkMenu *menuPtr, int index, int type); +static TkMenuEntry * MenuNewEntry(TkMenu *menuPtr, TkSizeT index, int type); static char * MenuVarProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static int MenuWidgetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, @@ -452,11 +455,11 @@ menuPtr->display = Tk_Display(newWin); menuPtr->interp = interp; menuPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, menuPtr, MenuCmdDeletedProc); - menuPtr->active = -1; + menuPtr->active = TCL_INDEX_NONE; menuPtr->cursorPtr = NULL; menuPtr->masterMenuPtr = menuPtr; menuPtr->menuType = UNKNOWN_TYPE; TkMenuInitializeDrawingFields(menuPtr); @@ -463,11 +466,11 @@ Tk_SetClass(menuPtr->tkwin, "Menu"); Tk_SetClassProcs(menuPtr->tkwin, &menuClass, menuPtr); Tk_CreateEventHandler(newWin, ExposureMask|StructureNotifyMask|ActivateMask, TkMenuEventProc, menuPtr); - if (Tk_InitOptions(interp, (char *) menuPtr, + if (Tk_InitOptions(interp, menuPtr, tsdPtr->menuOptionTable, menuPtr->tkwin) != TCL_OK) { Tk_DestroyWindow(menuPtr->tkwin); return TCL_ERROR; } @@ -634,11 +637,11 @@ } Tcl_Preserve(menuPtr); switch ((enum options) option) { case MENU_ACTIVATE: { - int index; + TkSizeT index; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "index"); goto error; } @@ -646,13 +649,13 @@ goto error; } if (menuPtr->active == index) { goto done; } - if ((index >= 0) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY) + if ((index != TCL_INDEX_NONE) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY) || (menuPtr->entries[index]->state == ENTRY_DISABLED))) { - index = -1; + index = TCL_INDEX_NONE; } result = TkActivateMenuEntry(menuPtr, index); break; } case MENU_ADD: @@ -670,11 +673,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } - resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr, + resultPtr = Tk_GetOptionValue(interp, menuPtr, tsdPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { goto error; } @@ -690,21 +693,21 @@ break; case MENU_CONFIGURE: { Tcl_Obj *resultPtr; if (objc == 2) { - resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, + resultPtr = Tk_GetOptionInfo(interp, menuPtr, tsdPtr->menuOptionTable, NULL, menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; } else { result = TCL_OK; Tcl_SetObjResult(interp, resultPtr); } } else if (objc == 3) { - resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, + resultPtr = Tk_GetOptionInfo(interp, menuPtr, tsdPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; } else { @@ -718,11 +721,12 @@ goto error; } break; } case MENU_DELETE: { - int first, last; + TkSizeT first, last; + Tcl_WideInt w; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "first ?last?"); goto error; } @@ -731,11 +735,12 @@ * If 'first' explicitly refers to past the end of the menu, we don't * do anything. [Bug 220950] */ if (isdigit(UCHAR(Tcl_GetString(objv[2])[0])) - && Tcl_GetIntFromObj(NULL, objv[2], &first) == TCL_OK) { + && Tcl_GetWideIntFromObj(NULL, objv[2], &w) == TCL_OK) { + first = w; if (first >= menuPtr->numEntries) { goto done; } } else if (TkGetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){ goto error; @@ -759,61 +764,61 @@ } DeleteMenuCloneEntries(menuPtr, first, last); break; } case MENU_ENTRYCGET: { - int index; + TkSizeT index; Tcl_Obj *resultPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "index option"); goto error; } if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } - if (index < 0) { + if (index == TCL_INDEX_NONE) { goto done; } mePtr = menuPtr->entries[index]; Tcl_Preserve(mePtr); - resultPtr = Tk_GetOptionValue(interp, (char *) mePtr, + resultPtr = Tk_GetOptionValue(interp, mePtr, mePtr->optionTable, objv[3], menuPtr->tkwin); Tcl_Release(mePtr); if (resultPtr == NULL) { goto error; } Tcl_SetObjResult(interp, resultPtr); break; } case MENU_ENTRYCONFIGURE: { - int index; + TkSizeT index; Tcl_Obj *resultPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "index ?-option value ...?"); goto error; } if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } - if (index < 0) { + if (index == TCL_INDEX_NONE) { goto done; } mePtr = menuPtr->entries[index]; Tcl_Preserve(mePtr); if (objc == 3) { - resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr, + resultPtr = Tk_GetOptionInfo(interp, mePtr, mePtr->optionTable, NULL, menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; } else { result = TCL_OK; Tcl_SetObjResult(interp, resultPtr); } } else if (objc == 4) { - resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr, + resultPtr = Tk_GetOptionInfo(interp, mePtr, mePtr->optionTable, objv[3], menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; } else { result = TCL_OK; @@ -825,23 +830,23 @@ } Tcl_Release(mePtr); break; } case MENU_INDEX: { - int index; + TkSizeT index; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "string"); goto error; } if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } - if (index < 0) { + if (index == TCL_INDEX_NONE) { Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); } else { - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index)); } break; } case MENU_INSERT: if (objc < 4) { @@ -852,85 +857,91 @@ if (MenuAddOrInsert(interp,menuPtr,objv[2],objc-3,objv+3) != TCL_OK) { goto error; } break; case MENU_INVOKE: { - int index; + TkSizeT index; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "index"); goto error; } if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } - if (index < 0) { + if (index == TCL_INDEX_NONE) { goto done; } result = TkInvokeMenu(interp, menuPtr, index); break; } case MENU_POST: { int x, y; + TkSizeT index = TCL_INDEX_NONE; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "x y"); + if (objc != 4 && objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "x y ?index?"); goto error; } if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { goto error; } + if (objc == 5) { + if (TkGetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) { + goto error; + } + } /* - * Tearoff menus are posted differently on Mac and Windows than - * non-tearoffs. TkpPostMenu does not actually map the menu's window - * on those platforms, and popup menus have to be handled specially. - * Also, menubar menues are not intended to be posted (bug 1567681, - * 2160206). + * Tearoff menus are the same as ordinary menus on the Mac and are + * posted differently on Windows than non-tearoffs. TkpPostMenu + * does not actually map the menu's window on those platforms, and + * popup menus have to be handled specially. Also, menubar menus are + * not intended to be posted (bug 1567681, 2160206). */ if (menuPtr->menuType == MENUBAR) { Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL); return TCL_ERROR; } else if (menuPtr->menuType != TEAROFF_MENU) { - result = TkpPostMenu(interp, menuPtr, x, y); + result = TkpPostMenu(interp, menuPtr, x, y, index); } else { - result = TkPostTearoffMenu(interp, menuPtr, x, y); + result = TkpPostTearoffMenu(interp, menuPtr, x, y, index); } break; } case MENU_POSTCASCADE: { - int index; + TkSizeT index; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "index"); goto error; } if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } - if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) { + if ((index == TCL_INDEX_NONE) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) { result = TkPostSubmenu(interp, menuPtr, NULL); } else { result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]); } break; } case MENU_TYPE: { - int index; + TkSizeT index; const char *typeStr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "index"); goto error; } if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } - if (index < 0) { + if (index == TCL_INDEX_NONE) { goto done; } if (menuPtr->entries[index]->type == TEAROFF_ENTRY) { typeStr = "tearoff"; } else { @@ -991,17 +1002,17 @@ int TkInvokeMenu( Tcl_Interp *interp, /* The interp that the menu lives in. */ TkMenu *menuPtr, /* The menu we are invoking. */ - int index) /* The zero based index of the item we are + TkSizeT index) /* The zero based index of the item we are * invoking. */ { int result = TCL_OK; TkMenuEntry *mePtr; - if (index < 0) { + if (index == TCL_INDEX_NONE) { goto done; } mePtr = menuPtr->entries[index]; if (mePtr->state == ENTRY_DISABLED) { goto done; @@ -1479,11 +1490,11 @@ static void MenuWorldChanged( ClientData instanceData) /* Information about widget. */ { TkMenu *menuPtr = instanceData; - int i; + TkSizeT i; TkMenuConfigureDrawOptions(menuPtr); for (i = 0; i < menuPtr->numEntries; i++) { TkMenuConfigureEntryDrawOptions(menuPtr->entries[i], menuPtr->entries[i]->index); @@ -1526,11 +1537,11 @@ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { menuListPtr->errorStructPtr = ckalloc(sizeof(Tk_SavedOptions)); - result = Tk_SetOptions(interp, (char *) menuListPtr, + result = Tk_SetOptions(interp, menuListPtr, tsdPtr->menuOptionTable, objc, objv, menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL); if (result != TCL_OK) { for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != menuListPtr; @@ -1620,16 +1631,15 @@ && (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) { int i; Tcl_EventuallyFree(menuListPtr->entries[0], (Tcl_FreeProc *) DestroyMenuEntry); - for (i = 0; i < menuListPtr->numEntries - 1; i++) { + for (i = 0; i < (int)menuListPtr->numEntries - 1; i++) { menuListPtr->entries[i] = menuListPtr->entries[i + 1]; menuListPtr->entries[i]->index = i; } - menuListPtr->numEntries--; - if (menuListPtr->numEntries == 0) { + if (--menuListPtr->numEntries == 0) { ckfree(menuListPtr->entries); menuListPtr->entries = NULL; } } @@ -1640,11 +1650,11 @@ * entries in the menu, since some of the things in the children (such * as graphics contexts) may have to change to reflect changes in the * parent. */ - for (i = 0; i < menuListPtr->numEntries; i++) { + for (i = 0; i < (int)menuListPtr->numEntries; i++) { TkMenuEntry *mePtr; mePtr = menuListPtr->entries[i]; ConfigureMenuEntry(mePtr, 0, NULL); } @@ -1698,16 +1708,16 @@ */ if (mePtr->labelPtr == NULL) { mePtr->labelLength = 0; } else { - Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); + (void)TkGetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); } if (mePtr->accelPtr == NULL) { mePtr->accelLength = 0; } else { - Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); + (void)TkGetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); } /* * If this is a cascade entry, the platform-specific data of the child * menu has to be updated. Also, the links that point to parents and @@ -1922,11 +1932,11 @@ MenuVarProc, mePtr); } result = TCL_OK; if (menuPtr->tkwin != NULL) { - if (Tk_SetOptions(menuPtr->interp, (char *) mePtr, + if (Tk_SetOptions(menuPtr->interp, mePtr, mePtr->optionTable, objc, objv, menuPtr->tkwin, &errorStruct, NULL) != TCL_OK) { return TCL_ERROR; } result = PostProcessEntry(mePtr); @@ -2108,11 +2118,11 @@ * specified. */ Tcl_Obj *objPtr, /* Specification of an entry in menu. See * manual entry for valid .*/ int lastOK, /* Non-zero means its OK to return index just * *after* last entry. */ - int *indexPtr) /* Where to store converted index. */ + TkSizeT *indexPtr) /* Where to store converted index. */ { int i; const char *string = Tcl_GetString(objPtr); if ((string[0] == 'a') && (strcmp(string, "active") == 0)) { @@ -2125,11 +2135,11 @@ *indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1); goto success; } if ((string[0] == 'n') && (strcmp(string, "none") == 0)) { - *indexPtr = -1; + *indexPtr = TCL_INDEX_NONE; goto success; } if (string[0] == '@') { if (GetIndexFromCoords(interp, menuPtr, string, indexPtr) @@ -2138,11 +2148,11 @@ } } if (isdigit(UCHAR(string[0]))) { if (Tcl_GetInt(interp, string, &i) == TCL_OK) { - if (i >= menuPtr->numEntries) { + if (i >= (int)menuPtr->numEntries) { if (lastOK) { i = menuPtr->numEntries; } else { i = menuPtr->numEntries-1; } @@ -2153,11 +2163,11 @@ goto success; } Tcl_ResetResult(interp); } - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int)menuPtr->numEntries; i++) { Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr; const char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr); if ((label != NULL) && (Tcl_StringMatch(label, string))) { *indexPtr = i; @@ -2236,17 +2246,17 @@ */ static TkMenuEntry * MenuNewEntry( TkMenu *menuPtr, /* Menu that will hold the new entry. */ - int index, /* Where in the menu the new entry is to + TkSizeT index, /* Where in the menu the new entry is to * go. */ int type) /* The type of the new entry. */ { TkMenuEntry *mePtr; TkMenuEntry **newEntries; - int i; + TkSizeT i; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Create a new array of entries with an empty slot for the new entry. @@ -2296,11 +2306,11 @@ mePtr->onValuePtr = NULL; mePtr->offValuePtr = NULL; mePtr->entryFlags = 0; mePtr->index = index; mePtr->nextCascadePtr = NULL; - if (Tk_InitOptions(menuPtr->interp, (char *) mePtr, + if (Tk_InitOptions(menuPtr->interp, mePtr, mePtr->optionTable, menuPtr->tkwin) != TCL_OK) { ckfree(mePtr); return NULL; } TkMenuInitializeEntryDrawingFields(mePtr); @@ -2339,11 +2349,12 @@ * NULL means insert at end. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[]) /* Arguments to command: first arg is type of * entry, others are config options. */ { - int type, index; + int type; + TkSizeT index; TkMenuEntry *mePtr; TkMenu *menuListPtr; if (indexPtr != NULL) { if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) { @@ -2350,11 +2361,11 @@ return TCL_ERROR; } } else { index = menuPtr->numEntries; } - if (index < 0) { + if (index == TCL_INDEX_NONE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\"", Tcl_GetString(indexPtr))); Tcl_SetErrorCode(interp, "TK", "MENU", "INDEX", NULL); return TCL_ERROR; } @@ -2382,11 +2393,11 @@ if (mePtr == NULL) { return TCL_ERROR; } if (ConfigureMenuEntry(mePtr, objc - 1, objv + 1) != TCL_OK) { TkMenu *errorMenuPtr; - int i; + TkSizeT i; for (errorMenuPtr = menuPtr->masterMenuPtr; errorMenuPtr != NULL; errorMenuPtr = errorMenuPtr->nextInstancePtr) { Tcl_EventuallyFree(errorMenuPtr->entries[index], @@ -2393,12 +2404,11 @@ (Tcl_FreeProc *) DestroyMenuEntry); for (i = index; i < errorMenuPtr->numEntries - 1; i++) { errorMenuPtr->entries[i] = errorMenuPtr->entries[i + 1]; errorMenuPtr->entries[i]->index = i; } - errorMenuPtr->numEntries--; - if (errorMenuPtr->numEntries == 0) { + if (--errorMenuPtr->numEntries == 0) { ckfree(errorMenuPtr->entries); errorMenuPtr->entries = NULL; } if (errorMenuPtr == menuListPtr) { break; @@ -2484,13 +2494,14 @@ TkMenuEntry *mePtr = clientData; TkMenu *menuPtr; const char *value; const char *name, *onValue; - if (flags & TCL_INTERP_DESTROYED) { + if (Tcl_InterpDeleted(interp) || (mePtr->namePtr == NULL)) { /* - * Do nothing if the interpreter is going away. + * Do nothing if the interpreter is going away or we have + * no variable name. */ return NULL; } @@ -2498,34 +2509,40 @@ if (menuPtr->menuFlags & MENU_DELETION_PENDING) { return NULL; } - /* - * See ticket [5d991b82]. - */ - - if (mePtr->namePtr == NULL) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - MenuVarProc, clientData); - return NULL; - } - name = Tcl_GetString(mePtr->namePtr); /* * If the variable is being unset, then re-establish the trace. */ if (flags & TCL_TRACE_UNSETS) { + ClientData probe = NULL; mePtr->entryFlags &= ~ENTRY_SELECTED; - if (flags & TCL_TRACE_DESTROYED) { - Tcl_TraceVar2(interp, name, NULL, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - MenuVarProc, clientData); - } + + do { + probe = Tcl_VarTraceInfo(interp, name, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MenuVarProc, probe); + if (probe == (ClientData)mePtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * namePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } + Tcl_TraceVar2(interp, name, NULL, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MenuVarProc, clientData); TkpConfigureMenuEntry(mePtr); TkEventuallyRedrawMenu(menuPtr, NULL); return NULL; } @@ -2578,17 +2595,17 @@ */ int TkActivateMenuEntry( register TkMenu *menuPtr, /* Menu in which to activate. */ - int index) /* Index of entry to activate, or -1 to - * deactivate all entries. */ + TkSizeT index) /* Index of entry to activate, or + * TCL_INDEX_NONE to deactivate all entries. */ { register TkMenuEntry *mePtr; int result = TCL_OK; - if (menuPtr->active >= 0) { + if (menuPtr->active != TCL_INDEX_NONE) { mePtr = menuPtr->entries[menuPtr->active]; /* * Don't change the state unless it's currently active (state might * already have been changed to disabled). @@ -2598,11 +2615,11 @@ mePtr->state = ENTRY_NORMAL; } TkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]); } menuPtr->active = index; - if (index >= 0) { + if (index != TCL_INDEX_NONE) { mePtr = menuPtr->entries[index]; mePtr->state = ENTRY_ACTIVE; TkEventuallyRedrawMenu(menuPtr, mePtr); } return result; @@ -2789,11 +2806,11 @@ /* * Clone all of the cascade menus that this menu points to. */ - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int)menuPtr->numEntries; i++) { TkMenuReferences *cascadeRefPtr; TkMenu *oldCascadePtr; if ((menuPtr->entries[i]->type == CASCADE_ENTRY) && (menuPtr->entries[i]->namePtr != NULL)) { @@ -2853,21 +2870,21 @@ MenuDoXPosition( Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *objPtr) { - int index; + TkSizeT index; TkRecomputeMenu(menuPtr); if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult(interp); - if (index < 0) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); + if (index == TCL_INDEX_NONE) { + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); } else { - Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->x)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(menuPtr->entries[index]->x)); } return TCL_OK; } /* @@ -2890,21 +2907,21 @@ MenuDoYPosition( Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *objPtr) { - int index; + TkSizeT index; TkRecomputeMenu(menuPtr); if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) { goto error; } Tcl_ResetResult(interp); - if (index < 0) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); + if (index == TCL_INDEX_NONE) { + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); } else { - Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->y)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(menuPtr->entries[index]->y)); } return TCL_OK; error: @@ -2928,16 +2945,16 @@ * If int is invalid, interp's result will be set to NULL. * *---------------------------------------------------------------------- */ -static int +static TkSizeT GetIndexFromCoords( Tcl_Interp *interp, /* Interpreter of menu. */ TkMenu *menuPtr, /* The menu we are searching. */ const char *string, /* The @string we are parsing. */ - int *indexPtr) /* The index of the item that matches. */ + TkSizeT *indexPtr) /* The index of the item that matches. */ { int x, y, i; const char *p; char *end; int x2, borderwidth, max; @@ -2968,11 +2985,11 @@ */ max = Tk_IsMapped(menuPtr->tkwin) ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin); max -= borderwidth; - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int)menuPtr->numEntries; i++) { if (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) { x2 = max; } else { x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width; } @@ -3011,11 +3028,11 @@ static void RecursivelyDeleteMenu( TkMenu *menuPtr) /* The menubar instance we are deleting. */ { - int i; + TkSizeT i; TkMenuEntry *mePtr; /* * It is not 100% clear that this preserve/release pair is required, but * we have added them for safety in this very complex code. @@ -3098,11 +3115,11 @@ resultPtr = Tcl_DuplicateObj(parentPtr); if (doDot) { Tcl_AppendToObj(resultPtr, ".", -1); } Tcl_AppendObjToObj(resultPtr, childPtr); - intPtr = Tcl_NewIntObj(i); + intPtr = Tcl_NewWideIntObj(i); Tcl_AppendObjToObj(resultPtr, intPtr); Tcl_DecrRefCount(intPtr); } destString = Tcl_GetString(resultPtr); if ((Tcl_FindCommand(interp, destString, NULL, 0) == NULL) @@ -3515,24 +3532,24 @@ for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { for (i = last; i >= first; i--) { Tcl_EventuallyFree(menuListPtr->entries[i], (Tcl_FreeProc *) DestroyMenuEntry); } - for (i = last + 1; i < menuListPtr->numEntries; i++) { + for (i = last + 1; i < (int)menuListPtr->numEntries; i++) { j = i - numDeleted; menuListPtr->entries[j] = menuListPtr->entries[i]; menuListPtr->entries[j]->index = j; } menuListPtr->numEntries -= numDeleted; if (menuListPtr->numEntries == 0) { ckfree(menuListPtr->entries); menuListPtr->entries = NULL; } - if ((menuListPtr->active >= first) - && (menuListPtr->active <= last)) { + if (((int)menuListPtr->active >= first) + && ((int)menuListPtr->active <= last)) { menuListPtr->active = -1; - } else if (menuListPtr->active > last) { + } else if ((int)menuListPtr->active > last) { menuListPtr->active -= numDeleted; } TkEventuallyRecomputeMenu(menuListPtr); } } Index: generic/tkMenu.h ================================================================== --- generic/tkMenu.h +++ generic/tkMenu.h @@ -66,15 +66,15 @@ struct TkMenu *menuPtr; /* Menu with which this entry is * associated. */ Tk_OptionTable optionTable; /* Option table for this menu entry. */ Tcl_Obj *labelPtr; /* Main text label displayed in entry (NULL if * no label). */ - int labelLength; /* Number of non-NULL characters in label. */ + TkSizeT labelLength; /* Number of non-NULL characters in label. */ int state; /* State of button for display purposes: * normal, active, or disabled. */ int underline; /* Value of -underline option: specifies index - * of character to underline (<0 means don't + * of character to underline (-1 means don't * underline anything). */ Tcl_Obj *underlinePtr; /* Index of character to underline. */ Tcl_Obj *bitmapPtr; /* Bitmap to display in menu entry, or NULL. * If not NULL then label is ignored. */ Tcl_Obj *imagePtr; /* Name of image to display, or NULL. If not @@ -87,11 +87,11 @@ Tk_Image selectImage; /* Image to display in entry when selected, or * NULL if none. Ignored if image is NULL. */ Tcl_Obj *accelPtr; /* Accelerator string displayed at right of * menu entry. NULL means no such accelerator. * Malloc'ed. */ - int accelLength; /* Number of non-NULL characters in + TkSizeT accelLength; /* Number of non-NULL characters in * accelerator. */ int indicatorOn; /* True means draw indicator, false means * don't draw it. This field is ignored unless * the entry is a radio or check button. */ /* @@ -118,11 +118,11 @@ * item in front of it. If this is 1, this * item starts a new column. This field is * always 0 for tearoff and separator * entries. */ int hideMargin; /* If this is 0, then the item has enough - * margin to accomodate a standard check mark + * margin to accommodate a standard check mark * and a default right margin. If this is 1, * then the item has no such margins, and * checkbuttons and radiobuttons with this set * will have a rectangle drawn in the * indicator around the item if the item is @@ -265,13 +265,13 @@ * freed up even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with menu. */ Tcl_Command widgetCmd; /* Token for menu's widget command. */ TkMenuEntry **entries; /* Array of pointers to all the entries in the * menu. NULL means no entries. */ - int numEntries; /* Number of elements in entries. */ - int active; /* Index of active entry. -1 means nothing - * active. */ + TkSizeT numEntries; /* Number of elements in entries. */ + TkSizeT active; /* Index of active entry. TCL_INDEX_NONE means + * nothing active. */ int menuType; /* MASTER_MENU, TEAROFF_MENU, or MENUBAR. See * below for definitions. */ Tcl_Obj *menuTypePtr; /* Used to control whether created tkwin is a * toplevel or not. "normal", "menubar", or * "toplevel" */ @@ -380,10 +380,11 @@ * this widget to be extended. */ Tk_SavedOptions *errorStructPtr; /* We actually have to allocate these because * multiple menus get changed during one * ConfigureMenu call. */ + Tcl_Obj *activeReliefPtr; /* 3-d effect for active element. */ } TkMenu; /* * When the toplevel configure -menu command is executed, the menu may not * exist yet. We need to keep a linked list of windows that reference a @@ -479,11 +480,11 @@ /* * Menu-related functions that are shared among Tk modules but not exported to * the outside world: */ -MODULE_SCOPE int TkActivateMenuEntry(TkMenu *menuPtr, int index); +MODULE_SCOPE int TkActivateMenuEntry(TkMenu *menuPtr, TkSizeT index); MODULE_SCOPE void TkBindMenu(Tk_Window tkwin, TkMenu *menuPtr); MODULE_SCOPE TkMenuReferences*TkCreateMenuReferences(Tcl_Interp *interp, const char *name); MODULE_SCOPE void TkDestroyMenu(TkMenu *menuPtr); MODULE_SCOPE void TkEventuallyRecomputeMenu(TkMenu *menuPtr); @@ -493,18 +494,18 @@ MODULE_SCOPE TkMenuReferences*TkFindMenuReferencesObj(Tcl_Interp *interp, Tcl_Obj *namePtr); MODULE_SCOPE int TkFreeMenuReferences(TkMenuReferences *menuRefPtr); MODULE_SCOPE Tcl_HashTable *TkGetMenuHashTable(Tcl_Interp *interp); MODULE_SCOPE int TkGetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr, - Tcl_Obj *objPtr, int lastOK, int *indexPtr); + Tcl_Obj *objPtr, int lastOK, TkSizeT *indexPtr); MODULE_SCOPE void TkMenuInitializeDrawingFields(TkMenu *menuPtr); MODULE_SCOPE void TkMenuInitializeEntryDrawingFields(TkMenuEntry *mePtr); MODULE_SCOPE int TkInvokeMenu(Tcl_Interp *interp, TkMenu *menuPtr, - int index); + TkSizeT index); MODULE_SCOPE void TkMenuConfigureDrawOptions(TkMenu *menuPtr); MODULE_SCOPE int TkMenuConfigureEntryDrawOptions( - TkMenuEntry *mePtr, int index); + TkMenuEntry *mePtr, TkSizeT index); MODULE_SCOPE void TkMenuFreeDrawOptions(TkMenu *menuPtr); MODULE_SCOPE void TkMenuEntryFreeDrawOptions(TkMenuEntry *mePtr); MODULE_SCOPE void TkMenuEventProc(ClientData clientData, XEvent *eventPtr); MODULE_SCOPE void TkMenuImageProc(ClientData clientData, int x, int y, @@ -518,11 +519,11 @@ Tcl_Obj *parentNamePtr, TkMenu *menuPtr); MODULE_SCOPE int TkPostCommand(TkMenu *menuPtr); MODULE_SCOPE int TkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr, TkMenuEntry *mePtr); MODULE_SCOPE int TkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr, - int x, int y); + int x, int y); MODULE_SCOPE int TkPreprocessMenu(TkMenu *menuPtr); MODULE_SCOPE void TkRecomputeMenu(TkMenu *menuPtr); /* * These routines are the platform-dependent routines called by the common @@ -541,9 +542,11 @@ int drawingParameters); MODULE_SCOPE void TkpMenuInit(void); MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr); MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr); MODULE_SCOPE int TkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr, - int x, int y); + int x, int y, int index); +MODULE_SCOPE int TkpPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr, + int x, int y, int index); MODULE_SCOPE void TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr); #endif /* _TKMENU */ Index: generic/tkMenuDraw.c ================================================================== --- generic/tkMenuDraw.c +++ generic/tkMenuDraw.c @@ -296,11 +296,11 @@ */ int TkMenuConfigureEntryDrawOptions( TkMenuEntry *mePtr, - int index) + TkSizeT index) { XGCValues gcValues; GC newGC, newActiveGC, newDisabledGC, newIndicatorGC; unsigned long mask; Tk_Font tkfont; @@ -473,11 +473,11 @@ * * Results: * None. * * Side effects: - * A when-idle hander is scheduled to do the redisplay, if there isn't + * A when-idle handler is scheduled to do the redisplay, if there isn't * one already scheduled. * *---------------------------------------------------------------------- */ @@ -485,11 +485,11 @@ TkEventuallyRedrawMenu( register TkMenu *menuPtr, /* Information about menu to redraw. */ register TkMenuEntry *mePtr)/* Entry to redraw. NULL means redraw all the * entries in the menu. */ { - int i; + TkSizeT i; if (menuPtr->tkwin == NULL) { return; } if (mePtr != NULL) { @@ -616,11 +616,12 @@ ClientData clientData) /* Information about widget. */ { register TkMenu *menuPtr = clientData; register TkMenuEntry *mePtr; register Tk_Window tkwin = menuPtr->tkwin; - int index, strictMotif; + TkSizeT index; + int strictMotif; Tk_Font tkfont; Tk_FontMetrics menuMetrics; int width; int borderWidth; Tk_3DBorder border; @@ -805,13 +806,12 @@ /* *---------------------------------------------------------------------- * * TkPostTearoffMenu -- * - * Posts a menu on the screen. Used to post tearoff menus. On Unix, all - * menus are posted this way. Adjusts the menu's position so that it fits - * on the screen, and maps and raises the menu. + * Posts a tearoff menu on the screen. Adjusts the menu's position so + * that it fits on the screen, and maps and raises the menu. * * Results: * Returns a standard Tcl Error. * * Side effects: @@ -825,68 +825,11 @@ Tcl_Interp *interp, /* The interpreter of the menu */ TkMenu *menuPtr, /* The menu we are posting */ int x, int y) /* The root X,Y coordinates where we are * posting */ { - int vRootX, vRootY, vRootWidth, vRootHeight; - int result; - - TkActivateMenuEntry(menuPtr, -1); - TkRecomputeMenu(menuPtr); - result = TkPostCommand(menuPtr); - if (result != TCL_OK) { - return result; - } - - /* - * The post commands could have deleted the menu, which means we are dead - * and should go away. - */ - - if (menuPtr->tkwin == NULL) { - return TCL_OK; - } - - /* - * Adjust the position of the menu if necessary to keep it visible on the - * screen. There are two special tricks to make this work right: - * - * 1. If a virtual root window manager is being used then the coordinates - * are in the virtual root window of menuPtr's parent; since the menu - * uses override-redirect mode it will be in the *real* root window for - * the screen, so we have to map the coordinates from the virtual root - * (if any) to the real root. Can't get the virtual root from the menu - * itself (it will never be seen by the wm) so use its parent instead - * (it would be better to have an an option that names a window to use - * for this...). - * 2. The menu may not have been mapped yet, so its current size might be - * the default 1x1. To compute how much space it needs, use its - * requested size, not its actual size. - */ - - Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY, - &vRootWidth, &vRootHeight); - vRootWidth -= Tk_ReqWidth(menuPtr->tkwin); - if (x > vRootX + vRootWidth) { - x = vRootX + vRootWidth; - } - if (x < vRootX) { - x = vRootX; - } - vRootHeight -= Tk_ReqHeight(menuPtr->tkwin); - if (y > vRootY + vRootHeight) { - y = vRootY + vRootHeight; - } - if (y < vRootY) { - y = vRootY; - } - Tk_MoveToplevelWindow(menuPtr->tkwin, x, y); - if (!Tk_IsMapped(menuPtr->tkwin)) { - Tk_MapWindow(menuPtr->tkwin); - } - TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL); - return TCL_OK; + return TkpPostTearoffMenu(interp, menuPtr, x, y, -1); } /* *-------------------------------------------------------------- * @@ -967,12 +910,12 @@ AdjustMenuCoords(menuPtr, mePtr, &x, &y); menuPtr->postedCascade = mePtr; subary[0] = mePtr->namePtr; subary[1] = Tcl_NewStringObj("post", -1); - subary[2] = Tcl_NewIntObj(x); - subary[3] = Tcl_NewIntObj(y); + subary[2] = Tcl_NewWideIntObj(x); + subary[3] = Tcl_NewWideIntObj(y); Tcl_IncrRefCount(subary[1]); Tcl_IncrRefCount(subary[2]); Tcl_IncrRefCount(subary[3]); result = Tcl_EvalObjv(interp, 4, subary, 0); Tcl_DecrRefCount(subary[1]); Index: generic/tkMenubutton.c ================================================================== --- generic/tkMenubutton.c +++ generic/tkMenubutton.c @@ -59,102 +59,102 @@ */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1, - Tk_Offset(TkMenuButton, activeBorder), 0, + offsetof(TkMenuButton, activeBorder), 0, (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1, - Tk_Offset(TkMenuButton, activeFg), + offsetof(TkMenuButton, activeFg), 0, DEF_MENUBUTTON_ACTIVE_FG_MONO, 0}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MENUBUTTON_ANCHOR, -1, - Tk_Offset(TkMenuButton, anchor), 0, 0, 0}, + offsetof(TkMenuButton, anchor), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder), + DEF_MENUBUTTON_BG_COLOR, -1, offsetof(TkMenuButton, normalBorder), 0, DEF_MENUBUTTON_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", - DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap), + DEF_MENUBUTTON_BITMAP, -1, offsetof(TkMenuButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_MENUBUTTON_BORDER_WIDTH, -1, - Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0}, + offsetof(TkMenuButton, borderWidth), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor), + DEF_MENUBUTTON_CURSOR, -1, offsetof(TkMenuButton, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction", - DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction), + DEF_MENUBUTTON_DIRECTION, -1, offsetof(TkMenuButton, direction), 0, directionStrings, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR, - -1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK, + -1, offsetof(TkMenuButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0}, + DEF_MENUBUTTON_FONT, -1, offsetof(TkMenuButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0}, + DEF_MENUBUTTON_FG, -1, offsetof(TkMenuButton, normalFg), 0, 0, 0}, {TK_OPTION_STRING, "-height", "height", "Height", - DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString), + DEF_MENUBUTTON_HEIGHT, -1, offsetof(TkMenuButton, heightString), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0}, + -1, offsetof(TkMenuButton, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_MENUBUTTON_HIGHLIGHT, -1, - Tk_Offset(TkMenuButton, highlightColorPtr), 0, 0, 0}, + offsetof(TkMenuButton, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH, - -1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0}, + -1, offsetof(TkMenuButton, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-image", "image", "Image", - DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString), + DEF_MENUBUTTON_IMAGE, -1, offsetof(TkMenuButton, imageString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn", - DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn), + DEF_MENUBUTTON_INDICATOR, -1, offsetof(TkMenuButton, indicatorOn), 0, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_MENUBUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0}, + DEF_MENUBUTTON_JUSTIFY, -1, offsetof(TkMenuButton, justify), 0, 0, 0}, {TK_OPTION_STRING, "-menu", "menu", "Menu", - DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName), + DEF_MENUBUTTON_MENU, -1, offsetof(TkMenuButton, menuName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX), + DEF_MENUBUTTON_PADX, -1, offsetof(TkMenuButton, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY), + DEF_MENUBUTTON_PADY, -1, offsetof(TkMenuButton, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief), + DEF_MENUBUTTON_RELIEF, -1, offsetof(TkMenuButton, relief), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkMenuButton, compound), 0, + DEF_BUTTON_COMPOUND, -1, offsetof(TkMenuButton, compound), 0, compoundStrings, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state), + DEF_MENUBUTTON_STATE, -1, offsetof(TkMenuButton, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_MENUBUTTON_TAKE_FOCUS, -1, - Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0}, + offsetof(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0}, + DEF_MENUBUTTON_TEXT, -1, offsetof(TkMenuButton, text), 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_MENUBUTTON_TEXT_VARIABLE, -1, - Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0}, + offsetof(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_MENUBUTTON_UNDERLINE, -1, Tk_Offset(TkMenuButton, underline), + DEF_MENUBUTTON_UNDERLINE, -1, offsetof(TkMenuButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", - DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString), + DEF_MENUBUTTON_WIDTH, -1, offsetof(TkMenuButton, widthString), 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", - DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength), + DEF_MENUBUTTON_WRAP_LENGTH, -1, offsetof(TkMenuButton, wrapLength), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; /* @@ -306,11 +306,11 @@ Tk_CreateEventHandler(mbPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, MenuButtonEventProc, mbPtr); - if (Tk_InitOptions(interp, (char *) mbPtr, optionTable, tkwin) != TCL_OK) { + if (Tk_InitOptions(interp, mbPtr, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(mbPtr->tkwin); return TCL_ERROR; } if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) { @@ -367,21 +367,21 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "cget option"); goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) mbPtr, + objPtr = Tk_GetOptionValue(interp, mbPtr, mbPtr->optionTable, objv[2], mbPtr->tkwin); if (objPtr == NULL) { goto error; } Tcl_SetObjResult(interp, objPtr); break; case COMMAND_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr, + objPtr = Tk_GetOptionInfo(interp, mbPtr, mbPtr->optionTable, (objc == 3) ? objv[2] : NULL, mbPtr->tkwin); if (objPtr == NULL) { goto error; } @@ -522,11 +522,11 @@ if (!error) { /* * First pass: set options to new values. */ - if (Tk_SetOptions(interp, (char *) mbPtr, + if (Tk_SetOptions(interp, mbPtr, mbPtr->optionTable, objc, objv, mbPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -879,30 +879,37 @@ { register TkMenuButton *mbPtr = clientData; const char *value; unsigned len; - /* - * See ticket [5d991b82]. - */ - - if (mbPtr->textVarName == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - MenuButtonTextVarProc, clientData); - } - return NULL; - } - /* * If the variable is unset, then immediately recreate it unless the whole * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && mbPtr->textVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + mbPtr->textVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MenuButtonTextVarProc, probe); + if (probe == (ClientData)mbPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, clientData); Index: generic/tkMessage.c ================================================================== --- generic/tkMessage.c +++ generic/tkMessage.c @@ -11,12 +11,12 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" +#include "default.h" /* * A data structure of the following type is kept for each message widget * managed by this file: */ @@ -107,61 +107,61 @@ * Information used for argv parsing. */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MESSAGE_ANCHOR, - -1, Tk_Offset(Message, anchor), 0, 0, 0}, + -1, offsetof(Message, anchor), 0, 0, 0}, {TK_OPTION_INT, "-aspect", "aspect", "Aspect", DEF_MESSAGE_ASPECT, - -1, Tk_Offset(Message, aspect), 0, 0, 0}, + -1, offsetof(Message, aspect), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_MESSAGE_BG_COLOR, -1, Tk_Offset(Message, border), 0, + DEF_MESSAGE_BG_COLOR, -1, offsetof(Message, border), 0, DEF_MESSAGE_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_MESSAGE_BORDER_WIDTH, -1, - Tk_Offset(Message, borderWidth), 0, 0, 0}, + offsetof(Message, borderWidth), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_MESSAGE_CURSOR, -1, Tk_Offset(Message, cursor), + DEF_MESSAGE_CURSOR, -1, offsetof(Message, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_MESSAGE_FONT, -1, Tk_Offset(Message, tkfont), 0, 0, 0}, + DEF_MESSAGE_FONT, -1, offsetof(Message, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_MESSAGE_FG, -1, Tk_Offset(Message, fgColorPtr), 0, 0, 0}, + DEF_MESSAGE_FG, -1, offsetof(Message, fgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_MESSAGE_HIGHLIGHT_BG, -1, - Tk_Offset(Message, highlightBgColorPtr), 0, 0, 0}, + offsetof(Message, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_MESSAGE_HIGHLIGHT, -1, Tk_Offset(Message, highlightColorPtr), + DEF_MESSAGE_HIGHLIGHT, -1, offsetof(Message, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_MESSAGE_HIGHLIGHT_WIDTH, -1, - Tk_Offset(Message, highlightWidth), 0, 0, 0}, + offsetof(Message, highlightWidth), 0, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_MESSAGE_JUSTIFY, -1, Tk_Offset(Message, justify), 0, 0, 0}, + DEF_MESSAGE_JUSTIFY, -1, offsetof(Message, justify), 0, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - DEF_MESSAGE_PADX, Tk_Offset(Message, padXPtr), - Tk_Offset(Message, padX), 0, 0, 0}, + DEF_MESSAGE_PADX, offsetof(Message, padXPtr), + offsetof(Message, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - DEF_MESSAGE_PADY, Tk_Offset(Message, padYPtr), - Tk_Offset(Message, padY), 0, 0, 0}, + DEF_MESSAGE_PADY, offsetof(Message, padYPtr), + offsetof(Message, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_MESSAGE_RELIEF, -1, Tk_Offset(Message, relief), 0, 0, 0}, + DEF_MESSAGE_RELIEF, -1, offsetof(Message, relief), 0, 0, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_MESSAGE_TAKE_FOCUS, -1, Tk_Offset(Message, takeFocus), + DEF_MESSAGE_TAKE_FOCUS, -1, offsetof(Message, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", - DEF_MESSAGE_TEXT, -1, Tk_Offset(Message, string), 0, 0, 0}, + DEF_MESSAGE_TEXT, -1, offsetof(Message, string), 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_MESSAGE_TEXT_VARIABLE, -1, Tk_Offset(Message, textVarName), + DEF_MESSAGE_TEXT_VARIABLE, -1, offsetof(Message, textVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-width", "width", "Width", - DEF_MESSAGE_WIDTH, -1, Tk_Offset(Message, width), 0, 0 ,0}, + DEF_MESSAGE_WIDTH, -1, offsetof(Message, width), 0, 0 ,0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /* * Forward declarations for functions defined later in this file: @@ -240,11 +240,11 @@ */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); msgPtr = ckalloc(sizeof(Message)); - memset(msgPtr, 0, (size_t) sizeof(Message)); + memset(msgPtr, 0, sizeof(Message)); /* * Set values for those fields that don't take a 0 or NULL value. */ @@ -265,11 +265,11 @@ Tk_SetClass(msgPtr->tkwin, "Message"); Tk_SetClassProcs(msgPtr->tkwin, &messageClass, msgPtr); Tk_CreateEventHandler(msgPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, MessageEventProc, msgPtr); - if (Tk_InitOptions(interp, (char *)msgPtr, optionTable, tkwin) != TCL_OK) { + if (Tk_InitOptions(interp, msgPtr, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(msgPtr->tkwin); return TCL_ERROR; } if (ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0) != TCL_OK) { @@ -329,11 +329,11 @@ case MESSAGE_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; } else { - objPtr = Tk_GetOptionValue(interp, (char *) msgPtr, + objPtr = Tk_GetOptionValue(interp, msgPtr, msgPtr->optionTable, objv[2], msgPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, objPtr); @@ -341,11 +341,11 @@ } } break; case MESSAGE_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) msgPtr, + objPtr = Tk_GetOptionInfo(interp, msgPtr, msgPtr->optionTable, (objc == 3) ? objv[2] : NULL, msgPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; } else { @@ -453,11 +453,11 @@ Tcl_UntraceVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, msgPtr); } - if (Tk_SetOptions(interp, (char *) msgPtr, msgPtr->optionTable, objc, objv, + if (Tk_SetOptions(interp, msgPtr, msgPtr->optionTable, objc, objv, msgPtr->tkwin, &savedOptions, NULL) != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } @@ -836,30 +836,37 @@ int flags) /* Information about what happened. */ { register Message *msgPtr = clientData; const char *value; - /* - * See ticket [5d991b82]. - */ - - if (msgPtr->textVarName == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - MessageTextVarProc, clientData); - } - return NULL; - } - /* * If the variable is unset, then immediately recreate it unless the whole * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && msgPtr->textVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + msgPtr->textVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MessageTextVarProc, probe); + if (probe == (ClientData)msgPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, clientData); Index: generic/tkObj.c ================================================================== --- generic/tkObj.c +++ generic/tkObj.c @@ -45,11 +45,11 @@ * Tcl_ObjTypes that we can use as screen distances without conversion. The * "dataKey" below is used to locate the ThreadSpecificData for the current * thread. */ -typedef struct ThreadSpecificData { +typedef struct { const Tcl_ObjType *doubleTypePtr; const Tcl_ObjType *intTypePtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -71,12 +71,16 @@ */ typedef struct WindowRep { Tk_Window tkwin; /* Cached window; NULL if not found. */ TkMainInfo *mainPtr; /* MainWindow associated with tkwin. */ - long epoch; /* Value of mainPtr->deletionEpoch at last +#if TCL_MAJOR_VERSION > 8 + size_t epoch; /* Value of mainPtr->deletionEpoch at last * successful lookup. */ +#else + long epoch; +#endif } WindowRep; /* * Prototypes for functions defined later in this file: */ @@ -94,33 +98,33 @@ static int SetWindowFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * The following structure defines the implementation of the "pixel" Tcl * object, used for measuring distances. The pixel object remembers its - * initial display-independant settings. + * initial display-independent settings. */ static const Tcl_ObjType pixelObjType = { "pixel", /* name */ FreePixelInternalRep, /* freeIntRepProc */ DupPixelInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetPixelFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* * The following structure defines the implementation of the "pixel" Tcl * object, used for measuring distances. The pixel object remembers its - * initial display-independant settings. + * initial display-independent settings. */ static const Tcl_ObjType mmObjType = { "mm", /* name */ FreeMMInternalRep, /* freeIntRepProc */ DupMMInternalRep, /* dupIntRepProc */ UpdateStringOfMM, /* updateStringProc */ - SetMMFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* * The following structure defines the implementation of the "window" * Tcl object. @@ -129,11 +133,11 @@ static const Tcl_ObjType windowObjType = { "window", /* name */ FreeWindowInternalRep, /* freeIntRepProc */ DupWindowInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetWindowFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* *---------------------------------------------------------------------- * @@ -666,11 +670,11 @@ UpdateStringOfMM( register Tcl_Obj *objPtr) /* pixel obj with string rep to update. */ { MMRep *mmPtr; char buffer[TCL_DOUBLE_SPACE]; - size_t len; + TkSizeT len; mmPtr = objPtr->internalRep.twoPtrValue.ptr1; /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */ if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) { Tcl_Panic("UpdateStringOfMM: false precondition"); Index: generic/tkOldConfig.c ================================================================== --- generic/tkOldConfig.c +++ generic/tkOldConfig.c @@ -23,24 +23,28 @@ * Tk_Uid's. */ #define INIT 0x20 +#ifndef TK_CONFIG_OPTION_SPECIFIED +# define TK_CONFIG_OPTION_SPECIFIED (1 << 4) +#endif + /* * Forward declarations for functions defined later in this file: */ static int DoConfig(Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specPtr, Tk_Uid value, - int valueIsUid, char *widgRec); + int valueIsUid, void *widgRec); static Tk_ConfigSpec * FindConfigSpec(Tcl_Interp *interp, Tk_ConfigSpec *specs, const char *argvName, int needFlags, int hateFlags); static char * FormatConfigInfo(Tcl_Interp *interp, Tk_Window tkwin, - const Tk_ConfigSpec *specPtr, char *widgRec); + const Tk_ConfigSpec *specPtr, void *widgRec); static const char * FormatConfigValue(Tcl_Interp *interp, Tk_Window tkwin, - const Tk_ConfigSpec *specPtr, char *widgRec, + const Tk_ConfigSpec *specPtr, void *widgRec, char *buffer, Tcl_FreeProc **freeProcPtr); static Tk_ConfigSpec * GetCachedSpecs(Tcl_Interp *interp, const Tk_ConfigSpec *staticSpecs); static void DeleteSpecCacheTable(ClientData clientData, Tcl_Interp *interp); @@ -338,24 +342,24 @@ * X resources). */ Tk_ConfigSpec *specPtr, /* Specifier to apply. */ Tk_Uid value, /* Value to use to fill in widgRec. */ int valueIsUid, /* Non-zero means value is a Tk_Uid; zero * means it's an ordinary string. */ - char *widgRec) /* Record whose fields are to be modified. + void *widgRec) /* Record whose fields are to be modified. * Values must be properly initialized. */ { - char *ptr; + void *ptr; Tk_Uid uid; int nullValue; nullValue = 0; if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) { nullValue = 1; } do { - ptr = widgRec + specPtr->offset; + ptr = (char *)widgRec + specPtr->offset; switch (specPtr->type) { case TK_CONFIG_BOOLEAN: if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) { return TCL_ERROR; } @@ -687,11 +691,11 @@ * floating-point precision. */ Tk_Window tkwin, /* Window corresponding to widget. */ register const Tk_ConfigSpec *specPtr, /* Pointer to information describing * option. */ - char *widgRec) /* Pointer to record holding current values of + void *widgRec) /* Pointer to record holding current values of * info for widget. */ { const char *argv[6]; char *result; char buffer[200]; @@ -753,22 +757,23 @@ FormatConfigValue( Tcl_Interp *interp, /* Interpreter for use in real conversions. */ Tk_Window tkwin, /* Window corresponding to widget. */ const Tk_ConfigSpec *specPtr, /* Pointer to information describing option. * Must not point to a synonym option. */ - char *widgRec, /* Pointer to record holding current values of + void *widgRec, /* Pointer to record holding current values of * info for widget. */ char *buffer, /* Static buffer to use for small values. * Must have at least 200 bytes of storage. */ Tcl_FreeProc **freeProcPtr) /* Pointer to word to fill in with address of * function to free the result, or NULL if * result is static. */ { - const char *ptr, *result; + void *ptr; + const char *result; *freeProcPtr = NULL; - ptr = widgRec + specPtr->offset; + ptr = (char *)widgRec + specPtr->offset; result = ""; switch (specPtr->type) { case TK_CONFIG_BOOLEAN: if (*((int *) ptr) == 0) { result = "0"; Index: generic/tkOldTest.c ================================================================== --- generic/tkOldTest.c +++ generic/tkOldTest.c @@ -89,11 +89,11 @@ /* *---------------------------------------------------------------------- * * TkOldTestInit -- * - * This function performs intialization for the Tk test suite + * This function performs initialization for the Tk test suite * extensions for testing support for legacy interfaces. * * Results: * Returns a standard Tcl completion code, and leaves an error message in * the interp's result if an error occurs. Index: generic/tkOption.c ================================================================== --- generic/tkOption.c +++ generic/tkOption.c @@ -174,11 +174,11 @@ * stack corresponding to this level (used to * restore "numUsed" fields when popping out * of a level. */ } StackLevel; -typedef struct ThreadSpecificData { +typedef struct { int initialized; /* 0 means the ThreadSpecific Data structure * for the current thread needs to be * initialized. */ ElArray *stacks[NUM_STACKS]; TkWindow *cachedWindow; /* Lowest-level window currently loaded in @@ -258,11 +258,11 @@ register Element *elPtr; Element newEl; register const char *p; const char *field; int count, firstField; - ptrdiff_t length; + size_t length; #define TMP_SIZE 100 char tmp[TMP_SIZE+1]; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -309,11 +309,11 @@ } length = p - field; if (length > TMP_SIZE) { length = TMP_SIZE; } - strncpy(tmp, field, (size_t) length); + strncpy(tmp, field, length); tmp[length] = 0; newEl.nameUid = Tk_GetUid(tmp); if (isupper(UCHAR(*field))) { newEl.flags |= CLASS; } @@ -1082,11 +1082,12 @@ * TK_INTERACTIVE_PRIO. Must be between 0 and * TK_MAX_PRIO. */ { const char *realName; Tcl_Obj *buffer; - int result, bufferSize; + int result; + size_t bufferSize; Tcl_Channel chan; Tcl_DString newName; /* * Prevent file system access in a safe interpreter. @@ -1113,11 +1114,11 @@ buffer = Tcl_NewObj(); Tcl_IncrRefCount(buffer); Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8"); bufferSize = Tcl_ReadChars(chan, buffer, -1, 0); - if (bufferSize < 0) { + if (bufferSize == (size_t)-1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading file \"%s\": %s", fileName, Tcl_PosixError(interp))); Tcl_Close(NULL, chan); return TCL_ERROR; Index: generic/tkPack.c ================================================================== --- generic/tkPack.c +++ generic/tkPack.c @@ -120,12 +120,14 @@ static void ArrangePacking(ClientData clientData); static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, int objc, Tcl_Obj *const objv[]); static void DestroyPacker(void *memPtr); static Packer * GetPacker(Tk_Window tkwin); +#ifndef TK_NO_DEPRECATED static int PackAfter(Tcl_Interp *interp, Packer *prevPtr, Packer *masterPtr, int objc,Tcl_Obj *const objv[]); +#endif /* !TK_NO_DEPRECATED */ static void PackStructureProc(ClientData clientData, XEvent *eventPtr); static void Unlink(Packer *packPtr); static int XExpansion(Packer *slavePtr, int cavityWidth); static int YExpansion(Packer *slavePtr, int cavityHeight); @@ -159,14 +161,14 @@ { Tcl_Obj *padding[2]; if (halfSpace*2 == allSpace) { Tcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, -1), - Tcl_NewIntObj(halfSpace)); + Tcl_NewWideIntObj(halfSpace)); } else { - padding[0] = Tcl_NewIntObj(halfSpace); - padding[1] = Tcl_NewIntObj(allSpace - halfSpace); + padding[0] = Tcl_NewWideIntObj(halfSpace); + padding[1] = Tcl_NewWideIntObj(allSpace - halfSpace); Tcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, -1), Tcl_NewListObj(2, padding)); } } @@ -195,15 +197,18 @@ Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin = clientData; const char *argv2; static const char *const optionStrings[] = { - /* after, append, before and unpack are deprecated */ +#ifndef TK_NO_DEPRECATED "after", "append", "before", "unpack", +#endif /* !TK_NO_DEPRECATED */ "configure", "forget", "info", "propagate", "slaves", NULL }; enum options { +#ifndef TK_NO_DEPRECATED PACK_AFTER, PACK_APPEND, PACK_BEFORE, PACK_UNPACK, +#endif /* !TK_NO_DEPRECATED */ PACK_CONFIGURE, PACK_FORGET, PACK_INFO, PACK_PROPAGATE, PACK_SLAVES }; int index; if (objc >= 2) { const char *string = Tcl_GetString(objv[1]); @@ -217,24 +222,27 @@ return TCL_ERROR; } if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, sizeof(char *), "option", 0, &index) != TCL_OK) { +#ifndef TK_NO_DEPRECATED /* * Call it again without the deprecated ones to get a proper error * message. This works well since there can't be any ambiguity between * deprecated and new options. */ Tcl_ResetResult(interp); Tcl_GetIndexFromObjStruct(interp, objv[1], &optionStrings[4], sizeof(char *), "option", 0, &index); +#endif /* TK_NO_DEPRECATED */ return TCL_ERROR; } argv2 = Tcl_GetString(objv[2]); switch ((enum options) index) { +#ifndef TK_NO_DEPRECATED case PACK_AFTER: { Packer *prevPtr; Tk_Window tkwin2; if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) { @@ -295,10 +303,11 @@ } } } return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3); } +#endif /* !TK_NO_DEPRECATED */ case PACK_CONFIGURE: if (argv2[0] != '.') { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad argument \"%s\": must be name of window", argv2)); Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW_PATH", NULL); @@ -456,10 +465,11 @@ TkNewWindowObj(slavePtr->tkwin)); } Tcl_SetObjResult(interp, resultObj); break; } +#ifndef TK_NO_DEPRECATED case PACK_UNPACK: { Tk_Window tkwin2; Packer *packPtr; if (objc != 3) { @@ -479,10 +489,11 @@ Unlink(packPtr); Tk_UnmapWindow(packPtr->tkwin); } break; } +#endif /* !TK_NO_DEPRECATED */ } return TCL_OK; } @@ -597,12 +608,13 @@ int maxWidth, maxHeight, tmp; masterPtr->flags &= ~REQUESTED_REPACK; /* - * If the master has no slaves anymore, then don't do anything at all: - * just leave the master's size as-is. + * If the master has no slaves anymore, then leave the master's size as-is. + * Otherwise there is no way to "relinquish" control over the master + * so another geometry manager can take over. */ if (masterPtr->slavePtr == NULL) { return; } @@ -1085,10 +1097,11 @@ * in the future. * *------------------------------------------------------------------------ */ +#ifndef TK_NO_DEPRECATED static int PackAfter( Tcl_Interp *interp, /* Interpreter for error reporting. */ Packer *prevPtr, /* Pack windows in argv just after this * window; NULL means pack as first child of @@ -1167,12 +1180,12 @@ packPtr->iPadX = packPtr->iPadY = 0; packPtr->flags &= ~(FILLX|FILLY|EXPAND); packPtr->flags |= OLD_STYLE; for (index = 0 ; index < optionCount; index++) { Tcl_Obj *curOptPtr = options[index]; - const char *curOpt = Tcl_GetString(curOptPtr); - size_t length = curOptPtr->length; + TkSizeT length; + const char *curOpt = TkGetStringFromObj(curOptPtr, &length); c = curOpt[0]; if ((c == 't') && (strncmp(curOpt, "top", length)) == 0) { @@ -1225,11 +1238,11 @@ packPtr->padY /= 2; packPtr->padTop /= 2; packPtr->iPadY = 0; index++; } else if ((c == 'f') && (length > 1) - && (strncmp(curOpt, "frame", (size_t) length) == 0)) { + && (strncmp(curOpt, "frame", length) == 0)) { if (optionCount < (index+2)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "wrong # args: \"frame\"" " option must be followed by anchor point", -1)); Tcl_SetErrorCode(interp, "TK", "OLDPACK", "BAD_PARAMETER", @@ -1305,10 +1318,11 @@ masterPtr->flags |= REQUESTED_REPACK; Tcl_DoWhenIdle(ArrangePacking, masterPtr); } return TCL_OK; } +#endif /* !TK_NO_DEPRECATED */ /* *---------------------------------------------------------------------- * * Unlink -- @@ -1358,15 +1372,19 @@ packPtr->masterPtr = NULL; /* * If we have emptied this master from slaves it means we are no longer * handling it and should mark it as free. + * + * Send the event "NoManagedChild" to the master to inform it about there + * being no managed children inside it. */ if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) { TkFreeGeometryMaster(masterPtr->tkwin, "pack"); masterPtr->flags &= ~ALLOCED_MASTER; + TkSendVirtualEvent(masterPtr->tkwin, "NoManagedChild", NULL); } } /* @@ -1454,11 +1472,11 @@ } if (packPtr->tkwin != NULL) { TkDisplay *dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr; Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable, - (char *) packPtr->tkwin)); + packPtr->tkwin)); } if (packPtr->flags & REQUESTED_REPACK) { Tcl_CancelIdleCall(ArrangePacking, packPtr); } @@ -1520,10 +1538,11 @@ * "option value" pairs. Caller must make sure * that there is at least one window name. */ { Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr; Tk_Window other, slave, parent, ancestor; + TkWindow *master; int i, j, numWindows, tmp, positionGiven; const char *string; static const char *const optionStrings[] = { "-after", "-anchor", "-before", "-expand", "-fill", "-in", "-ipadx", "-ipady", "-padx", "-pady", "-side", NULL }; @@ -1795,10 +1814,28 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't pack %s inside itself", Tcl_GetString(objv[j]))); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "SELF", NULL); return TCL_ERROR; } + + /* + * Check for management loops. + */ + + for (master = (TkWindow *)masterPtr->tkwin; master != NULL; + master = (TkWindow *)TkGetGeomMaster(master)) { + if (master == (TkWindow *)slave) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't put %s inside %s, would cause management loop", + Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); + Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); + return TCL_ERROR; + } + } + if (masterPtr->tkwin != Tk_Parent(slave)) { + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin; + } /* * Unpack the slave if it's currently packed, then position it after * prevPtr. */ Index: generic/tkPanedWindow.c ================================================================== --- generic/tkPanedWindow.c +++ generic/tkPanedWindow.c @@ -11,12 +11,12 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" +#include "default.h" /* * Flag values for "sticky"ness. The 16 combinations subsume the packer's * notion of anchor and fill. * @@ -234,11 +234,11 @@ static void AdjustForSticky(int sticky, int cavityWidth, int cavityHeight, int *xPtr, int *yPtr, int *slaveWidthPtr, int *slaveHeightPtr); static void MoveSash(PanedWindow *pwPtr, int sash, int diff); static int ObjectIsEmpty(Tcl_Obj *objPtr); -static char * ComputeSlotAddress(char *recordPtr, int offset); +static void * ComputeSlotAddress(void *recordPtr, size_t offset); static int PanedWindowIdentifyCoords(PanedWindow *pwPtr, Tcl_Interp *interp, int x, int y); /* * Sashes are between panes only, so there is one less sash than slaves @@ -273,96 +273,96 @@ 0 }; static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_PANEDWINDOW_BG_COLOR, -1, Tk_Offset(PanedWindow, background), 0, + DEF_PANEDWINDOW_BG_COLOR, -1, offsetof(PanedWindow, background), 0, DEF_PANEDWINDOW_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_PANEDWINDOW_BORDERWIDTH, -1, Tk_Offset(PanedWindow, borderWidth), + DEF_PANEDWINDOW_BORDERWIDTH, -1, offsetof(PanedWindow, borderWidth), 0, 0, GEOMETRY}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_PANEDWINDOW_CURSOR, -1, Tk_Offset(PanedWindow, cursor), + DEF_PANEDWINDOW_CURSOR, -1, offsetof(PanedWindow, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-handlepad", "handlePad", "HandlePad", - DEF_PANEDWINDOW_HANDLEPAD, -1, Tk_Offset(PanedWindow, handlePad), + DEF_PANEDWINDOW_HANDLEPAD, -1, offsetof(PanedWindow, handlePad), 0, 0, GEOMETRY}, {TK_OPTION_PIXELS, "-handlesize", "handleSize", "HandleSize", - DEF_PANEDWINDOW_HANDLESIZE, Tk_Offset(PanedWindow, handleSizePtr), - Tk_Offset(PanedWindow, handleSize), 0, 0, GEOMETRY}, + DEF_PANEDWINDOW_HANDLESIZE, offsetof(PanedWindow, handleSizePtr), + offsetof(PanedWindow, handleSize), 0, 0, GEOMETRY}, {TK_OPTION_PIXELS, "-height", "height", "Height", - DEF_PANEDWINDOW_HEIGHT, Tk_Offset(PanedWindow, heightPtr), - Tk_Offset(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY}, + DEF_PANEDWINDOW_HEIGHT, offsetof(PanedWindow, heightPtr), + offsetof(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY}, {TK_OPTION_BOOLEAN, "-opaqueresize", "opaqueResize", "OpaqueResize", DEF_PANEDWINDOW_OPAQUERESIZE, -1, - Tk_Offset(PanedWindow, resizeOpaque), 0, 0, 0}, + offsetof(PanedWindow, resizeOpaque), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", - DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient), + DEF_PANEDWINDOW_ORIENT, -1, offsetof(PanedWindow, orient), 0, orientStrings, GEOMETRY}, {TK_OPTION_BORDER, "-proxybackground", "proxyBackground", "ProxyBackground", - 0, -1, Tk_Offset(PanedWindow, proxyBackground), TK_OPTION_NULL_OK, + 0, -1, offsetof(PanedWindow, proxyBackground), TK_OPTION_NULL_OK, (ClientData) DEF_PANEDWINDOW_BG_MONO}, {TK_OPTION_PIXELS, "-proxyborderwidth", "proxyBorderWidth", "ProxyBorderWidth", - DEF_PANEDWINDOW_PROXYBORDER, Tk_Offset(PanedWindow, proxyBorderWidthPtr), - Tk_Offset(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY}, + DEF_PANEDWINDOW_PROXYBORDER, offsetof(PanedWindow, proxyBorderWidthPtr), + offsetof(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY}, {TK_OPTION_RELIEF, "-proxyrelief", "proxyRelief", "Relief", - 0, -1, Tk_Offset(PanedWindow, proxyRelief), + 0, -1, offsetof(PanedWindow, proxyRelief), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0}, + DEF_PANEDWINDOW_RELIEF, -1, offsetof(PanedWindow, relief), 0, 0, 0}, {TK_OPTION_CURSOR, "-sashcursor", "sashCursor", "Cursor", - DEF_PANEDWINDOW_SASHCURSOR, -1, Tk_Offset(PanedWindow, sashCursor), + DEF_PANEDWINDOW_SASHCURSOR, -1, offsetof(PanedWindow, sashCursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-sashpad", "sashPad", "SashPad", - DEF_PANEDWINDOW_SASHPAD, -1, Tk_Offset(PanedWindow, sashPad), + DEF_PANEDWINDOW_SASHPAD, -1, offsetof(PanedWindow, sashPad), 0, 0, GEOMETRY}, {TK_OPTION_RELIEF, "-sashrelief", "sashRelief", "Relief", - DEF_PANEDWINDOW_SASHRELIEF, -1, Tk_Offset(PanedWindow, sashRelief), + DEF_PANEDWINDOW_SASHRELIEF, -1, offsetof(PanedWindow, sashRelief), 0, 0, 0}, {TK_OPTION_PIXELS, "-sashwidth", "sashWidth", "Width", - DEF_PANEDWINDOW_SASHWIDTH, Tk_Offset(PanedWindow, sashWidthPtr), - Tk_Offset(PanedWindow, sashWidth), 0, 0, GEOMETRY}, + DEF_PANEDWINDOW_SASHWIDTH, offsetof(PanedWindow, sashWidthPtr), + offsetof(PanedWindow, sashWidth), 0, 0, GEOMETRY}, {TK_OPTION_BOOLEAN, "-showhandle", "showHandle", "ShowHandle", - DEF_PANEDWINDOW_SHOWHANDLE, -1, Tk_Offset(PanedWindow, showHandle), + DEF_PANEDWINDOW_SHOWHANDLE, -1, offsetof(PanedWindow, showHandle), 0, 0, GEOMETRY}, {TK_OPTION_PIXELS, "-width", "width", "Width", - DEF_PANEDWINDOW_WIDTH, Tk_Offset(PanedWindow, widthPtr), - Tk_Offset(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY}, + DEF_PANEDWINDOW_WIDTH, offsetof(PanedWindow, widthPtr), + offsetof(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; static const Tk_OptionSpec slaveOptionSpecs[] = { {TK_OPTION_WINDOW, "-after", NULL, NULL, - DEF_PANEDWINDOW_PANE_AFTER, -1, Tk_Offset(Slave, after), + DEF_PANEDWINDOW_PANE_AFTER, -1, offsetof(Slave, after), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_WINDOW, "-before", NULL, NULL, - DEF_PANEDWINDOW_PANE_BEFORE, -1, Tk_Offset(Slave, before), + DEF_PANEDWINDOW_PANE_BEFORE, -1, offsetof(Slave, before), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-height", NULL, NULL, - DEF_PANEDWINDOW_PANE_HEIGHT, Tk_Offset(Slave, heightPtr), - Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0}, + DEF_PANEDWINDOW_PANE_HEIGHT, offsetof(Slave, heightPtr), + offsetof(Slave, height), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide", - DEF_PANEDWINDOW_PANE_HIDE, -1, Tk_Offset(Slave, hide), 0,0,GEOMETRY}, + DEF_PANEDWINDOW_PANE_HIDE, -1, offsetof(Slave, hide), 0,0,GEOMETRY}, {TK_OPTION_PIXELS, "-minsize", NULL, NULL, - DEF_PANEDWINDOW_PANE_MINSIZE, -1, Tk_Offset(Slave, minSize), 0, 0, 0}, + DEF_PANEDWINDOW_PANE_MINSIZE, -1, offsetof(Slave, minSize), 0, 0, 0}, {TK_OPTION_PIXELS, "-padx", NULL, NULL, - DEF_PANEDWINDOW_PANE_PADX, -1, Tk_Offset(Slave, padx), 0, 0, 0}, + DEF_PANEDWINDOW_PANE_PADX, -1, offsetof(Slave, padx), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", NULL, NULL, - DEF_PANEDWINDOW_PANE_PADY, -1, Tk_Offset(Slave, pady), 0, 0, 0}, + DEF_PANEDWINDOW_PANE_PADY, -1, offsetof(Slave, pady), 0, 0, 0}, {TK_OPTION_CUSTOM, "-sticky", NULL, NULL, - DEF_PANEDWINDOW_PANE_STICKY, -1, Tk_Offset(Slave, sticky), 0, + DEF_PANEDWINDOW_PANE_STICKY, -1, offsetof(Slave, sticky), 0, &stickyOption, 0}, {TK_OPTION_STRING_TABLE, "-stretch", "stretch", "Stretch", - DEF_PANEDWINDOW_PANE_STRETCH, -1, Tk_Offset(Slave, stretch), 0, + DEF_PANEDWINDOW_PANE_STRETCH, -1, offsetof(Slave, stretch), 0, (ClientData) stretchStrings, 0}, {TK_OPTION_PIXELS, "-width", NULL, NULL, - DEF_PANEDWINDOW_PANE_WIDTH, Tk_Offset(Slave, widthPtr), - Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0}, + DEF_PANEDWINDOW_PANE_WIDTH, offsetof(Slave, widthPtr), + offsetof(Slave, width), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /* *-------------------------------------------------------------- @@ -457,11 +457,11 @@ * otherwise Tk might free it while we still need it. */ Tcl_Preserve(pwPtr->tkwin); - if (Tk_InitOptions(interp, (char *) pwPtr, pwOpts->pwOptions, + if (Tk_InitOptions(interp, pwPtr, pwOpts->pwOptions, tkwin) != TCL_OK) { Tk_DestroyWindow(pwPtr->tkwin); return TCL_ERROR; } @@ -576,11 +576,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; break; } - resultObj = Tk_GetOptionValue(interp, (char *) pwPtr, + resultObj = Tk_GetOptionValue(interp, pwPtr, pwPtr->optionTable, objv[2], pwPtr->tkwin); if (resultObj == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObj); @@ -588,11 +588,11 @@ break; case PW_CONFIGURE: resultObj = NULL; if (objc <= 3) { - resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr, + resultObj = Tk_GetOptionInfo(interp, pwPtr, pwPtr->optionTable, (objc == 3) ? objv[2] : NULL, pwPtr->tkwin); if (resultObj == NULL) { result = TCL_ERROR; } else { @@ -667,11 +667,11 @@ } resultObj = NULL; for (i = 0; i < pwPtr->numSlaves; i++) { if (pwPtr->slaves[i]->tkwin == tkwin) { resultObj = Tk_GetOptionValue(interp, - (char *) pwPtr->slaves[i], pwPtr->slaveOpts, + pwPtr->slaves[i], pwPtr->slaveOpts, objv[3], tkwin); } } if (resultObj == NULL) { if (i == pwPtr->numSlaves) { @@ -707,11 +707,11 @@ break; } for (i = 0; i < pwPtr->numSlaves; i++) { if (pwPtr->slaves[i]->tkwin == tkwin) { resultObj = Tk_GetOptionInfo(interp, - (char *) pwPtr->slaves[i], pwPtr->slaveOpts, + pwPtr->slaves[i], pwPtr->slaveOpts, (objc == 4) ? objv[3] : NULL, pwPtr->tkwin); if (resultObj == NULL) { result = TCL_ERROR; } else { @@ -846,11 +846,11 @@ * return from Tk_SetOptions once, here, so we can save a little bit of * extra testing in the for loop below. */ memset((void *)&options, 0, sizeof(Slave)); - if (Tk_SetOptions(interp, (char *) &options, pwPtr->slaveOpts, + if (Tk_SetOptions(interp, &options, pwPtr->slaveOpts, objc - firstOptionArg, objv + firstOptionArg, pwPtr->tkwin, NULL, NULL) != TCL_OK) { return TCL_ERROR; } @@ -923,11 +923,11 @@ pwPtr->tkwin); found = 0; for (j = 0; j < pwPtr->numSlaves; j++) { if (pwPtr->slaves[j] != NULL && pwPtr->slaves[j]->tkwin == tkwin) { - Tk_SetOptions(interp, (char *) pwPtr->slaves[j], + Tk_SetOptions(interp, pwPtr->slaves[j], pwPtr->slaveOpts, objc - firstOptionArg, objv + firstOptionArg, pwPtr->tkwin, NULL, NULL); if (pwPtr->slaves[j]->minSize < 0) { pwPtr->slaves[j]->minSize = 0; } @@ -970,13 +970,13 @@ * out with their "natural" dimensions. */ slavePtr = ckalloc(sizeof(Slave)); memset(slavePtr, 0, sizeof(Slave)); - Tk_InitOptions(interp, (char *)slavePtr, pwPtr->slaveOpts, + Tk_InitOptions(interp, slavePtr, pwPtr->slaveOpts, pwPtr->tkwin); - Tk_SetOptions(interp, (char *)slavePtr, pwPtr->slaveOpts, + Tk_SetOptions(interp, slavePtr, pwPtr->slaveOpts, objc - firstOptionArg, objv + firstOptionArg, pwPtr->tkwin, NULL, NULL); slavePtr->tkwin = tkwin; slavePtr->masterPtr = pwPtr; doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width; @@ -1009,11 +1009,11 @@ * Allocate the new slaves array, then copy the slaves into it, in order. */ i = sizeof(Slave *) * (pwPtr->numSlaves + numNewSlaves); newSlaves = ckalloc(i); - memset(newSlaves, 0, (size_t) i); + memset(newSlaves, 0, i); if (index == -1) { /* * If none of the existing slaves have to be moved, just copy the old * and append the new. */ @@ -1130,12 +1130,12 @@ Tcl_SetErrorCode(interp, "TK", "VALUE", "SASH_INDEX", NULL); return TCL_ERROR; } slavePtr = pwPtr->slaves[sash]; - coords[0] = Tcl_NewIntObj(slavePtr->sashx); - coords[1] = Tcl_NewIntObj(slavePtr->sashy); + coords[0] = Tcl_NewWideIntObj(slavePtr->sashx); + coords[1] = Tcl_NewWideIntObj(slavePtr->sashy); Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords)); break; case SASH_MARK: if (objc != 6 && objc != 4) { @@ -1164,12 +1164,12 @@ } pwPtr->slaves[sash]->markx = x; pwPtr->slaves[sash]->marky = y; } else { - coords[0] = Tcl_NewIntObj(pwPtr->slaves[sash]->markx); - coords[1] = Tcl_NewIntObj(pwPtr->slaves[sash]->marky); + coords[0] = Tcl_NewWideIntObj(pwPtr->slaves[sash]->markx); + coords[1] = Tcl_NewWideIntObj(pwPtr->slaves[sash]->marky); Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords)); } break; case SASH_DRAGTO: @@ -1247,11 +1247,11 @@ Tcl_Obj *const objv[]) /* Argument values. */ { Tk_SavedOptions savedOptions; int typemask = 0; - if (Tk_SetOptions(interp, (char *) pwPtr, pwPtr->optionTable, objc, objv, + if (Tk_SetOptions(interp, pwPtr, pwPtr->optionTable, objc, objv, pwPtr->tkwin, &savedOptions, &typemask) != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } @@ -1482,14 +1482,14 @@ * Set up boilerplate geometry values for sashes (width, height, common * coordinates). */ if (horizontal) { - sashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderWidth(tkwin)); + sashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderLeft(tkwin)); sashWidth = pwPtr->sashWidth; } else { - sashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderWidth(tkwin)); + sashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderLeft(tkwin)); sashHeight = pwPtr->sashWidth; } /* * Draw the sashes. @@ -1752,11 +1752,11 @@ /* * First pass; compute sizes */ paneDynSize = paneDynMinSize = 0; - internalBW = Tk_InternalBorderWidth(pwPtr->tkwin); + internalBW = Tk_InternalBorderLeft(pwPtr->tkwin); pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW); pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW); x = y = internalBW; stretchReserve = (horizontal ? pwWidth : pwHeight); @@ -2198,11 +2198,11 @@ Slave *slavePtr; const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL); pwPtr->flags |= REQUESTED_RELAYOUT; - x = y = internalBw = Tk_InternalBorderWidth(pwPtr->tkwin); + x = y = internalBw = Tk_InternalBorderLeft(pwPtr->tkwin); reqWidth = reqHeight = 0; /* * Sashes and handles share space on the display. To simplify processing * below, precompute the x and y offsets of the handles and sashes within @@ -2453,11 +2453,12 @@ * internal value is to be stored. */ char *oldInternalPtr, /* Pointer to storage for the old value. */ int flags) /* Flags for the option, set Tk_SetOptions. */ { int sticky = 0; - char c, *internalPtr; + char c; + void *internalPtr; const char *string; internalPtr = ComputeSlotAddress(recordPtr, internalOffset); if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) { @@ -2874,12 +2875,12 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - coords[0] = Tcl_NewIntObj(pwPtr->proxyx); - coords[1] = Tcl_NewIntObj(pwPtr->proxyy); + coords[0] = Tcl_NewWideIntObj(pwPtr->proxyx); + coords[1] = Tcl_NewWideIntObj(pwPtr->proxyy); Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords)); break; case PROXY_FORGET: if (objc != 3) { @@ -2904,35 +2905,35 @@ if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) { return TCL_ERROR; } - internalBW = Tk_InternalBorderWidth(pwPtr->tkwin); + internalBW = Tk_InternalBorderLeft(pwPtr->tkwin); if (pwPtr->orient == ORIENT_HORIZONTAL) { if (x < 0) { x = 0; } pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW); if (x > pwWidth) { x = pwWidth; } - y = Tk_InternalBorderWidth(pwPtr->tkwin); + y = Tk_InternalBorderLeft(pwPtr->tkwin); sashWidth = pwPtr->sashWidth; sashHeight = Tk_Height(pwPtr->tkwin) - - (2 * Tk_InternalBorderWidth(pwPtr->tkwin)); + (2 * Tk_InternalBorderLeft(pwPtr->tkwin)); } else { if (y < 0) { y = 0; } pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW); if (y > pwHeight) { y = pwHeight; } - x = Tk_InternalBorderWidth(pwPtr->tkwin); + x = Tk_InternalBorderLeft(pwPtr->tkwin); sashHeight = pwPtr->sashWidth; sashWidth = Tk_Width(pwPtr->tkwin) - - (2 * Tk_InternalBorderWidth(pwPtr->tkwin)); + (2 * Tk_InternalBorderLeft(pwPtr->tkwin)); } if (sashWidth < 1) { sashWidth = 1; } @@ -3017,17 +3018,17 @@ * None. * *---------------------------------------------------------------------- */ -static char * +static void * ComputeSlotAddress( - char *recordPtr, /* Pointer to the start of a record. */ - int offset) /* Offset of a slot within that record; may be < 0. */ + void *recordPtr, /* Pointer to the start of a record. */ + size_t offset) /* Offset of a slot within that record; may be -1. */ { - if (offset >= 0) { - return recordPtr + offset; + if (offset != (size_t)-1) { + return (char *)recordPtr + offset; } else { return NULL; } } @@ -3064,11 +3065,11 @@ if (Tk_IsMapped(pwPtr->tkwin)) { sashHeight = Tk_Height(pwPtr->tkwin); } else { sashHeight = Tk_ReqHeight(pwPtr->tkwin); } - sashHeight -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); + sashHeight -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin); if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) { sashWidth = pwPtr->handleSize; lpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2; rpad = pwPtr->handleSize - lpad; lpad += pwPtr->sashPad; @@ -3092,11 +3093,11 @@ if (Tk_IsMapped(pwPtr->tkwin)) { sashWidth = Tk_Width(pwPtr->tkwin); } else { sashWidth = Tk_ReqWidth(pwPtr->tkwin); } - sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); + sashWidth -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin); lpad = rpad = 0; } GetFirstLastVisiblePane(pwPtr, &first, &last); isHandle = 0; @@ -3139,11 +3140,11 @@ */ if (found != -1) { Tcl_Obj *list[2]; - list[0] = Tcl_NewIntObj(found); + list[0] = Tcl_NewWideIntObj(found); list[1] = Tcl_NewStringObj((isHandle ? "handle" : "sash"), -1); Tcl_SetObjResult(interp, Tcl_NewListObj(2, list)); } return TCL_OK; } ADDED generic/tkPkgConfig.c Index: generic/tkPkgConfig.c ================================================================== --- /dev/null +++ generic/tkPkgConfig.c @@ -0,0 +1,166 @@ +/* + * tkPkgConfig.c -- + * + * This file contains the configuration information to embed into the tcl + * binary library. + * + * Copyright (c) 2002 Andreas Kupries + * Copyright (c) 2017 Stuart Cassoff + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +/* Note, the definitions in this module are influenced by the following C + * preprocessor macros: + * + * OSCMa = shortcut for "old style configuration macro activates" + * NSCMdt = shortcut for "new style configuration macro declares that" + * + * - TCL_THREADS OSCMa compilation as threaded. + * - TCL_MEM_DEBUG OSCMa memory debugging. + * + * - TCL_CFG_DO64BIT NSCMdt tk is compiled for a 64bit system. + * - NDEBUG NSCMdt tk is compiled with symbol info off. + * - TCL_CFG_OPTIMIZED NSCMdt tk is compiled with cc optimizations on + * - TCL_CFG_PROFILED NSCMdt tk is compiled with profiling info. + * + * - _WIN32 || __CYGWIN__ The value for the fontsytem key will be + * MAC_OSX_TK chosen based on these macros/defines. + * HAVE_XFT NSCMdt xft font support was requested. + * + * - CFG_RUNTIME_* Paths to various stuff at runtime. + * - CFG_INSTALL_* Paths to various stuff at installation time. + * + * - TCL_CFGVAL_ENCODING string containing the encoding used for the + * configuration values. + */ + +#include "tkInt.h" + + +#ifndef TCL_CFGVAL_ENCODING +#define TCL_CFGVAL_ENCODING "ascii" +#endif + +/* + * Use C preprocessor statements to define the various values for the embedded + * configuration information. + */ + +#ifdef TCL_THREADS +# define CFG_THREADED "1" +#else +# define CFG_THREADED "0" +#endif + +#ifdef TCL_MEM_DEBUG +# define CFG_MEMDEBUG "1" +#else +# define CFG_MEMDEBUG "0" +#endif + +#ifdef TCL_CFG_DO64BIT +# define CFG_64 "1" +#else +# define CFG_64 "0" +#endif + +#ifndef NDEBUG +# define CFG_DEBUG "1" +#else +# define CFG_DEBUG "0" +#endif + +#ifdef TCL_CFG_OPTIMIZED +# define CFG_OPTIMIZED "1" +#else +# define CFG_OPTIMIZED "0" +#endif + +#ifdef TCL_CFG_PROFILED +# define CFG_PROFILED "1" +#else +# define CFG_PROFILED "0" +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +# define CFG_FONTSYSTEM "gdi" +#elif defined(MAC_OSX_TK) +# define CFG_FONTSYSTEM "cocoa" +#elif defined(HAVE_XFT) +# define CFG_FONTSYSTEM "xft" +#else +# define CFG_FONTSYSTEM "x11" +#endif + +static Tcl_Config const cfg[] = { + {"debug", CFG_DEBUG}, + {"threaded", CFG_THREADED}, + {"profiled", CFG_PROFILED}, + {"64bit", CFG_64}, + {"optimized", CFG_OPTIMIZED}, + {"mem_debug", CFG_MEMDEBUG}, + {"fontsystem", CFG_FONTSYSTEM}, + + /* Runtime paths to various stuff */ + +#ifdef CFG_RUNTIME_LIBDIR + {"libdir,runtime", CFG_RUNTIME_LIBDIR}, +#endif +#ifdef CFG_RUNTIME_BINDIR + {"bindir,runtime", CFG_RUNTIME_BINDIR}, +#endif +#ifdef CFG_RUNTIME_SCRDIR + {"scriptdir,runtime", CFG_RUNTIME_SCRDIR}, +#endif +#ifdef CFG_RUNTIME_INCDIR + {"includedir,runtime", CFG_RUNTIME_INCDIR}, +#endif +#ifdef CFG_RUNTIME_DOCDIR + {"docdir,runtime", CFG_RUNTIME_DOCDIR}, +#endif +#ifdef CFG_RUNTIME_DEMODIR + {"demodir,runtime", CFG_RUNTIME_DEMODIR}, +#endif + + /* Installation paths to various stuff */ + +#ifdef CFG_INSTALL_LIBDIR + {"libdir,install", CFG_INSTALL_LIBDIR}, +#endif +#ifdef CFG_INSTALL_BINDIR + {"bindir,install", CFG_INSTALL_BINDIR}, +#endif +#ifdef CFG_INSTALL_SCRDIR + {"scriptdir,install", CFG_INSTALL_SCRDIR}, +#endif +#ifdef CFG_INSTALL_INCDIR + {"includedir,install", CFG_INSTALL_INCDIR}, +#endif +#ifdef CFG_INSTALL_DOCDIR + {"docdir,install", CFG_INSTALL_DOCDIR}, +#endif +#ifdef CFG_INSTALL_DEMODIR + {"demodir,install", CFG_INSTALL_DEMODIR}, +#endif + + /* Last entry, closes the array */ + {NULL, NULL} +}; + +void +TkInitEmbeddedConfigurationInformation( + Tcl_Interp *interp) /* Interpreter the configuration command is + * registered in. */ +{ + Tcl_RegisterConfig(interp, "tk", cfg, TCL_CFGVAL_ENCODING); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ Index: generic/tkPlace.c ================================================================== --- generic/tkPlace.c +++ generic/tkPlace.c @@ -80,33 +80,33 @@ #define IN_MASK 1 static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_ANCHOR, "-anchor", NULL, NULL, "nw", -1, - Tk_Offset(Slave, anchor), 0, 0, 0}, + offsetof(Slave, anchor), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-bordermode", NULL, NULL, "inside", -1, - Tk_Offset(Slave, borderMode), 0, borderModeStrings, 0}, - {TK_OPTION_PIXELS, "-height", NULL, NULL, "", Tk_Offset(Slave, heightPtr), - Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_WINDOW, "-in", NULL, NULL, "", -1, Tk_Offset(Slave, inTkwin), + offsetof(Slave, borderMode), 0, borderModeStrings, 0}, + {TK_OPTION_PIXELS, "-height", NULL, NULL, "", offsetof(Slave, heightPtr), + offsetof(Slave, height), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_WINDOW, "-in", NULL, NULL, "", -1, offsetof(Slave, inTkwin), 0, 0, IN_MASK}, {TK_OPTION_DOUBLE, "-relheight", NULL, NULL, "", - Tk_Offset(Slave, relHeightPtr), Tk_Offset(Slave, relHeight), + offsetof(Slave, relHeightPtr), offsetof(Slave, relHeight), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-relwidth", NULL, NULL, "", - Tk_Offset(Slave, relWidthPtr), Tk_Offset(Slave, relWidth), + offsetof(Slave, relWidthPtr), offsetof(Slave, relWidth), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-relx", NULL, NULL, "0", -1, - Tk_Offset(Slave, relX), 0, 0, 0}, + offsetof(Slave, relX), 0, 0, 0}, {TK_OPTION_DOUBLE, "-rely", NULL, NULL, "0", -1, - Tk_Offset(Slave, relY), 0, 0, 0}, - {TK_OPTION_PIXELS, "-width", NULL, NULL, "", Tk_Offset(Slave, widthPtr), - Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_PIXELS, "-x", NULL, NULL, "0", Tk_Offset(Slave, xPtr), - Tk_Offset(Slave, x), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_PIXELS, "-y", NULL, NULL, "0", Tk_Offset(Slave, yPtr), - Tk_Offset(Slave, y), TK_OPTION_NULL_OK, 0, 0}, + offsetof(Slave, relY), 0, 0, 0}, + {TK_OPTION_PIXELS, "-width", NULL, NULL, "", offsetof(Slave, widthPtr), + offsetof(Slave, width), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_PIXELS, "-x", NULL, NULL, "0", offsetof(Slave, xPtr), + offsetof(Slave, x), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_PIXELS, "-y", NULL, NULL, "0", offsetof(Slave, yPtr), + offsetof(Slave, y), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* * Flag definitions for Slave structures: @@ -288,11 +288,11 @@ slavePtr = FindSlave(tkwin); if (slavePtr == NULL) { return TCL_OK; } - objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, optionTable, + objPtr = Tk_GetOptionInfo(interp, slavePtr, optionTable, (objc == 4) ? objv[3] : NULL, tkwin); if (objPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); @@ -313,11 +313,11 @@ (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } UnlinkSlave(slavePtr); Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, - (char *) tkwin)); + tkwin)); Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, slavePtr); Tk_ManageGeometry(tkwin, NULL, NULL); Tk_UnmapWindow(tkwin); FreeSlave(slavePtr); @@ -453,11 +453,11 @@ Tk_Window tkwin) /* Token for desired slave. */ { register Tcl_HashEntry *hPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin); + hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, tkwin); if (hPtr == NULL) { return NULL; } return Tcl_GetHashValue(hPtr); } @@ -576,11 +576,11 @@ Tk_Window tkwin) /* Token for desired master. */ { register Tcl_HashEntry *hPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, (char *) tkwin); + hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, tkwin); if (hPtr == NULL) { return NULL; } return Tcl_GetHashValue(hPtr); } @@ -614,11 +614,12 @@ { register Master *masterPtr; Tk_SavedOptions savedOptions; int mask; Slave *slavePtr; - Tk_Window masterWin = (Tk_Window) NULL; + Tk_Window masterWin = NULL; + TkWindow *master; if (Tk_TopWinHierarchy(tkwin)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use placer on top-level window \"%s\"; use " "wm command instead", Tk_PathName(tkwin))); @@ -626,11 +627,11 @@ return TCL_ERROR; } slavePtr = CreateSlave(tkwin, table); - if (Tk_SetOptions(interp, (char *) slavePtr, table, objc, objv, + if (Tk_SetOptions(interp, slavePtr, table, objc, objv, slavePtr->tkwin, &savedOptions, &mask) != TCL_OK) { goto error; } /* @@ -692,10 +693,29 @@ "can't place %s relative to itself", Tk_PathName(slavePtr->tkwin))); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); goto error; } + + /* + * Check for management loops. + */ + + for (master = (TkWindow *)tkwin; master != NULL; + master = (TkWindow *)TkGetGeomMaster(master)) { + if (master == (TkWindow *)slavePtr->tkwin) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't put %s inside %s, would cause management loop", + Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin))); + Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); + goto error; + } + } + if (tkwin != Tk_Parent(slavePtr->tkwin)) { + ((TkWindow *)slavePtr->tkwin)->maintainerPtr = (TkWindow *)tkwin; + } + if ((slavePtr->masterPtr != NULL) && (slavePtr->masterPtr->tkwin == tkwin)) { /* * Re-using same old master. Nothing to do. */ @@ -1082,11 +1102,11 @@ slavePtr->masterPtr = NULL; nextPtr = slavePtr->nextPtr; slavePtr->nextPtr = NULL; } Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->masterTable, - (char *) masterPtr->tkwin)); + masterPtr->tkwin)); if (masterPtr->flags & PARENT_RECONFIG_PENDING) { Tcl_CancelIdleCall(RecomputePlacement, masterPtr); } masterPtr->tkwin = NULL; if (masterPtr->abortPtr != NULL) { @@ -1149,11 +1169,11 @@ if (eventPtr->type == DestroyNotify) { if (slavePtr->masterPtr != NULL) { UnlinkSlave(slavePtr); } Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, - (char *) slavePtr->tkwin)); + slavePtr->tkwin)); FreeSlave(slavePtr); } } /* @@ -1183,10 +1203,16 @@ Slave *slavePtr = clientData; Master *masterPtr; if ((slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) && (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) { + /* + * Send a ConfigureNotify to indicate that the size change + * request was rejected. + */ + + TkDoConfigureNotify((TkWindow *)(slavePtr->tkwin)); return; } masterPtr = slavePtr->masterPtr; if (masterPtr == NULL) { return; @@ -1228,11 +1254,11 @@ Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } Tk_UnmapWindow(tkwin); UnlinkSlave(slavePtr); Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, - (char *) tkwin)); + tkwin)); Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, slavePtr); FreeSlave(slavePtr); } Index: generic/tkPointer.c ================================================================== --- generic/tkPointer.c +++ generic/tkPointer.c @@ -21,23 +21,11 @@ #if defined(MAC_OSX_TK) #include "tkMacOSXInt.h" #define Cursor XCursor #endif -/* - * Mask that selects any of the state bits corresponding to buttons, plus - * masks that select individual buttons' bits: - */ - -#define ALL_BUTTONS \ - (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask) -static const unsigned int buttonMasks[] = { - Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask -}; -#define ButtonMask(b) (buttonMasks[(b)-Button1]) - -typedef struct ThreadSpecificData { +typedef struct { TkWindow *grabWinPtr; /* Window that defines the top of the grab * tree in a global grab. */ int lastState; /* Last known state flags. */ XPoint lastPos; /* Last reported mouse position. */ TkWindow *lastWinPtr; /* Last reported mouse window. */ @@ -264,12 +252,12 @@ /* * Generate ButtonPress/ButtonRelease events based on the differences * between the current button state and the last known button state. */ - for (b = Button1; b <= Button5; b++) { - mask = ButtonMask(b); + for (b = Button1; b <= Button9; b++) { + mask = TkGetButtonMask(b); if (changes & mask) { if (state & mask) { type = ButtonPress; /* Index: generic/tkRectOval.c ================================================================== --- generic/tkRectOval.c +++ generic/tkRectOval.c @@ -58,66 +58,66 @@ TkPixelParseProc, TkPixelPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.activeDash), + NULL, offsetof(RectOvalItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-activefill", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.activeStipple), + NULL, offsetof(RectOvalItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, - "0.0", Tk_Offset(RectOvalItem, outline.activeWidth), + "0.0", offsetof(RectOvalItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.dash), + NULL, offsetof(RectOvalItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, - "0", Tk_Offset(RectOvalItem, outline.offset), + "0", offsetof(RectOvalItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.disabledDash), + NULL, offsetof(RectOvalItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.disabledColor), + NULL, offsetof(RectOvalItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.disabledStipple), + NULL, offsetof(RectOvalItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_PIXELS, "-disabledwidth", NULL, NULL, - "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth), + "0.0", offsetof(RectOvalItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_COLOR, "-fill", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, fillColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, - "0,0", Tk_Offset(RectOvalItem, tsoffset), + "0,0", offsetof(RectOvalItem, tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_COLOR, "-outline", NULL, NULL, - "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL}, + "black", offsetof(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL, - "0,0", Tk_Offset(RectOvalItem, outline.tsoffset), + "0,0", offsetof(RectOvalItem, outline.tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-state", NULL, NULL, - NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption}, + NULL, offsetof(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption}, {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, - NULL, Tk_Offset(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK, NULL}, + NULL, offsetof(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_CUSTOM, "-width", NULL, NULL, - "1.0", Tk_Offset(RectOvalItem, outline.width), + "1.0", offsetof(RectOvalItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* @@ -146,10 +146,12 @@ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); static int RectToArea(Tk_Canvas canvas, Tk_Item *itemPtr, double *areaPtr); static double RectToPoint(Tk_Canvas canvas, Tk_Item *itemPtr, double *pointPtr); +static void RotateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, double angleRad); static void ScaleRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, double scaleX, double scaleY); static void TranslateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY); @@ -178,11 +180,12 @@ NULL, /* icursorProc */ NULL, /* selectionProc */ NULL, /* insertProc */ NULL, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateRectOval, /* rotateProc */ + 0, NULL, NULL }; Tk_ItemType tkOvalType = { "oval", /* name */ sizeof(RectOvalItem), /* itemSize */ @@ -202,11 +205,12 @@ NULL, /* cursorProc */ NULL, /* selectionProc */ NULL, /* insertProc */ NULL, /* dTextProc */ NULL, /* nextPtr */ - NULL, 0, NULL, NULL + RotateRectOval, /* rotateProc */ + 0, NULL, NULL }; /* *-------------------------------------------------------------- * @@ -513,12 +517,11 @@ #ifdef MAC_OSX_TK /* * Mac OS X CG drawing needs access to the outline linewidth even for * fills (as linewidth controls antialiasing). */ - - gcValues.line_width = rectOvalPtr->outline.gc != None ? + gcValues.line_width = rectOvalPtr->outline.gc != NULL ? rectOvalPtr->outline.gc->line_width : 0; mask |= GCLineWidth; #endif newGC = Tk_GetGC(tkwin, mask, &gcValues); } @@ -1280,10 +1283,61 @@ return -1; } } return result; } + +/* + *-------------------------------------------------------------- + * + * RotateRectOval -- + * + * This function is invoked to rotate a rectangle or oval item's + * coordinates. It works by rotating a computed point in the centre of + * the bounding box, NOT by rotating the corners of the bounding box. + * + * Results: + * None. + * + * Side effects: + * The position of the rectangle or oval is rotated by angleRad about + * (originX, originY), and the bounding box is updated in the generic + * part of the item structure. + * + *-------------------------------------------------------------- + */ + +static void +RotateRectOval( + Tk_Canvas canvas, /* Canvas containing rectangle. */ + Tk_Item *itemPtr, /* Rectangle to be scaled. */ + double originX, double originY, + /* Origin about which to rotate rect. */ + double angleRad) /* Amount to scale in X direction. */ +{ + RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; + double newX, newY, oldX, oldY; + + /* + * Compute the centre of the box, then rotate that about the origin. + */ + + newX = oldX = (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2]) / 2.0; + newY = oldY = (rectOvalPtr->bbox[1] + rectOvalPtr->bbox[3]) / 2.0; + TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad), + &newX, &newY); + + /* + * Apply the translation to the box. + */ + + rectOvalPtr->bbox[0] += newX - oldX; + rectOvalPtr->bbox[1] += newY - oldY; + rectOvalPtr->bbox[2] += newX - oldX; + rectOvalPtr->bbox[3] += newY - oldY; + ComputeRectOvalBbox(canvas, rectOvalPtr); +} /* *-------------------------------------------------------------- * * ScaleRectOval -- Index: generic/tkScale.c ================================================================== --- generic/tkScale.c +++ generic/tkScale.c @@ -15,13 +15,13 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" #include "tkScale.h" +#include "default.h" #if defined(_WIN32) #define snprintf _snprintf #endif @@ -43,100 +43,100 @@ "active", "disabled", "normal", NULL }; static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder), + DEF_SCALE_ACTIVE_BG_COLOR, -1, offsetof(TkScale, activeBorder), 0, DEF_SCALE_ACTIVE_BG_MONO, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder), + DEF_SCALE_BG_COLOR, -1, offsetof(TkScale, bgBorder), 0, DEF_SCALE_BG_MONO, 0}, {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement", - DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement), + DEF_SCALE_BIG_INCREMENT, -1, offsetof(TkScale, bigIncrement), 0, 0, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth), + DEF_SCALE_BORDER_WIDTH, -1, offsetof(TkScale, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", - DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command), + DEF_SCALE_COMMAND, -1, offsetof(TkScale, command), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor), + DEF_SCALE_CURSOR, -1, offsetof(TkScale, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-digits", "digits", "Digits", - DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits), + DEF_SCALE_DIGITS, -1, offsetof(TkScale, digits), 0, 0, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0}, + DEF_SCALE_FONT, -1, offsetof(TkScale, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0, + DEF_SCALE_FG_COLOR, -1, offsetof(TkScale, textColorPtr), 0, (ClientData) DEF_SCALE_FG_MONO, 0}, {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1, - Tk_Offset(TkScale, fromValue), 0, 0, 0}, + offsetof(TkScale, fromValue), 0, 0, 0}, {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkScale, highlightBorder), + -1, offsetof(TkScale, highlightBorder), 0, DEF_SCALE_HIGHLIGHT_BG_MONO, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr), + DEF_SCALE_HIGHLIGHT, -1, offsetof(TkScale, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1, - Tk_Offset(TkScale, highlightWidth), 0, 0, 0}, + offsetof(TkScale, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-label", "label", "Label", - DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label), + DEF_SCALE_LABEL, -1, offsetof(TkScale, label), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-length", "length", "Length", - DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0}, + DEF_SCALE_LENGTH, -1, offsetof(TkScale, length), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", - DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient), + DEF_SCALE_ORIENT, -1, offsetof(TkScale, orient), 0, orientStrings, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0}, + DEF_SCALE_RELIEF, -1, offsetof(TkScale, relief), 0, 0, 0}, {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay", - DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay), + DEF_SCALE_REPEAT_DELAY, -1, offsetof(TkScale, repeatDelay), 0, 0, 0}, {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval", - DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval), + DEF_SCALE_REPEAT_INTERVAL, -1, offsetof(TkScale, repeatInterval), 0, 0, 0}, {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution", - DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution), + DEF_SCALE_RESOLUTION, -1, offsetof(TkScale, resolution), 0, 0, 0}, {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue", - DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue), + DEF_SCALE_SHOW_VALUE, -1, offsetof(TkScale, showValue), 0, 0, 0}, {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength", - DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength), + DEF_SCALE_SLIDER_LENGTH, -1, offsetof(TkScale, sliderLength), 0, 0, 0}, {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief", - DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief), + DEF_SCALE_SLIDER_RELIEF, -1, offsetof(TkScale, sliderRelief), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state), + DEF_SCALE_STATE, -1, offsetof(TkScale, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1, + DEF_SCALE_TAKE_FOCUS, offsetof(TkScale, takeFocusPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval", - DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval), + DEF_SCALE_TICK_INTERVAL, -1, offsetof(TkScale, tickInterval), 0, 0, 0}, {TK_OPTION_DOUBLE, "-to", "to", "To", - DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0}, + DEF_SCALE_TO, -1, offsetof(TkScale, toValue), 0, 0, 0}, {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background", - DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr), + DEF_SCALE_TROUGH_COLOR, -1, offsetof(TkScale, troughColorPtr), 0, DEF_SCALE_TROUGH_MONO, 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", - DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1, + DEF_SCALE_VARIABLE, offsetof(TkScale, varNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-width", "width", "Width", - DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0}, + DEF_SCALE_WIDTH, -1, offsetof(TkScale, width), 0, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* * The following tables define the scale widget commands and map the indexes @@ -155,15 +155,17 @@ /* * Forward declarations for procedures defined later in this file: */ -static void ComputeFormat(TkScale *scalePtr); +static void ComputeFormat(TkScale *scalePtr, int forTicks); static void ComputeScaleGeometry(TkScale *scalePtr); static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr, int objc, Tcl_Obj *const objv[]); static void DestroyScale(char *memPtr); +static double MaxTickRoundingError(TkScale *scalePtr, + double tickResolution); static void ScaleCmdDeletedProc(ClientData clientData); static void ScaleEventProc(ClientData clientData, XEvent *eventPtr); static char * ScaleVarProc(ClientData clientData, Tcl_Interp *interp, const char *name1, @@ -180,13 +182,54 @@ */ static const Tk_ClassProcs scaleClass = { sizeof(Tk_ClassProcs), /* size */ ScaleWorldChanged, /* worldChangedProc */ - NULL, /* createProc */ - NULL /* modalProc */ + NULL, /* createProc */ + NULL /* modalProc */ }; + +/* + *-------------------------------------------------------------- + * + * ScaleDigit, ScaleMax, ScaleMin, ScaleRound -- + * + * Simple math helper functions, designed to be automatically inlined by + * the compiler most of the time. + * + *-------------------------------------------------------------- + */ + +static inline int +ScaleDigit( + double value) +{ + return (int) floor(log10(fabs(value))); +} + +static inline double +ScaleMax( + double a, + double b) +{ + return (a > b) ? a : b; +} + +static inline double +ScaleMin( + double a, + double b) +{ + return (a < b) ? a : b; +} + +static inline int +ScaleRound( + double value) +{ + return (int) floor(value + 0.5); +} /* *-------------------------------------------------------------- * * Tk_ScaleObjCmd -- @@ -298,11 +341,11 @@ Tk_SetClassProcs(scalePtr->tkwin, &scaleClass, scalePtr); Tk_CreateEventHandler(scalePtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, ScaleEventProc, scalePtr); - if ((Tk_InitOptions(interp, (char *) scalePtr, optionTable, tkwin) + if ((Tk_InitOptions(interp, scalePtr, optionTable, tkwin) != TCL_OK) || (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) { Tk_DestroyWindow(scalePtr->tkwin); return TCL_ERROR; } @@ -361,20 +404,20 @@ case COMMAND_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "cget option"); goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) scalePtr, + objPtr = Tk_GetOptionValue(interp, scalePtr, scalePtr->optionTable, objv[2], scalePtr->tkwin); if (objPtr == NULL) { goto error; } Tcl_SetObjResult(interp, objPtr); break; case COMMAND_CONFIGURE: if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr, + objPtr = Tk_GetOptionInfo(interp, scalePtr, scalePtr->optionTable, (objc == 3) ? objv[2] : NULL, scalePtr->tkwin); if (objPtr == NULL) { goto error; } @@ -406,12 +449,12 @@ } else { x = TkScaleValueToPixel(scalePtr, value); y = scalePtr->horizTroughY + scalePtr->width/2 + scalePtr->borderWidth; } - coords[0] = Tcl_NewIntObj(x); - coords[1] = Tcl_NewIntObj(y); + coords[0] = Tcl_NewWideIntObj(x); + coords[1] = Tcl_NewWideIntObj(y); Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords)); break; } case COMMAND_GET: { double value; @@ -428,11 +471,11 @@ (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { goto error; } value = TkScalePixelToValue(scalePtr, x, y); } - Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->format, value)); + Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->valueFormat, value)); break; } case COMMAND_IDENTIFY: { int x, y; const char *zone = ""; @@ -580,11 +623,11 @@ if (!error) { /* * First pass: set options to new values. */ - if (Tk_SetOptions(interp, (char *) scalePtr, + if (Tk_SetOptions(interp, scalePtr, scalePtr->optionTable, objc, objv, scalePtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -609,23 +652,23 @@ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL, TCL_GLOBAL_ONLY); if ((valuePtr != NULL) && (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) { - scalePtr->value = TkRoundToResolution(scalePtr, value); + scalePtr->value = TkRoundValueToResolution(scalePtr, value); } } /* * Several options need special processing, such as parsing the * orientation and creating GCs. */ - scalePtr->fromValue = TkRoundToResolution(scalePtr, + scalePtr->fromValue = TkRoundValueToResolution(scalePtr, scalePtr->fromValue); - scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue); - scalePtr->tickInterval = TkRoundToResolution(scalePtr, + scalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue); + scalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr, scalePtr->tickInterval); /* * Make sure that the tick interval has the right sign so that * addition moves from fromValue to toValue. @@ -634,13 +677,14 @@ if ((scalePtr->tickInterval < 0) ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) { scalePtr->tickInterval = -scalePtr->tickInterval; } - ComputeFormat(scalePtr); + ComputeFormat(scalePtr, 0); + ComputeFormat(scalePtr, 1); - scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0; + scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0; Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder); if (scalePtr->highlightWidth < 0) { scalePtr->highlightWidth = 0; @@ -756,32 +800,82 @@ ComputeScaleGeometry(scalePtr); TkEventuallyRedrawScale(scalePtr, REDRAW_ALL); } + + /* + *---------------------------------------------------------------------- + * + * MaxTickRoundingError -- + * + * Given the separation between values that can be displayed on ticks, + * this calculates the maximum magnitude of error for the displayed + * value. Tries to be clever by working out the increment in error + * between ticks rather than testing all of them, so may overestimate + * error if it is greater than 0.25 x the value separation. + * + * Results: + * Maximum error magnitude of tick numbers. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static double +MaxTickRoundingError( + TkScale *scalePtr, /* Information about scale widget. */ + double tickResolution) /* Separation between displayable values. */ +{ + double tickPosn, firstTickError, lastTickError, intervalError; + int tickCount; + + /* + * Compute the error for each tick-related measure. + */ + + tickPosn = scalePtr->fromValue / tickResolution; + firstTickError = tickPosn - ScaleRound(tickPosn); + + tickPosn = scalePtr->tickInterval / tickResolution; + intervalError = tickPosn - ScaleRound(tickPosn); + + tickCount = (int) ((scalePtr->toValue - scalePtr->fromValue) / + scalePtr->tickInterval); /* not including first */ + lastTickError = ScaleMin(0.5, + fabs(firstTickError + tickCount * intervalError)); + + /* + * Compute the maximum cumulative rounding error. + */ + + return ScaleMax(fabs(firstTickError), lastTickError) * tickResolution; +} /* *---------------------------------------------------------------------- * * ComputeFormat -- * - * This procedure is invoked to recompute the "format" field of a scale's - * widget record, which determines how the value of the scale is - * converted to a string. + * This procedure is invoked to recompute the "valueFormat" or + * "tickFormat" field of a scale's widget record, which determines how + * the value of the scale or one of its ticks is converted to a string. * * Results: * None. * - * Side effects: - * The format field of scalePtr is modified. + * Side effects: The valueFormat or tickFormat field of scalePtr is modified. * *---------------------------------------------------------------------- */ static void ComputeFormat( - TkScale *scalePtr) /* Information about scale widget. */ + TkScale *scalePtr, /* Information about scale widget. */ + int forTicks) /* Do for ticks rather than value */ { double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; int eDigits, fDigits; @@ -796,52 +890,77 @@ maxValue = x; } if (maxValue == 0) { maxValue = 1; } - mostSigDigit = (int) floor(log10(maxValue)); - - /* - * If the number of significant digits wasn't specified explicitly, - * compute it. It's the difference between the most significant digit - * needed to represent any number on the scale and the most significant - * digit of the smallest difference between numbers on the scale. In other - * words, display enough digits so that at least one digit will be - * different between any two adjacent positions of the scale. - */ - - numDigits = scalePtr->digits; - if (numDigits > TCL_MAX_PREC) { - numDigits = 0; - } - if (numDigits <= 0) { - if (scalePtr->resolution > 0) { - /* - * A resolution was specified for the scale, so just use it. - */ - - leastSigDigit = (int) floor(log10(scalePtr->resolution)); - } else { - /* - * No resolution was specified, so compute the difference in value - * between adjacent pixels and use it for the least significant - * digit. - */ - - x = fabs(scalePtr->fromValue - scalePtr->toValue); - if (scalePtr->length > 0) { - x /= scalePtr->length; - } - if (x > 0){ - leastSigDigit = (int) floor(log10(x)); - } else { - leastSigDigit = 0; - } - } - numDigits = mostSigDigit - leastSigDigit + 1; - if (numDigits < 1) { - numDigits = 1; + mostSigDigit = ScaleDigit(maxValue); + + if (forTicks) { + /* + * Display only enough digits to ensure adjacent ticks have different + * values. + */ + + if (scalePtr->tickInterval != 0) { + leastSigDigit = ScaleDigit(scalePtr->tickInterval); + + /* + * Now add more digits until max error is less than + * TICK_VALUES_DISPLAY_ACCURACY intervals + */ + + while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit)) + > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) { + --leastSigDigit; + } + numDigits = 1 + mostSigDigit - leastSigDigit; + } else { + numDigits = 1; + } + } else { + /* + * If the number of significant digits wasn't specified explicitly, + * compute it. It's the difference between the most significant digit + * needed to represent any number on the scale and the most + * significant digit of the smallest difference between numbers on the + * scale. In other words, display enough digits so that at least one + * digit will be different between any two adjacent positions of the + * scale. + */ + + numDigits = scalePtr->digits; + if (numDigits > TCL_MAX_PREC) { + numDigits = 0; + } + if (numDigits <= 0) { + if (scalePtr->resolution > 0) { + /* + * A resolution was specified for the scale, so just use it. + */ + + leastSigDigit = ScaleDigit(scalePtr->resolution); + } else { + /* + * No resolution was specified, so compute the difference in + * value between adjacent pixels and use it for the least + * significant digit. + */ + + x = fabs(scalePtr->fromValue - scalePtr->toValue); + if (scalePtr->length > 0) { + x /= scalePtr->length; + } + if (x > 0) { + leastSigDigit = ScaleDigit(x); + } else { + leastSigDigit = 0; + } + } + numDigits = mostSigDigit - leastSigDigit + 1; + if (numDigits < 1) { + numDigits = 1; + } } } /* * Compute the number of characters required using "e" format and "f" @@ -861,14 +980,23 @@ fDigits++; /* Decimal point. */ } if (mostSigDigit < 0) { fDigits++; /* Zero to left of decimal point. */ } - if (fDigits <= eDigits) { - sprintf(scalePtr->format, "%%.%df", afterDecimal); + + if (forTicks) { + if (fDigits <= eDigits) { + sprintf(scalePtr->tickFormat, "%%.%df", afterDecimal); + } else { + sprintf(scalePtr->tickFormat, "%%.%de", numDigits - 1); + } } else { - sprintf(scalePtr->format, "%%.%de", numDigits-1); + if (fDigits <= eDigits) { + sprintf(scalePtr->valueFormat, "%%.%df", afterDecimal); + } else { + sprintf(scalePtr->valueFormat, "%%.%de", numDigits - 1); + } } } /* *---------------------------------------------------------------------- @@ -892,11 +1020,11 @@ static void ComputeScaleGeometry( register TkScale *scalePtr) /* Information about widget. */ { char valueString[TCL_DOUBLE_SPACE]; - int tmp, valuePixels, x, y, extraSpace; + int tmp, valuePixels, tickPixels, x, y, extraSpace; Tk_FontMetrics fm; Tk_GetFontMetrics(scalePtr->tkfont, &fm); scalePtr->fontHeight = fm.linespace + SPACING; @@ -938,38 +1066,57 @@ * 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, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->fromValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->toValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1); if (valuePixels < tmp) { valuePixels = tmp; } + + /* + * Now do the same thing for the tick values + */ + + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->fromValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + tickPixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); + + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->toValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1); + if (tickPixels < tmp) { + tickPixels = tmp; + } /* * Assign x-locations to the elements of the scale, working from left to * right. */ x = scalePtr->inset; if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) { - scalePtr->vertTickRightX = x + SPACING + valuePixels; + scalePtr->vertTickRightX = x + SPACING + tickPixels; scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels + fm.ascent/2; x = scalePtr->vertValueRightX + SPACING; } else if (scalePtr->tickInterval != 0) { - scalePtr->vertTickRightX = x + SPACING + valuePixels; + scalePtr->vertTickRightX = x + SPACING + tickPixels; scalePtr->vertValueRightX = scalePtr->vertTickRightX; x = scalePtr->vertTickRightX + SPACING; } else if (scalePtr->showValue) { scalePtr->vertTickRightX = x; scalePtr->vertValueRightX = x + SPACING + valuePixels; @@ -1117,14 +1264,18 @@ } /* *-------------------------------------------------------------- * - * TkRoundToResolution -- + * TkRoundValueToResolution, TkRoundIntervalToResolution -- * * Round a given floating-point value to the nearest multiple of the * scale's resolution. + * TkRoundValueToResolution rounds an absolute value based on the from + * value as a reference. + * TkRoundIntervalToResolution rounds a relative value without + * reference, i.e. it rounds an interval. * * Results: * The return value is the rounded result. * * Side effects: @@ -1132,11 +1283,20 @@ * *-------------------------------------------------------------- */ double -TkRoundToResolution( +TkRoundValueToResolution( + TkScale *scalePtr, /* Information about scale widget. */ + double value) /* Value to round. */ +{ + return TkRoundIntervalToResolution(scalePtr, value - scalePtr->fromValue) + + scalePtr->fromValue; +} + +double +TkRoundIntervalToResolution( TkScale *scalePtr, /* Information about scale widget. */ double value) /* Value to round. */ { double rem, rounded, tick; @@ -1145,17 +1305,17 @@ } tick = floor(value/scalePtr->resolution); rounded = scalePtr->resolution * tick; rem = value - rounded; if (rem < 0) { - if (rem <= -scalePtr->resolution/2) { - rounded = (tick - 1.0) * scalePtr->resolution; - } + if (rem <= -scalePtr->resolution/2) { + rounded = (tick - 1.0) * scalePtr->resolution; + } } else { - if (rem >= scalePtr->resolution/2) { - rounded = (tick + 1.0) * scalePtr->resolution; - } + if (rem >= scalePtr->resolution/2) { + rounded = (tick + 1.0) * scalePtr->resolution; + } } return rounded; } /* @@ -1190,30 +1350,37 @@ const char *resultStr; double value; Tcl_Obj *valuePtr; int result; - /* - * See ticket [5d991b82]. - */ - - if (scalePtr->varNamePtr == NULL) { - if (!(flags & TCL_INTERP_DESTROYED)) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - ScaleVarProc, clientData); - } - return NULL; - } - /* * If the variable is unset, then immediately recreate it unless the whole * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && scalePtr->varNamePtr) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + Tcl_GetString(scalePtr->varNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ScaleVarProc, probe); + if (probe == (ClientData)scalePtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * varNamePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr), NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, clientData); scalePtr->flags |= NEVER_SET; TkScaleSetValue(scalePtr, scalePtr->value, 1, 0); @@ -1236,11 +1403,11 @@ result = Tcl_GetDoubleFromObj(interp, valuePtr, &value); if (result != TCL_OK) { resultStr = "can't assign non-numeric value to scale variable"; ScaleSetVariable(scalePtr); } else { - scalePtr->value = TkRoundToResolution(scalePtr, value); + scalePtr->value = TkRoundValueToResolution(scalePtr, value); /* * This code is a bit tricky because it sets the scale's value before * calling TkScaleSetValue. This way, TkScaleSetValue won't bother to * set the variable again or to invoke the -command. However, it also @@ -1280,11 +1447,11 @@ int setVar, /* Non-zero means reflect new value through to * associated variable, if any. */ int invokeCommand) /* Non-zero means invoked -command option to * notify of new value, 0 means don't. */ { - value = TkRoundToResolution(scalePtr, value); + value = TkRoundValueToResolution(scalePtr, value); if ((value < scalePtr->fromValue) ^ (scalePtr->toValue < scalePtr->fromValue)) { value = scalePtr->fromValue; } if ((value > scalePtr->toValue) @@ -1335,11 +1502,11 @@ register TkScale *scalePtr) /* Info about widget. */ { if (scalePtr->varNamePtr != NULL) { char string[TCL_DOUBLE_SPACE]; - if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; } scalePtr->flags |= SETTING_VAR; Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL, @@ -1400,11 +1567,11 @@ if (value > 1) { value = 1; } value = scalePtr->fromValue + value * (scalePtr->toValue - scalePtr->fromValue); - return TkRoundToResolution(scalePtr, value); + return TkRoundValueToResolution(scalePtr, value); } /* *---------------------------------------------------------------------- * @@ -1437,12 +1604,12 @@ ? Tk_Height(scalePtr->tkwin) : Tk_Width(scalePtr->tkwin)) - scalePtr->sliderLength - 2*scalePtr->inset - 2*scalePtr->borderWidth; if (valueRange == 0) { y = 0; } else { - y = (int) ((value - scalePtr->fromValue) * pixelRange - / valueRange + 0.5); + y = ScaleRound((value - scalePtr->fromValue) * pixelRange + / valueRange); if (y < 0) { y = 0; } else if (y > pixelRange) { y = pixelRange; } Index: generic/tkScale.h ================================================================== --- generic/tkScale.h +++ generic/tkScale.h @@ -71,12 +71,14 @@ * multiple of this value. */ int digits; /* Number of significant digits to print in * values. 0 means we get to choose the number * based on resolution and/or the range of the * scale. */ - char format[16]; /* Sprintf conversion specifier computed from + char valueFormat[16]; /* Sprintf conversion specifier computed from * digits and other information. */ + char tickFormat[16]; /* Sprintf conversion specifier computed from + * tick interval. */ double bigIncrement; /* Amount to use for large increments to scale * value. (0 means we pick a value). */ char *command; /* Command prefix to use when invoking Tcl * commands because the scale value changed. * NULL means don't invoke commands. */ @@ -83,11 +85,11 @@ int repeatDelay; /* How long to wait before auto-repeating on * scrolling actions (in ms). */ int repeatInterval; /* Interval between autorepeats (in ms). */ char *label; /* Label to display above or to right of * scale; NULL means don't display a label. */ - int labelLength; /* Number of non-NULL chars. in label. */ + TkSizeT labelLength; /* Number of non-NULL chars. in label. */ enum state state; /* Values are active, normal, or disabled. * Value of scale cannot be changed when * disabled. */ /* @@ -212,16 +214,25 @@ * window. */ #define SPACING 2 +/* + * The tick values are all displayed with the same number of decimal places. + * This number of decimal places is such that the displayed values are all + * accurate to within the following proportion of a tick interval. + */ + +#define TICK_VALUES_DISPLAY_ACCURACY 0.2 + /* * Declaration of procedures used in the implementation of the scale widget. */ MODULE_SCOPE void TkEventuallyRedrawScale(TkScale *scalePtr, int what); -MODULE_SCOPE double TkRoundToResolution(TkScale *scalePtr, double value); +MODULE_SCOPE double TkRoundValueToResolution(TkScale *scalePtr, double value); +MODULE_SCOPE double TkRoundIntervalToResolution(TkScale *scalePtr, double value); MODULE_SCOPE TkScale * TkpCreateScale(Tk_Window tkwin); MODULE_SCOPE void TkpDestroyScale(TkScale *scalePtr); MODULE_SCOPE void TkpDisplayScale(ClientData clientData); MODULE_SCOPE int TkpScaleElement(TkScale *scalePtr, int x, int y); MODULE_SCOPE void TkScaleSetValue(TkScale *scalePtr, double value, Index: generic/tkScrollbar.c ================================================================== --- generic/tkScrollbar.c +++ generic/tkScrollbar.c @@ -31,66 +31,66 @@ * Information used for argv parsing. */ static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_SCROLLBAR_ACTIVE_BG_COLOR, Tk_Offset(TkScrollbar, activeBorder), + DEF_SCROLLBAR_ACTIVE_BG_COLOR, offsetof(TkScrollbar, activeBorder), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_SCROLLBAR_ACTIVE_BG_MONO, Tk_Offset(TkScrollbar, activeBorder), + DEF_SCROLLBAR_ACTIVE_BG_MONO, offsetof(TkScrollbar, activeBorder), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_RELIEF, "-activerelief", "activeRelief", "Relief", - DEF_SCROLLBAR_ACTIVE_RELIEF, Tk_Offset(TkScrollbar, activeRelief), 0, NULL}, + DEF_SCROLLBAR_ACTIVE_RELIEF, offsetof(TkScrollbar, activeRelief), 0, NULL}, {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_SCROLLBAR_BG_COLOR, Tk_Offset(TkScrollbar, bgBorder), + DEF_SCROLLBAR_BG_COLOR, offsetof(TkScrollbar, bgBorder), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_SCROLLBAR_BG_MONO, Tk_Offset(TkScrollbar, bgBorder), + DEF_SCROLLBAR_BG_MONO, offsetof(TkScrollbar, bgBorder), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL}, {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL}, {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_SCROLLBAR_BORDER_WIDTH, Tk_Offset(TkScrollbar, borderWidth), 0, NULL}, + DEF_SCROLLBAR_BORDER_WIDTH, offsetof(TkScrollbar, borderWidth), 0, NULL}, {TK_CONFIG_STRING, "-command", "command", "Command", - DEF_SCROLLBAR_COMMAND, Tk_Offset(TkScrollbar, command), + DEF_SCROLLBAR_COMMAND, offsetof(TkScrollbar, command), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", - DEF_SCROLLBAR_CURSOR, Tk_Offset(TkScrollbar, cursor), TK_CONFIG_NULL_OK, NULL}, + DEF_SCROLLBAR_CURSOR, offsetof(TkScrollbar, cursor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_PIXELS, "-elementborderwidth", "elementBorderWidth", "BorderWidth", DEF_SCROLLBAR_EL_BORDER_WIDTH, - Tk_Offset(TkScrollbar, elementBorderWidth), 0, NULL}, + offsetof(TkScrollbar, elementBorderWidth), 0, NULL}, {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_SCROLLBAR_HIGHLIGHT_BG, - Tk_Offset(TkScrollbar, highlightBgColorPtr), 0, NULL}, + offsetof(TkScrollbar, highlightBgColorPtr), 0, NULL}, {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_SCROLLBAR_HIGHLIGHT, - Tk_Offset(TkScrollbar, highlightColorPtr), 0, NULL}, + offsetof(TkScrollbar, highlightColorPtr), 0, NULL}, {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", - DEF_SCROLLBAR_HIGHLIGHT_WIDTH, Tk_Offset(TkScrollbar, highlightWidth), 0, NULL}, + DEF_SCROLLBAR_HIGHLIGHT_WIDTH, offsetof(TkScrollbar, highlightWidth), 0, NULL}, {TK_CONFIG_BOOLEAN, "-jump", "jump", "Jump", - DEF_SCROLLBAR_JUMP, Tk_Offset(TkScrollbar, jump), 0, NULL}, + DEF_SCROLLBAR_JUMP, offsetof(TkScrollbar, jump), 0, NULL}, {TK_CONFIG_CUSTOM, "-orient", "orient", "Orient", - DEF_SCROLLBAR_ORIENT, Tk_Offset(TkScrollbar, vertical), 0, + DEF_SCROLLBAR_ORIENT, offsetof(TkScrollbar, vertical), 0, &orientOption}, {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", - DEF_SCROLLBAR_RELIEF, Tk_Offset(TkScrollbar, relief), 0, NULL}, + DEF_SCROLLBAR_RELIEF, offsetof(TkScrollbar, relief), 0, NULL}, {TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay", - DEF_SCROLLBAR_REPEAT_DELAY, Tk_Offset(TkScrollbar, repeatDelay), 0, NULL}, + DEF_SCROLLBAR_REPEAT_DELAY, offsetof(TkScrollbar, repeatDelay), 0, NULL}, {TK_CONFIG_INT, "-repeatinterval", "repeatInterval", "RepeatInterval", - DEF_SCROLLBAR_REPEAT_INTERVAL, Tk_Offset(TkScrollbar, repeatInterval), 0, NULL}, + DEF_SCROLLBAR_REPEAT_INTERVAL, offsetof(TkScrollbar, repeatInterval), 0, NULL}, {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_SCROLLBAR_TAKE_FOCUS, Tk_Offset(TkScrollbar, takeFocus), + DEF_SCROLLBAR_TAKE_FOCUS, offsetof(TkScrollbar, takeFocus), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background", - DEF_SCROLLBAR_TROUGH_COLOR, Tk_Offset(TkScrollbar, troughColorPtr), + DEF_SCROLLBAR_TROUGH_COLOR, offsetof(TkScrollbar, troughColorPtr), TK_CONFIG_COLOR_ONLY, NULL}, {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background", - DEF_SCROLLBAR_TROUGH_MONO, Tk_Offset(TkScrollbar, troughColorPtr), + DEF_SCROLLBAR_TROUGH_MONO, offsetof(TkScrollbar, troughColorPtr), TK_CONFIG_MONO_ONLY, NULL}, {TK_CONFIG_PIXELS, "-width", "width", "Width", - tkDefScrollbarWidth, Tk_Offset(TkScrollbar, width), 0, NULL}, + tkDefScrollbarWidth, offsetof(TkScrollbar, width), 0, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* * Forward declarations for functions defined later in this file: @@ -177,14 +177,16 @@ scrollPtr->arrowLength = 0; scrollPtr->sliderFirst = 0; scrollPtr->sliderLast = 0; scrollPtr->activeField = 0; scrollPtr->activeRelief = TK_RELIEF_RAISED; +#ifndef TK_NO_DEPRECATED scrollPtr->totalUnits = 0; scrollPtr->windowUnits = 0; scrollPtr->firstUnit = 0; scrollPtr->lastUnit = 0; +#endif /* TK_NO_DEPRECATED */ scrollPtr->firstFraction = 0.0; scrollPtr->lastFraction = 0.0; scrollPtr->cursor = NULL; scrollPtr->takeFocus = NULL; scrollPtr->flags = 0; @@ -222,12 +224,12 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { register TkScrollbar *scrollPtr = clientData; - int result = TCL_OK; - int length, cmdIndex; + int result = TCL_OK, cmdIndex; + TkSizeT length; static const char *const commandNames[] = { "activate", "cget", "configure", "delta", "fraction", "get", "identify", "set", NULL }; enum command { @@ -267,11 +269,11 @@ } if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "activate element"); goto error; } - c = Tcl_GetStringFromObj(objv[2], &length)[0]; + c = TkGetStringFromObj(objv[2], &length)[0]; oldActiveField = scrollPtr->activeField; if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow1") == 0)) { scrollPtr->activeField = TOP_ARROW; } else if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow2") == 0)) { scrollPtr->activeField = BOTTOM_ARROW; @@ -375,21 +377,23 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "get"); goto error; } - if (scrollPtr->flags & NEW_STYLE_COMMANDS) { - resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction); - resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction); - Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs)); - } else { - resObjs[0] = Tcl_NewIntObj(scrollPtr->totalUnits); - resObjs[1] = Tcl_NewIntObj(scrollPtr->windowUnits); - resObjs[2] = Tcl_NewIntObj(scrollPtr->firstUnit); - resObjs[3] = Tcl_NewIntObj(scrollPtr->lastUnit); +#ifndef TK_NO_DEPRECATED + if (scrollPtr->flags & OLD_STYLE_COMMANDS) { + resObjs[0] = Tcl_NewWideIntObj(scrollPtr->totalUnits); + resObjs[1] = Tcl_NewWideIntObj(scrollPtr->windowUnits); + resObjs[2] = Tcl_NewWideIntObj(scrollPtr->firstUnit); + resObjs[3] = Tcl_NewWideIntObj(scrollPtr->lastUnit); Tcl_SetObjResult(interp, Tcl_NewListObj(4, resObjs)); + break; } +#endif /* TK_NO_DEPRECATED */ + resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction); + resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs)); break; } case COMMAND_IDENTIFY: { int x, y; const char *zone = ""; @@ -411,12 +415,10 @@ } Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1)); break; } case COMMAND_SET: { - int totalUnits, windowUnits, firstUnit, lastUnit; - if (objc == 4) { double first, last; if (Tcl_GetDoubleFromObj(interp, objv[2], &first) != TCL_OK) { goto error; @@ -436,12 +438,14 @@ } else if (last > 1.0) { scrollPtr->lastFraction = 1.0; } else { scrollPtr->lastFraction = last; } - scrollPtr->flags |= NEW_STYLE_COMMANDS; +#ifndef TK_NO_DEPRECATED + scrollPtr->flags &= ~OLD_STYLE_COMMANDS; } else if (objc == 6) { + int totalUnits, windowUnits, firstUnit, lastUnit; if (Tcl_GetIntFromObj(interp, objv[2], &totalUnits) != TCL_OK) { goto error; } if (totalUnits < 0) { totalUnits = 0; @@ -474,15 +478,14 @@ scrollPtr->lastFraction = 1.0; } else { scrollPtr->firstFraction = ((double) firstUnit)/totalUnits; scrollPtr->lastFraction = ((double) (lastUnit+1))/totalUnits; } - scrollPtr->flags &= ~NEW_STYLE_COMMANDS; + scrollPtr->flags |= OLD_STYLE_COMMANDS; +#endif /* !TK_NO_DEPRECATED */ } else { Tcl_WrongNumArgs(interp, 1, objv, "set firstFraction lastFraction"); - Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]), - " set totalUnits windowUnits firstUnit lastUnit\"", NULL); goto error; } TkpComputeScrollbarGeometry(scrollPtr); TkScrollbarEventuallyRedraw(scrollPtr); break; Index: generic/tkScrollbar.h ================================================================== --- generic/tkScrollbar.h +++ generic/tkScrollbar.h @@ -91,25 +91,29 @@ * information is provided by the application by invoking the "set" widget * command. This information can now be provided in two ways: the "old" * form (totalUnits, windowUnits, firstUnit, and lastUnit), or the "new" * form (firstFraction and lastFraction). FirstFraction and lastFraction * will always be valid, but the old-style information is only valid if - * the NEW_STYLE_COMMANDS flag is 0. + * the OLD_STYLE_COMMANDS flag is 1. */ +#ifndef TK_NO_DEPRECATED int totalUnits; /* Total dimension of application, in units. - * Valid only if the NEW_STYLE_COMMANDS flag - * isn't set. */ + * Valid only if the OLD_STYLE_COMMANDS flag + * is set. */ int windowUnits; /* Maximum number of units that can be * displayed in the window at once. Valid only - * if the NEW_STYLE_COMMANDS flag isn't set. */ + * if the OLD_STYLE_COMMANDS flag is set. */ int firstUnit; /* Number of last unit visible in * application's window. Valid only if the - * NEW_STYLE_COMMANDS flag isn't set. */ + * OLD_STYLE_COMMANDS flag is set. */ int lastUnit; /* Index of last unit visible in window. - * Valid only if the NEW_STYLE_COMMANDS flag + * Valid only if the OLD_STYLE_COMMANDS flag * isn't set. */ +#else + int dummy1,dummy2,dummy3,dummy4; /* sizeof(TkScrollbar) should not depend on TK_NO_DEPRECATED */ +#endif /* TK_NO_DEPRECATED */ double firstFraction; /* Position of first visible thing in window, * specified as a fraction between 0 and * 1.0. */ double lastFraction; /* Position of last visible thing in window, * specified as a fraction between 0 and @@ -142,20 +146,22 @@ /* * Flag bits for scrollbars: * * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has * already been queued to redraw this window. - * NEW_STYLE_COMMANDS: Non-zero means the new style of commands + * OLD_STYLE_COMMANDS: Non-zero means the old style of commands * should be used to communicate with the widget: - * ".t yview scroll 2 lines", instead of - * ".t yview 40", for example. + * ".t yview 40", instead of + * ".t yview scroll 2 lines", for example. * GOT_FOCUS: Non-zero means this window has the input * focus. */ #define REDRAW_PENDING 1 -#define NEW_STYLE_COMMANDS 2 +#ifndef TK_NO_DEPRECATED +# define OLD_STYLE_COMMANDS 2 +#endif /* TK_NO_DEPRECATED */ #define GOT_FOCUS 4 /* * Declaration of scrollbar class functions structure * and default scrollbar width, for use in configSpec. Index: generic/tkSelect.c ================================================================== --- generic/tkSelect.c +++ generic/tkSelect.c @@ -24,11 +24,11 @@ Tcl_Interp *interp; /* Interpreter in which to invoke command. */ int cmdLength; /* # of non-NULL bytes in command. */ int charOffset; /* The offset of the next char to retrieve. */ int byteOffset; /* The expected byte offset of the next * chunk. */ - char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character + char buffer[4]; /* A buffer to hold part of a UTF character * that is split across chunks. */ char command[1]; /* Command to invoke. Actual space is * allocated as large as necessary. This must * be the last entry in the structure. */ } CommandInfo; @@ -46,11 +46,11 @@ /* * The structure below is used to keep each thread's pending list separate. */ -typedef struct ThreadSpecificData { +typedef struct { TkSelInProgress *pendingPtr; /* Topmost search in progress, or NULL if * none. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -188,11 +188,11 @@ /* * The clientData is selection controlled memory, so we * should make a copy for this selPtr. */ - unsigned cmdInfoLen = Tk_Offset(CommandInfo, command) + 1 + + size_t cmdInfoLen = offsetof(CommandInfo, command) + 1 + ((CommandInfo *)clientData)->cmdLength; selPtr->clientData = ckalloc(cmdInfoLen); memcpy(selPtr->clientData, clientData, cmdInfoLen); } else { @@ -355,11 +355,11 @@ { register TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; Tk_LostSelProc *clearProc = NULL; - ClientData clearData = NULL;/* Initialization needed only to prevent + void *clearData = NULL;/* Initialization needed only to prevent * compiler warning. */ if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); } @@ -464,11 +464,11 @@ TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; TkSelectionInfo *prevPtr; TkSelectionInfo *nextPtr; Tk_LostSelProc *clearProc = NULL; - ClientData clearData = NULL;/* Initialization needed only to prevent + void *clearData = NULL;/* Initialization needed only to prevent * compiler warning. */ if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); } @@ -829,11 +829,11 @@ case SELECTION_HANDLE: { Atom target, format; const char *targetName = NULL; const char *formatName = NULL; register CommandInfo *cmdInfoPtr; - int cmdLength; + TkSizeT cmdLength; static const char *const handleOptionStrings[] = { "-format", "-selection", "-type", NULL }; enum handleOptions { HANDLE_FORMAT, HANDLE_SELECTION, HANDLE_TYPE @@ -898,15 +898,15 @@ } else if (formatName != NULL) { format = Tk_InternAtom(tkwin, formatName); } else { format = XA_STRING; } - string = Tcl_GetStringFromObj(objs[1], &cmdLength); + string = TkGetStringFromObj(objs[1], &cmdLength); if (cmdLength == 0) { Tk_DeleteSelHandler(tkwin, selection, target); } else { - cmdInfoPtr = ckalloc(Tk_Offset(CommandInfo, command) + cmdInfoPtr = ckalloc(offsetof(CommandInfo, command) + 1 + cmdLength); cmdInfoPtr->interp = interp; cmdInfoPtr->charOffset = 0; cmdInfoPtr->byteOffset = 0; cmdInfoPtr->buffer[0] = '\0'; @@ -1244,11 +1244,11 @@ } prevPtr = infoPtr; } if (infoPtr != NULL && (infoPtr->owner == tkwin) && - (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) { + (eventPtr->xselectionclear.serial >= (unsigned long) infoPtr->serial)) { if (prevPtr == NULL) { dispPtr->selectionInfoPtr = infoPtr->nextPtr; } else { prevPtr->nextPtr = infoPtr->nextPtr; } @@ -1385,11 +1385,11 @@ * TODO: This assumes that bytes are characters; that's not true! */ string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); count = (length > maxBytes) ? maxBytes : length; - memcpy(buffer, string, (size_t) count); + memcpy(buffer, string, count); buffer[count] = '\0'; /* * Update the partial character information for the next retrieval if * the command has not been deleted. @@ -1408,11 +1408,11 @@ numChars++; } cmdInfoPtr->charOffset += numChars; length = p - string; if (length > 0) { - strncpy(cmdInfoPtr->buffer, string, (size_t) length); + strncpy(cmdInfoPtr->buffer, string, length); } cmdInfoPtr->buffer[length] = '\0'; } cmdInfoPtr->byteOffset += count + extraBytes; } @@ -1506,11 +1506,11 @@ length = Tcl_DStringLength(&ds); if (length >= maxBytes) { Tcl_DStringFree(&ds); return -1; } - memcpy(buffer, Tcl_DStringValue(&ds), (unsigned) (1+length)); + memcpy(buffer, Tcl_DStringValue(&ds), length + 1); Tcl_DStringFree(&ds); *typePtr = XA_ATOM; return length; } Index: generic/tkSelect.h ================================================================== --- generic/tkSelect.h +++ generic/tkSelect.h @@ -23,18 +23,22 @@ */ typedef struct TkSelectionInfo { Atom selection; /* Selection name, e.g. XA_PRIMARY. */ Tk_Window owner; /* Current owner of this selection. */ - int serial; /* Serial number of last XSelectionSetOwner +#if TCL_MAJOR_VERSION > 8 + unsigned long serial; /* Serial number of last XSelectionSetOwner * request made to server for this selection * (used to filter out redundant * SelectionClear events). */ +#else + int serial; +#endif Time time; /* Timestamp used to acquire selection. */ Tk_LostSelProc *clearProc; /* Procedure to call when owner loses * selection. */ - ClientData clearData; /* Info to pass to clearProc. */ + void *clearData; /* Info to pass to clearProc. */ struct TkSelectionInfo *nextPtr; /* Next in list of current selections on this * display. NULL means end of list. */ } TkSelectionInfo; @@ -50,12 +54,12 @@ * as TARGETS or STRING. */ Atom format; /* Format in which selection info will be * returned, such as STRING or ATOM. */ Tk_SelectionProc *proc; /* Procedure to generate selection in this * format. */ - ClientData clientData; /* Argument to pass to proc. */ - int size; /* Size of units returned by proc (8 for + void *clientData; /* Argument to pass to proc. */ + TkSizeT size; /* Size of units returned by proc (8 for * STRING, 32 for almost anything else). */ struct TkSelHandler *nextPtr; /* Next selection handler associated with same * window (NULL for end of list). */ } TkSelHandler; Index: generic/tkSquare.c ================================================================== --- generic/tkSquare.c +++ generic/tkSquare.c @@ -64,33 +64,33 @@ * Information used for argv parsing. */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", - "#d9d9d9", Tk_Offset(Square, bgBorderPtr), -1, 0, + "#d9d9d9", offsetof(Square, bgBorderPtr), -1, 0, "white", 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", 0}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - "2", Tk_Offset(Square, borderWidthPtr), -1, 0, NULL, 0}, + "2", offsetof(Square, borderWidthPtr), -1, 0, NULL, 0}, {TK_OPTION_BOOLEAN, "-dbl", "doubleBuffer", "DoubleBuffer", - "1", Tk_Offset(Square, doubleBufferPtr), -1, 0 , NULL, 0}, + "1", offsetof(Square, doubleBufferPtr), -1, 0 , NULL, 0}, {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground", - "#b03060", Tk_Offset(Square, fgBorderPtr), -1, 0, + "#b03060", offsetof(Square, fgBorderPtr), -1, 0, "black", 0}, {TK_OPTION_PIXELS, "-posx", "posx", "PosX", "0", - Tk_Offset(Square, xPtr), -1, 0, NULL, 0}, + offsetof(Square, xPtr), -1, 0, NULL, 0}, {TK_OPTION_PIXELS, "-posy", "posy", "PosY", "0", - Tk_Offset(Square, yPtr), -1, 0, NULL, 0}, + offsetof(Square, yPtr), -1, 0, NULL, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - "raised", Tk_Offset(Square, reliefPtr), -1, 0, NULL, 0}, + "raised", offsetof(Square, reliefPtr), -1, 0, NULL, 0}, {TK_OPTION_PIXELS, "-size", "size", "Size", "20", - Tk_Offset(Square, sizeObjPtr), -1, 0, NULL, 0}, + offsetof(Square, sizeObjPtr), -1, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; /* * Forward declarations for procedures defined later in this file: @@ -170,20 +170,20 @@ Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd, squarePtr, SquareDeletedProc); squarePtr->gc = NULL; squarePtr->optionTable = optionTable; - if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin) + if (Tk_InitOptions(interp, squarePtr, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(squarePtr->tkwin); ckfree(squarePtr); return TCL_ERROR; } Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask, SquareObjEventProc, squarePtr); - if (Tk_SetOptions(interp, (char *) squarePtr, optionTable, objc - 2, + if (Tk_SetOptions(interp, squarePtr, optionTable, objc - 2, objv + 2, tkwin, NULL, NULL) != TCL_OK) { goto error; } if (SquareConfigure(interp, squarePtr) != TCL_OK) { goto error; @@ -248,11 +248,11 @@ case SQUARE_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } - resultObjPtr = Tk_GetOptionValue(interp, (char *) squarePtr, + resultObjPtr = Tk_GetOptionValue(interp, squarePtr, squarePtr->optionTable, objv[2], squarePtr->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); @@ -259,23 +259,23 @@ } break; case SQUARE_CONFIGURE: resultObjPtr = NULL; if (objc == 2) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr, + resultObjPtr = Tk_GetOptionInfo(interp, squarePtr, squarePtr->optionTable, NULL, squarePtr->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } } else if (objc == 3) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr, + resultObjPtr = Tk_GetOptionInfo(interp, squarePtr, squarePtr->optionTable, objv[2], squarePtr->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } } else { - result = Tk_SetOptions(interp, (char *) squarePtr, + result = Tk_SetOptions(interp, squarePtr, squarePtr->optionTable, objc - 2, objv + 2, squarePtr->tkwin, NULL, NULL); if (result == TCL_OK) { result = SquareConfigure(interp, squarePtr); } @@ -333,11 +333,11 @@ bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, squarePtr->bgBorderPtr); Tk_SetWindowBackground(squarePtr->tkwin, Tk_3DBorderColor(bgBorder)->pixel); Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer); - if ((squarePtr->gc == NULL) && (doubleBuffer)) { + if ((squarePtr->gc == NULL) && doubleBuffer) { XGCValues gcValues; gcValues.function = GXcopy; gcValues.graphics_exposures = False; squarePtr->gc = Tk_GetGC(squarePtr->tkwin, GCFunction|GCGraphicsExposures, &gcValues); Index: generic/tkStubInit.c ================================================================== --- generic/tkStubInit.c +++ generic/tkStubInit.c @@ -36,10 +36,47 @@ /* * Remove macro that might interfere with the definition below. */ #undef Tk_MainEx +#undef Tk_FreeXId +#undef Tk_FreeStyleFromObj +#undef Tk_GetStyleFromObj +#undef TkWinGetPlatformId + +#if defined(TK_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 +#define Tk_MainEx 0 +#define Tk_FreeXId 0 +#define Tk_FreeStyleFromObj 0 +#define Tk_GetStyleFromObj 0 +#define TkWinGetPlatformId 0 +#define Tk_PhotoPutBlock_NoComposite 0 +#define Tk_PhotoPutZoomedBlock_NoComposite 0 +#define Tk_PhotoExpand_Panic 0 +#define Tk_PhotoPutBlock_Panic 0 +#define Tk_PhotoPutZoomedBlock_Panic 0 +#define Tk_PhotoSetSize_Panic 0 +#else +static void +doNothing(void) +{ + /* dummy implementation, no need to do anything */ +} +#define Tk_FreeXId ((void (*)(Display *, XID)) doNothing) +#define Tk_FreeStyleFromObj ((void (*)(Tcl_Obj *)) doNothing) +#define Tk_GetStyleFromObj getStyleFromObj +static Tk_Style Tk_GetStyleFromObj(Tcl_Obj *obj) +{ + return Tk_AllocStyleFromObj(NULL, obj); +} +#if defined(_WIN32) || defined(__CYGWIN__) +#define TkWinGetPlatformId winGetPlatformId +static int TkWinGetPlatformId(void) { + return 2; +} +#endif /* defined(_WIN32) || defined(__CYGWIN__) */ +#endif /* !TK_NO_DEPRECATED */ #ifdef _WIN32 int TkpCmapStressed(Tk_Window tkwin, Colormap colormap) @@ -63,10 +100,12 @@ # define TkUnixDoOneXEvent 0 # define TkUnixSetMenubar 0 # define XCreateWindow 0 # define XOffsetRegion 0 # define XUnionRegion 0 +# define XPolygonRegion 0 +# define XPointInRegion 0 # define TkWmCleanup (void (*)(TkDisplay *)) TkpSync # define TkSendCleanup (void (*)(TkDisplay *)) TkpSync # define TkpTestsendCmd 0 #else /* !_WIN32 */ @@ -201,11 +240,10 @@ # define TkWinXCleanup 0 # define TkWinXInit 0 # define TkWinSetForegroundWindow 0 # define TkWinDialogDebug 0 # define TkWinGetMenuSystemDefault 0 -# define TkWinGetPlatformId 0 # define TkWinSetHINSTANCE 0 # define TkWinGetPlatformTheme 0 # define TkWinChildProc 0 # elif !defined(MAC_OSX_TK) /* UNIX */ @@ -234,10 +272,18 @@ * WARNING: The contents of this file is automatically generated by the * tools/genStubs.tcl script. Any modifications to the function declarations * below should be made in the generic/tk.decls script. */ +#ifdef __GNUC__ +/* + * The rest of this file shouldn't warn about deprecated functions; they're + * there because we intend them to be so and know that this file is OK to + * touch those fields. + */ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif /* !BEGIN!: Do not edit below this line. */ static const TkIntStubs tkIntStubs = { TCL_STUB_MAGIC, 0, @@ -451,10 +497,11 @@ TkSmoothPrintProc, /* 180 */ TkDrawAngledTextLayout, /* 181 */ TkUnderlineAngledTextLayout, /* 182 */ TkIntersectAngledTextLayout, /* 183 */ TkDrawAngledChars, /* 184 */ + TkDebugPhotoStringMatchDef, /* 185 */ }; static const TkIntPlatStubs tkIntPlatStubs = { TCL_STUB_MAGIC, 0, @@ -722,10 +769,12 @@ XDrawSegments, /* 133 */ XDrawPoint, /* 134 */ XDrawPoints, /* 135 */ XReparentWindow, /* 136 */ XPutImage, /* 137 */ + XPolygonRegion, /* 138 */ + XPointInRegion, /* 139 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ XSetDashes, /* 0 */ XGetModifierMapping, /* 1 */ XCreateImage, /* 2 */ Index: generic/tkStyle.c ================================================================== --- generic/tkStyle.c +++ generic/tkStyle.c @@ -96,11 +96,11 @@ /* * Thread-local data. */ -typedef struct ThreadSpecificData { +typedef struct { int nbInit; /* Number of calls to the init proc. */ Tcl_HashTable engineTable; /* Map a name to a style engine. Keys are * strings, values are Tk_StyleEngine * pointers. */ StyleEngine *defaultEnginePtr; @@ -153,11 +153,11 @@ static const Tcl_ObjType styleObjType = { "style", /* name */ FreeStyleObjProc, /* freeIntRepProc */ DupStyleObjProc, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetStyleFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* *--------------------------------------------------------------------------- * @@ -1074,11 +1074,11 @@ void Tk_GetElementSize( Tk_Style style, /* The widget style. */ Tk_StyledElement element, /* The styled element, previously returned by * Tk_GetStyledElement. */ - char *recordPtr, /* The widget record. */ + void *recordPtr, /* The widget record. */ Tk_Window tkwin, /* The widget window. */ int width, int height, /* Requested size. */ int inner, /* If TRUE, compute the outer size according * to the requested minimum inner size. If * FALSE, compute the inner size according to @@ -1115,11 +1115,11 @@ void Tk_GetElementBox( Tk_Style style, /* The widget style. */ Tk_StyledElement element, /* The styled element, previously returned by * Tk_GetStyledElement. */ - char *recordPtr, /* The widget record. */ + void *recordPtr, /* The widget record. */ Tk_Window tkwin, /* The widget window. */ int x, int y, /* Top left corner of available area. */ int width, int height, /* Size of available area. */ int inner, /* Boolean. If TRUE, compute the bounding box * according to the requested inscribed box @@ -1157,11 +1157,11 @@ int Tk_GetElementBorderWidth( Tk_Style style, /* The widget style. */ Tk_StyledElement element, /* The styled element, previously returned by * Tk_GetStyledElement. */ - char *recordPtr, /* The widget record. */ + void *recordPtr, /* The widget record. */ Tk_Window tkwin) /* The widget window. */ { Style *stylePtr = (Style *) style; StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element; @@ -1188,11 +1188,11 @@ void Tk_DrawElement( Tk_Style style, /* The widget style. */ Tk_StyledElement element, /* The styled element, previously returned by * Tk_GetStyledElement. */ - char *recordPtr, /* The widget record. */ + void *recordPtr, /* The widget record. */ Tk_Window tkwin, /* The widget window. */ Drawable d, /* Where to draw element. */ int x, int y, /* Top left corner of element. */ int width, int height, /* Size of element. */ int state) /* Drawing state flags. */ @@ -1358,11 +1358,11 @@ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "style \"%s\" doesn't exist", name)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "STYLE", name, NULL); } - return (Tk_Style) NULL; + return NULL; } stylePtr = Tcl_GetHashValue(entryPtr); return (Tk_Style) stylePtr; } @@ -1403,63 +1403,16 @@ Tk_AllocStyleFromObj( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Obj *objPtr) /* Object containing name of the style to * retrieve. */ { - Style *stylePtr; - - if (objPtr->typePtr != &styleObjType) { - SetStyleFromAny(interp, objPtr); - } - stylePtr = objPtr->internalRep.twoPtrValue.ptr1; - - return (Tk_Style) stylePtr; -} - -/* - *---------------------------------------------------------------------- - * - * Tk_GetStyleFromObj -- - * - * Find the style that corresponds to a given object. The style must have - * already been created by Tk_CreateStyle. - * - * Results: - * The return value is a token for the style that matches objPtr, or NULL - * if none found. - * - * Side effects: - * If the object is not already a style ref, the conversion will free any - * old internal representation. - * - *---------------------------------------------------------------------- - */ - -Tk_Style -Tk_GetStyleFromObj( - Tcl_Obj *objPtr) /* The object from which to get the style. */ -{ - if (objPtr->typePtr != &styleObjType) { - SetStyleFromAny(NULL, objPtr); - } - - return objPtr->internalRep.twoPtrValue.ptr1; -} - -/* - *--------------------------------------------------------------------------- - * - * Tk_FreeStyleFromObj -- - * - * No-op. Present only for stubs compatibility. - * - *--------------------------------------------------------------------------- - */ -void -Tk_FreeStyleFromObj( - Tcl_Obj *objPtr) -{ + if (objPtr->typePtr != &styleObjType) { + if (SetStyleFromAny(interp, objPtr) != TCL_OK) { + return NULL; + } + } + return objPtr->internalRep.twoPtrValue.ptr1; } /* *---------------------------------------------------------------------- * @@ -1467,12 +1420,12 @@ * * Convert the internal representation of a Tcl object to the style * internal form. * * Results: - * Always returns TCL_OK. If an error occurs is returned (e.g. the style - * doesn't exist), an error message will be left in interp's result. + * If an error occurs is returned (e.g. the style doesn't exist), an + * error message will be left in interp's result and TCL_ERROR is returned. * * Side effects: * The object is left with its typePtr pointing to styleObjType. * *---------------------------------------------------------------------- @@ -1483,10 +1436,11 @@ Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { const Tcl_ObjType *typePtr; const char *name; + Tk_Style style; /* * Free the old internalRep before setting the new one. */ @@ -1494,12 +1448,16 @@ typePtr = objPtr->typePtr; if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { typePtr->freeIntRepProc(objPtr); } + style = Tk_GetStyle(interp, name); + if (style == NULL) { + return TCL_ERROR; + } objPtr->typePtr = &styleObjType; - objPtr->internalRep.twoPtrValue.ptr1 = Tk_GetStyle(interp, name); + objPtr->internalRep.twoPtrValue.ptr1 = style; return TCL_OK; } /* Index: generic/tkTest.c ================================================================== --- generic/tkTest.c +++ generic/tkTest.c @@ -29,13 +29,13 @@ #endif #if defined(MAC_OSX_TK) #include "tkMacOSXInt.h" #include "tkScrollbar.h" -#define APP_IS_DRAWING TkTestAppIsDrawing() +#define LOG_DISPLAY TkTestLogDisplay() #else -#define APP_IS_DRAWING 0 +#define LOG_DISPLAY 1 #endif #ifdef __UNIX__ #include "tkUnixInt.h" #endif @@ -192,10 +192,13 @@ char *saveInternalPtr); static void CustomOptionFree(ClientData clientData, Tk_Window tkwin, char *internalPtr); static int TestpropObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); +static int TestprintfObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) static int TestwrapperObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); @@ -204,17 +207,20 @@ static int TrivialConfigObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); static void TrivialEventProc(ClientData clientData, XEvent *eventPtr); +static int TestPhotoStringMatchCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); /* *---------------------------------------------------------------------- * * Tktest_Init -- * - * This function performs intialization for the Tk test suite exensions. + * This function performs initialization for the Tk test suite extensions. * * Results: * Returns a standard Tcl completion code, and leaves an error message in * the interp's result if an error occurs. * @@ -228,11 +234,11 @@ Tktest_Init( Tcl_Interp *interp) /* Interpreter for application. */ { static int initialized = 0; - if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) { return TCL_ERROR; } if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) { return TCL_ERROR; } @@ -240,11 +246,11 @@ /* * Create additional commands for testing Tk. */ if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) { - return TCL_ERROR; + return TCL_ERROR; } Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd, (ClientData) Tk_MainWindow(interp), NULL); @@ -264,12 +270,16 @@ (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testmakeexist", TestmakeexistObjCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testprop", TestpropObjCmd, (ClientData) Tk_MainWindow(interp), NULL); + Tcl_CreateObjCommand(interp, "testprintf", TestprintfObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testtext", TkpTesttextCmd, (ClientData) Tk_MainWindow(interp), NULL); + Tcl_CreateObjCommand(interp, "testphotostringmatch", + TestPhotoStringMatchCmd, (ClientData) Tk_MainWindow(interp), + NULL); #if defined(_WIN32) Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd, (ClientData) Tk_MainWindow(interp), NULL); #elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK) @@ -453,11 +463,11 @@ * * Results: * A standard Tcl result. * * Side effects: - * All the intepreters created by previous calls to "testnewapp" get + * All the interpreters created by previous calls to "testnewapp" get * deleted. * *---------------------------------------------------------------------- */ @@ -525,11 +535,11 @@ CustomOptionGet, CustomOptionRestore, CustomOptionFree, INT2PTR(1) }; - Tk_Window mainWin = (Tk_Window) clientData; + Tk_Window mainWin = clientData; Tk_Window tkwin; int index, result = TCL_OK; /* * Structures used by the "chain1" subcommand and also shared by the @@ -544,13 +554,13 @@ Tcl_Obj *extension4ObjPtr; Tcl_Obj *extension5ObjPtr; } ExtensionWidgetRecord; static const Tk_OptionSpec baseSpecs[] = { {TK_OPTION_STRING, "-one", "one", "One", "one", - Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1, 0, NULL, 0}, + offsetof(ExtensionWidgetRecord, base1ObjPtr), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-two", "two", "Two", "two", - Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0}, + offsetof(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command"); @@ -588,51 +598,51 @@ static const char *const stringTable[] = { "one", "two", "three", "four", NULL }; static const Tk_OptionSpec typesSpecs[] = { {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1", - Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1}, + offsetof(TypesRecord, booleanPtr), -1, 0, 0, 0x1}, {TK_OPTION_INT, "-integer", "integer", "Integer", "7", - Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2}, + offsetof(TypesRecord, integerPtr), -1, 0, 0, 0x2}, {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159", - Tk_Offset(TypesRecord, doublePtr), -1, 0, 0, 0x4}, + offsetof(TypesRecord, doublePtr), -1, 0, 0, 0x4}, {TK_OPTION_STRING, "-string", "string", "String", - "foo", Tk_Offset(TypesRecord, stringPtr), -1, + "foo", offsetof(TypesRecord, stringPtr), -1, TK_CONFIG_NULL_OK, 0, 0x8}, {TK_OPTION_STRING_TABLE, "-stringtable", "StringTable", "stringTable", - "one", Tk_Offset(TypesRecord, stringTablePtr), -1, + "one", offsetof(TypesRecord, stringTablePtr), -1, TK_CONFIG_NULL_OK, stringTable, 0x10}, {TK_OPTION_COLOR, "-color", "color", "Color", - "red", Tk_Offset(TypesRecord, colorPtr), -1, + "red", offsetof(TypesRecord, colorPtr), -1, TK_CONFIG_NULL_OK, "black", 0x20}, {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12", - Tk_Offset(TypesRecord, fontPtr), -1, + offsetof(TypesRecord, fontPtr), -1, TK_CONFIG_NULL_OK, 0, 0x40}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50", - Tk_Offset(TypesRecord, bitmapPtr), -1, + offsetof(TypesRecord, bitmapPtr), -1, TK_CONFIG_NULL_OK, 0, 0x80}, {TK_OPTION_BORDER, "-border", "border", "Border", - "blue", Tk_Offset(TypesRecord, borderPtr), -1, + "blue", offsetof(TypesRecord, borderPtr), -1, TK_CONFIG_NULL_OK, "white", 0x100}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised", - Tk_Offset(TypesRecord, reliefPtr), -1, + offsetof(TypesRecord, reliefPtr), -1, TK_CONFIG_NULL_OK, 0, 0x200}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm", - Tk_Offset(TypesRecord, cursorPtr), -1, + offsetof(TypesRecord, cursorPtr), -1, TK_CONFIG_NULL_OK, 0, 0x400}, {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left", - Tk_Offset(TypesRecord, justifyPtr), -1, + offsetof(TypesRecord, justifyPtr), -1, TK_CONFIG_NULL_OK, 0, 0x800}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL, - Tk_Offset(TypesRecord, anchorPtr), -1, + offsetof(TypesRecord, anchorPtr), -1, TK_CONFIG_NULL_OK, 0, 0x1000}, {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", - "1", Tk_Offset(TypesRecord, pixelPtr), -1, + "1", offsetof(TypesRecord, pixelPtr), -1, TK_CONFIG_NULL_OK, 0, 0x2000}, {TK_OPTION_CUSTOM, "-custom", NULL, NULL, - "", Tk_Offset(TypesRecord, customPtr), -1, + "", offsetof(TypesRecord, customPtr), -1, TK_CONFIG_NULL_OK, &CustomOption, 0x4000}, {TK_OPTION_SYNONYM, "-synonym", NULL, NULL, NULL, 0, -1, 0, "-color", 0x8000}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; @@ -639,11 +649,11 @@ Tk_OptionTable optionTable; Tk_Window tkwin; optionTable = Tk_CreateOptionTable(interp, typesSpecs); tables[index] = optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + tkwin = Tk_CreateWindowFromPath(interp, clientData, Tcl_GetString(objv[2]), NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "Test"); @@ -666,19 +676,19 @@ recordPtr->anchorPtr = NULL; recordPtr->pixelPtr = NULL; recordPtr->mmPtr = NULL; recordPtr->stringTablePtr = NULL; recordPtr->customPtr = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, + result = Tk_InitOptions(interp, recordPtr, optionTable, tkwin); if (result == TCL_OK) { recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), TrivialConfigObjCmd, (ClientData) recordPtr, TrivialCmdDeletedProc); Tk_CreateEventHandler(tkwin, StructureNotifyMask, TrivialEventProc, (ClientData) recordPtr); - result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + result = Tk_SetOptions(interp, recordPtr, optionTable, objc-3, objv+3, tkwin, NULL, NULL); if (result != TCL_OK) { Tk_DestroyWindow(tkwin); } } else { @@ -694,11 +704,11 @@ case CHAIN1: { ExtensionWidgetRecord *recordPtr; Tk_Window tkwin; Tk_OptionTable optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + tkwin = Tk_CreateWindowFromPath(interp, clientData, Tcl_GetString(objv[2]), NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "Test"); @@ -709,16 +719,16 @@ recordPtr->header.interp = interp; recordPtr->header.optionTable = optionTable; recordPtr->header.tkwin = tkwin; recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL; recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL; - result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin); + result = Tk_InitOptions(interp, recordPtr, optionTable, tkwin); if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + result = Tk_SetOptions(interp, recordPtr, optionTable, objc-3, objv+3, tkwin, NULL, NULL); if (result != TCL_OK) { - Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin); + Tk_FreeConfigOptions(recordPtr, optionTable, tkwin); } } if (result == TCL_OK) { recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), TrivialConfigObjCmd, @@ -733,25 +743,25 @@ case CHAIN2: case CHAIN3: { ExtensionWidgetRecord *recordPtr; static const Tk_OptionSpec extensionSpecs[] = { {TK_OPTION_STRING, "-three", "three", "Three", "three", - Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr), -1, 0, NULL, 0}, + offsetof(ExtensionWidgetRecord, extension3ObjPtr), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-four", "four", "Four", "four", - Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr), -1, 0, NULL, 0}, + offsetof(ExtensionWidgetRecord, extension4ObjPtr), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-two", "two", "Two", "two and a half", - Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0}, + offsetof(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-oneAgain", "oneAgain", "OneAgain", "one again", - Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr), -1, 0, NULL, 0}, + offsetof(ExtensionWidgetRecord, extension5ObjPtr), -1, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, (ClientData) baseSpecs, 0} }; Tk_Window tkwin; Tk_OptionTable optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + tkwin = Tk_CreateWindowFromPath(interp, clientData, Tcl_GetString(objv[2]), NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "Test"); @@ -763,13 +773,13 @@ recordPtr->header.optionTable = optionTable; recordPtr->header.tkwin = tkwin; recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL; recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL; recordPtr->extension5ObjPtr = NULL; - result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin); + result = Tk_InitOptions(interp, recordPtr, optionTable, tkwin); if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + result = Tk_SetOptions(interp, recordPtr, optionTable, objc-3, objv+3, tkwin, NULL, NULL); if (result != TCL_OK) { Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin); } } @@ -789,19 +799,19 @@ Tcl_Obj *intPtr; } ErrorWidgetRecord; ErrorWidgetRecord widgetRecord; static const Tk_OptionSpec errorSpecs[] = { {TK_OPTION_INT, "-int", "integer", "Integer", "bogus", - Tk_Offset(ErrorWidgetRecord, intPtr), 0, 0, NULL, 0}, + offsetof(ErrorWidgetRecord, intPtr), 0, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; Tk_OptionTable optionTable; widgetRecord.intPtr = NULL; optionTable = Tk_CreateOptionTable(interp, errorSpecs); tables[index] = optionTable; - return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable, + return Tk_InitOptions(interp, &widgetRecord, optionTable, (Tk_Window) NULL); } case DEL: if (objc != 3) { @@ -863,54 +873,54 @@ static const char *const internalStringTable[] = { "one", "two", "three", "four", NULL }; static const Tk_OptionSpec internalSpecs[] = { {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1", - -1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1}, + -1, offsetof(InternalRecord, boolean), 0, 0, 0x1}, {TK_OPTION_INT, "-integer", "integer", "Integer", "148962237", - -1, Tk_Offset(InternalRecord, integer), 0, 0, 0x2}, + -1, offsetof(InternalRecord, integer), 0, 0, 0x2}, {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159", - -1, Tk_Offset(InternalRecord, doubleValue), 0, 0, 0x4}, + -1, offsetof(InternalRecord, doubleValue), 0, 0, 0x4}, {TK_OPTION_STRING, "-string", "string", "String", "foo", - -1, Tk_Offset(InternalRecord, string), + -1, offsetof(InternalRecord, string), TK_CONFIG_NULL_OK, 0, 0x8}, {TK_OPTION_STRING_TABLE, "-stringtable", "StringTable", "stringTable", "one", - -1, Tk_Offset(InternalRecord, index), + -1, offsetof(InternalRecord, index), TK_CONFIG_NULL_OK, internalStringTable, 0x10}, {TK_OPTION_COLOR, "-color", "color", "Color", "red", - -1, Tk_Offset(InternalRecord, colorPtr), + -1, offsetof(InternalRecord, colorPtr), TK_CONFIG_NULL_OK, "black", 0x20}, {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12", - -1, Tk_Offset(InternalRecord, tkfont), + -1, offsetof(InternalRecord, tkfont), TK_CONFIG_NULL_OK, 0, 0x40}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50", - -1, Tk_Offset(InternalRecord, bitmap), + -1, offsetof(InternalRecord, bitmap), TK_CONFIG_NULL_OK, 0, 0x80}, {TK_OPTION_BORDER, "-border", "border", "Border", "blue", - -1, Tk_Offset(InternalRecord, border), + -1, offsetof(InternalRecord, border), TK_CONFIG_NULL_OK, "white", 0x100}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised", - -1, Tk_Offset(InternalRecord, relief), + -1, offsetof(InternalRecord, relief), TK_CONFIG_NULL_OK, 0, 0x200}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm", - -1, Tk_Offset(InternalRecord, cursor), + -1, offsetof(InternalRecord, cursor), TK_CONFIG_NULL_OK, 0, 0x400}, {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left", - -1, Tk_Offset(InternalRecord, justify), + -1, offsetof(InternalRecord, justify), TK_CONFIG_NULL_OK, 0, 0x800}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL, - -1, Tk_Offset(InternalRecord, anchor), + -1, offsetof(InternalRecord, anchor), TK_CONFIG_NULL_OK, 0, 0x1000}, {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", "1", - -1, Tk_Offset(InternalRecord, pixels), + -1, offsetof(InternalRecord, pixels), TK_CONFIG_NULL_OK, 0, 0x2000}, {TK_OPTION_WINDOW, "-window", "window", "Window", NULL, - -1, Tk_Offset(InternalRecord, tkwin), + -1, offsetof(InternalRecord, tkwin), TK_CONFIG_NULL_OK, 0, 0}, {TK_OPTION_CUSTOM, "-custom", NULL, NULL, "", - -1, Tk_Offset(InternalRecord, custom), + -1, offsetof(InternalRecord, custom), TK_CONFIG_NULL_OK, &CustomOption, 0x4000}, {TK_OPTION_SYNONYM, "-synonym", NULL, NULL, NULL, -1, -1, 0, "-color", 0x8000}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; @@ -917,11 +927,11 @@ Tk_OptionTable optionTable; Tk_Window tkwin; optionTable = Tk_CreateOptionTable(interp, internalSpecs); tables[index] = optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + tkwin = Tk_CreateWindowFromPath(interp, clientData, Tcl_GetString(objv[2]), NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "Test"); @@ -945,19 +955,19 @@ recordPtr->anchor = TK_ANCHOR_N; recordPtr->pixels = 0; recordPtr->mm = 0.0; recordPtr->tkwin = NULL; recordPtr->custom = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, + result = Tk_InitOptions(interp, recordPtr, optionTable, tkwin); if (result == TCL_OK) { recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), TrivialConfigObjCmd, recordPtr, TrivialCmdDeletedProc); Tk_CreateEventHandler(tkwin, StructureNotifyMask, TrivialEventProc, recordPtr); - result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + result = Tk_SetOptions(interp, recordPtr, optionTable, objc - 3, objv + 3, tkwin, NULL, NULL); if (result != TCL_OK) { Tk_DestroyWindow(tkwin); } } else { @@ -980,19 +990,19 @@ Tcl_Obj *five; } FiveRecord; FiveRecord *recordPtr; static const Tk_OptionSpec smallSpecs[] = { {TK_OPTION_INT, "-one", "one", "One", "1", - Tk_Offset(FiveRecord, one), -1, 0, NULL, 0}, + offsetof(FiveRecord, one), -1, 0, NULL, 0}, {TK_OPTION_INT, "-two", "two", "Two", "2", - Tk_Offset(FiveRecord, two), -1, 0, NULL, 0}, + offsetof(FiveRecord, two), -1, 0, NULL, 0}, {TK_OPTION_INT, "-three", "three", "Three", "3", - Tk_Offset(FiveRecord, three), -1, 0, NULL, 0}, + offsetof(FiveRecord, three), -1, 0, NULL, 0}, {TK_OPTION_INT, "-four", "four", "Four", "4", - Tk_Offset(FiveRecord, four), -1, 0, NULL, 0}, + offsetof(FiveRecord, four), -1, 0, NULL, 0}, {TK_OPTION_STRING, "-five", NULL, NULL, NULL, - Tk_Offset(FiveRecord, five), -1, 0, NULL, 0}, + offsetof(FiveRecord, five), -1, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "new name ?-option value ...?"); @@ -1006,22 +1016,22 @@ tables[index] = recordPtr->header.optionTable; recordPtr->header.tkwin = NULL; recordPtr->one = recordPtr->two = recordPtr->three = NULL; recordPtr->four = recordPtr->five = NULL; Tcl_SetObjResult(interp, objv[2]); - result = Tk_InitOptions(interp, (char *) recordPtr, + result = Tk_InitOptions(interp, recordPtr, recordPtr->header.optionTable, (Tk_Window) NULL); if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, + result = Tk_SetOptions(interp, recordPtr, recordPtr->header.optionTable, objc - 3, objv + 3, (Tk_Window) NULL, NULL, NULL); if (result == TCL_OK) { recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), TrivialConfigObjCmd, (ClientData) recordPtr, TrivialCmdDeletedProc); } else { - Tk_FreeConfigOptions((char *) recordPtr, + Tk_FreeConfigOptions(recordPtr, recordPtr->header.optionTable, (Tk_Window) NULL); } } if (result != TCL_OK) { ckfree(recordPtr); @@ -1034,11 +1044,11 @@ Tcl_Obj *fooObjPtr; } NotEnoughRecord; NotEnoughRecord record; static const Tk_OptionSpec errorSpecs[] = { {TK_OPTION_INT, "-foo", "foo", "Foo", "0", - Tk_Offset(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0}, + offsetof(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1); Tk_OptionTable optionTable; @@ -1046,12 +1056,12 @@ tkwin = Tk_CreateWindowFromPath(interp, mainWin, ".config", NULL); Tk_SetClass(tkwin, "Config"); optionTable = Tk_CreateOptionTable(interp, errorSpecs); tables[index] = optionTable; - Tk_InitOptions(interp, (char *) &record, optionTable, tkwin); - if (Tk_SetOptions(interp, (char *) &record, optionTable, 1, + Tk_InitOptions(interp, &record, optionTable, tkwin); + if (Tk_SetOptions(interp, &record, optionTable, 1, &newObjPtr, tkwin, NULL, NULL) != TCL_OK) { result = TCL_ERROR; } Tcl_DecrRefCount(newObjPtr); Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin); @@ -1065,15 +1075,15 @@ Tcl_Obj *windowPtr; } SlaveRecord; SlaveRecord *recordPtr; static const Tk_OptionSpec slaveSpecs[] = { {TK_OPTION_WINDOW, "-window", "window", "Window", ".bar", - Tk_Offset(SlaveRecord, windowPtr), -1, TK_CONFIG_NULL_OK, NULL, 0}, + offsetof(SlaveRecord, windowPtr), -1, TK_CONFIG_NULL_OK, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; Tk_Window tkwin = Tk_CreateWindowFromPath(interp, - (Tk_Window) clientData, Tcl_GetString(objv[2]), NULL); + clientData, Tcl_GetString(objv[2]), NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "Test"); @@ -1084,14 +1094,14 @@ slaveSpecs); tables[index] = recordPtr->header.optionTable; recordPtr->header.tkwin = tkwin; recordPtr->windowPtr = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, + result = Tk_InitOptions(interp, recordPtr, recordPtr->header.optionTable, tkwin); if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, + result = Tk_SetOptions(interp, recordPtr, recordPtr->header.optionTable, objc - 3, objv + 3, tkwin, NULL, NULL); if (result == TCL_OK) { recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), TrivialConfigObjCmd, @@ -1098,11 +1108,11 @@ recordPtr, TrivialCmdDeletedProc); Tk_CreateEventHandler(tkwin, StructureNotifyMask, TrivialEventProc, recordPtr); Tcl_SetObjResult(interp, objv[2]); } else { - Tk_FreeConfigOptions((char *) recordPtr, + Tk_FreeConfigOptions(recordPtr, recordPtr->header.optionTable, tkwin); } } if (result != TCL_OK) { Tk_DestroyWindow(tkwin); @@ -1146,11 +1156,11 @@ enum { CGET, CONFIGURE, CSAVE }; Tcl_Obj *resultObjPtr; int index, mask; - TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData; + TrivialCommandHeader *headerPtr = clientData; Tk_Window tkwin = headerPtr->tkwin; Tk_SavedOptions saved; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?"); @@ -1169,11 +1179,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; goto done; } - resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData, + resultObjPtr = Tk_GetOptionValue(interp, clientData, headerPtr->optionTable, objv[2], tkwin); if (resultObjPtr != NULL) { Tcl_SetObjResult(interp, resultObjPtr); result = TCL_OK; } else { @@ -1180,41 +1190,41 @@ result = TCL_ERROR; } break; case CONFIGURE: if (objc == 2) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, + resultObjPtr = Tk_GetOptionInfo(interp, clientData, headerPtr->optionTable, NULL, tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); } } else if (objc == 3) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, + resultObjPtr = Tk_GetOptionInfo(interp, clientData, headerPtr->optionTable, objv[2], tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); } } else { - result = Tk_SetOptions(interp, (char *) clientData, + result = Tk_SetOptions(interp, clientData, headerPtr->optionTable, objc - 2, objv + 2, tkwin, NULL, &mask); if (result == TCL_OK) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(mask)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(mask)); } } break; case CSAVE: - result = Tk_SetOptions(interp, (char *) clientData, + result = Tk_SetOptions(interp, clientData, headerPtr->optionTable, objc - 2, objv + 2, tkwin, &saved, &mask); Tk_FreeSavedOptions(&saved); if (result == TCL_OK) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(mask)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(mask)); } break; } done: Tcl_Release(clientData); @@ -1241,11 +1251,11 @@ static void TrivialCmdDeletedProc( ClientData clientData) /* Pointer to widget record for widget. */ { - TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData; + TrivialCommandHeader *headerPtr = clientData; Tk_Window tkwin = headerPtr->tkwin; if (tkwin != NULL) { Tk_DestroyWindow(tkwin); } else if (headerPtr->optionTable != NULL) { @@ -1253,12 +1263,12 @@ * This is a "new" object, which doesn't have a window, so we can't * depend on cleaning up in the event function. Free its resources * here. */ - Tk_FreeConfigOptions((char *) clientData, - headerPtr->optionTable, (Tk_Window) NULL); + Tk_FreeConfigOptions(clientData, + headerPtr->optionTable, NULL); Tcl_EventuallyFree(clientData, TCL_DYNAMIC); } } /* @@ -1280,15 +1290,15 @@ static void TrivialEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData; + TrivialCommandHeader *headerPtr = clientData; if (eventPtr->type == DestroyNotify) { if (headerPtr->tkwin != NULL) { - Tk_FreeConfigOptions((char *) clientData, + Tk_FreeConfigOptions(clientData, headerPtr->optionTable, headerPtr->tkwin); headerPtr->optionTable = NULL; headerPtr->tkwin = NULL; Tcl_DeleteCommandFromToken(headerPtr->interp, headerPtr->widgetCmd); @@ -1326,11 +1336,11 @@ enum option {COUNTS, SUBFONTS}; int index; Tk_Window tkwin; Tk_Font tkfont; - tkwin = (Tk_Window) clientData; + tkwin = clientData; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option fontName"); return TCL_ERROR; } @@ -1446,11 +1456,11 @@ ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { - TImageMaster *timPtr = (TImageMaster *) clientData; + TImageMaster *timPtr = clientData; int x, y, width, height; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; @@ -1501,11 +1511,11 @@ ImageGet( Tk_Window tkwin, /* Token for window in which image will be * used. */ ClientData clientData) /* Pointer to TImageMaster for image. */ { - TImageMaster *timPtr = (TImageMaster *) clientData; + TImageMaster *timPtr = clientData; TImageInstance *instPtr; char buffer[100]; XGCValues gcValues; sprintf(buffer, "%s get", timPtr->imageName); @@ -1548,35 +1558,46 @@ int width, int height, /* Dimensions of area to redraw. */ int drawableX, int drawableY) /* Coordinates in drawable corresponding to * imageX and imageY. */ { - TImageInstance *instPtr = (TImageInstance *) clientData; + TImageInstance *instPtr = clientData; char buffer[200 + TCL_INTEGER_SPACE * 6]; /* * The purpose of the test image type is to track the calls to an image * display proc and record the parameters passed in each call. On macOS - * these tests will fail because of the asynchronous drawing. The low - * level graphics calls below which are supposed to draw a rectangle will - * not draw anything to the screen because the idle task will not be - * processed inside of the drawRect method and hence will not be able to - * obtain a valid graphics context. Instead, the window will be marked as - * needing display, and will be redrawn during a future asynchronous call - * to drawRect. This will generate an other call to this display proc, - * and the recorded data will show extra calls, causing the test to fail. - * To avoid this, we can set the [NSApp simulateDrawing] flag, which will - * cause all low level drawing routines to return immediately and not - * schedule the window for drawing later. This flag is cleared by the - * next call to XSync, which is called by the update command. + * a display proc must be run inside of the drawRect method of an NSView + * in order for the graphics operations to have any effect. To deal with + * this, whenever a display proc is called outside of any drawRect method + * it schedules a redraw of the NSView by calling [view setNeedsDisplay:YES]. + * This will trigger a later call to the view's drawRect method which will + * run the display proc a second time. + * + * This complicates testing, since it can result in more calls to the display + * proc than are expected by the test. It can also result in an inconsistent + * number of calls unless the test waits until the call to drawRect actually + * occurs before validating its results. + * + * In an attempt to work around this, this display proc only logs those + * calls which occur within a drawRect method. This means that tests must + * be written so as to ensure that the drawRect method is run before + * results are validated. In practice it usually suffices to run update + * idletasks (to run the display proc the first time) followed by update + * (to run the display proc in drawRect). + * + * This also has the consequence that the image changed command will log + * different results on Aqua than on other systems, because when the image + * is redisplayed in the drawRect method the entire image will be drawn, + * not just the changed portion. Tests must account for this. */ - sprintf(buffer, "%s display %d %d %d %d", - instPtr->masterPtr->imageName, imageX, imageY, width, height); - if (!APP_IS_DRAWING) { + if (LOG_DISPLAY) { + sprintf(buffer, "%s display %d %d %d %d", + instPtr->masterPtr->imageName, imageX, imageY, width, height); Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, - NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); } if (width > (instPtr->masterPtr->width - imageX)) { width = instPtr->masterPtr->width - imageX; } if (height > (instPtr->masterPtr->height - imageY)) { @@ -1612,11 +1633,11 @@ static void ImageFree( ClientData clientData, /* Pointer to TImageInstance for instance. */ Display *display) /* Display where image was to be drawn. */ { - TImageInstance *instPtr = (TImageInstance *) clientData; + TImageInstance *instPtr = clientData; char buffer[200]; sprintf(buffer, "%s free", instPtr->masterPtr->imageName); Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); @@ -1646,11 +1667,11 @@ ImageDelete( ClientData clientData) /* Pointer to TImageMaster for image. When * this function is called, no more instances * exist. */ { - TImageMaster *timPtr = (TImageMaster *) clientData; + TImageMaster *timPtr = clientData; char buffer[100]; sprintf(buffer, "%s delete", timPtr->imageName); Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); @@ -1685,11 +1706,11 @@ ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { - Tk_Window mainWin = (Tk_Window) clientData; + Tk_Window mainWin = clientData; int i; Tk_Window tkwin; for (i = 1; i < objc; i++) { tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), mainWin); @@ -1728,11 +1749,11 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { #ifdef __UNIX__ - Tk_Window mainWin = (Tk_Window) clientData; + Tk_Window mainWin = clientData; Tk_Window tkwin, menubar; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; @@ -1841,11 +1862,11 @@ ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { - Tk_Window mainWin = (Tk_Window) clientData; + Tk_Window mainWin = clientData; int result, actualFormat; unsigned long bytesAfter, length, value; Atom actualType, propName; unsigned char *property, *p; char *end; @@ -1892,10 +1913,64 @@ if (property != NULL) { XFree(property); } return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * + * TestpropObjCmd -- + * + * This function implements the "testprop" command. It fetches and prints + * the value of a property on a window. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +TestprintfObjCmd( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ +{ + char buffer[256]; + Tcl_WideInt wideInt; +#ifdef _WIN32 + __int64 longLongInt; +#else + long long longLongInt; +#endif + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "wideint"); + return TCL_ERROR; + } + if (Tcl_GetWideIntFromObj(interp, objv[1], &wideInt) != TCL_OK) { + return TCL_ERROR; + } + longLongInt = wideInt; + + /* Just add a lot of arguments to sprintf. Reason: on AMD64, the first + * 4 or 6 arguments (we assume 8, just in case) might be put in registers, + * which still woudn't tell if the assumed size is correct: We want this + * test-case to fail if the 64-bit value is printed as truncated to 32-bit. + */ + sprintf(buffer, "%s%s%s%s%s%s%s%s%" TCL_LL_MODIFIER "d %" + TCL_LL_MODIFIER "u", "", "", "", "", "", "", "", "", + (Tcl_WideInt)longLongInt, (Tcl_WideUInt)longLongInt); + Tcl_AppendResult(interp, buffer, NULL); + return TCL_OK; +} #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) /* *---------------------------------------------------------------------- * @@ -1928,11 +2003,11 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "window"); return TCL_ERROR; } - tkwin = (Tk_Window) clientData; + tkwin = clientData; winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin); if (winPtr == NULL) { return TCL_ERROR; } @@ -1987,11 +2062,11 @@ int objEmpty; char *newStr, *string, *internalPtr; objEmpty = 0; - if (internalOffset >= 0) { + if (internalOffset != -1) { internalPtr = recordPtr + internalOffset; } else { internalPtr = NULL; } @@ -2063,13 +2138,61 @@ { if (*(char **)internalPtr != NULL) { ckfree(*(char **)internalPtr); } } +/* + *---------------------------------------------------------------------- + * + * TestPhotoStringMatchCmd -- + * + * This function implements the "testphotostringmatch" command. It + * provides a way from Tcl to call the string match function for the + * default image handler directly. + * + * Results: + * A standard Tcl result. If data is in the proper format, the result in + * interp will contain width and height as a list. If the data cannot be + * parsed as default image format, returns TCL_ERROR and leaves an + * appropriate error message in interp. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +TestPhotoStringMatchCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ +{ + Tcl_Obj *dummy = NULL; + Tcl_Obj *resultObj[2]; + int width, height; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "imageData"); + return TCL_ERROR; + } + if (TkDebugPhotoStringMatchDef(interp, objv[1], dummy, &width, &height)) { + resultObj[0] = Tcl_NewWideIntObj(width); + resultObj[1] = Tcl_NewWideIntObj(height); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObj)); + return TCL_OK; + } else { + return TCL_ERROR; + } +} + + /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tkText.c ================================================================== --- generic/tkText.c +++ generic/tkText.c @@ -12,13 +12,13 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" #include "tkUndo.h" +#include "default.h" #if defined(MAC_OSX_TK) #define Style TkStyle #define DInfo TkDInfo #endif @@ -120,142 +120,142 @@ */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators", "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1, - Tk_Offset(TkText, autoSeparators), + offsetof(TkText, autoSeparators), TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", - DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border), + DEF_TEXT_BG_COLOR, -1, offsetof(TkText, border), 0, DEF_TEXT_BG_MONO, 0}, {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, "-borderwidth", TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, "-background", 0}, {TK_OPTION_BOOLEAN, "-blockcursor", "blockCursor", "BlockCursor", DEF_TEXT_BLOCK_CURSOR, -1, - Tk_Offset(TkText, insertCursorType), 0, 0, 0}, + offsetof(TkText, insertCursorType), 0, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_TEXT_BORDER_WIDTH, -1, Tk_Offset(TkText, borderWidth), + DEF_TEXT_BORDER_WIDTH, -1, offsetof(TkText, borderWidth), 0, 0, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", - DEF_TEXT_CURSOR, -1, Tk_Offset(TkText, cursor), + DEF_TEXT_CURSOR, -1, offsetof(TkText, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_CUSTOM, "-endline", NULL, NULL, - NULL, -1, Tk_Offset(TkText, end), TK_OPTION_NULL_OK, + NULL, -1, offsetof(TkText, end), TK_OPTION_NULL_OK, &lineOption, TK_TEXT_LINE_RANGE}, {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_TEXT_EXPORT_SELECTION, -1, - Tk_Offset(TkText, exportSelection), 0, 0, 0}, + offsetof(TkText, exportSelection), 0, 0, 0}, {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_TEXT_FONT, -1, Tk_Offset(TkText, tkfont), 0, 0, + DEF_TEXT_FONT, -1, offsetof(TkText, tkfont), 0, 0, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_TEXT_FG, -1, Tk_Offset(TkText, fgColor), 0, + DEF_TEXT_FG, -1, offsetof(TkText, fgColor), 0, 0, 0}, {TK_OPTION_PIXELS, "-height", "height", "Height", - DEF_TEXT_HEIGHT, -1, Tk_Offset(TkText, height), 0, 0, 0}, + DEF_TEXT_HEIGHT, -1, offsetof(TkText, height), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_TEXT_HIGHLIGHT_BG, - -1, Tk_Offset(TkText, highlightBgColorPtr), + -1, offsetof(TkText, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_TEXT_HIGHLIGHT, -1, Tk_Offset(TkText, highlightColorPtr), + DEF_TEXT_HIGHLIGHT, -1, offsetof(TkText, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, -1, - Tk_Offset(TkText, highlightWidth), 0, 0, TK_TEXT_LINE_GEOMETRY}, + offsetof(TkText, highlightWidth), 0, 0, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_BORDER, "-inactiveselectbackground","inactiveSelectBackground", "Foreground", DEF_TEXT_INACTIVE_SELECT_COLOR, - -1, Tk_Offset(TkText, inactiveSelBorder), + -1, offsetof(TkText, inactiveSelBorder), TK_OPTION_NULL_OK, DEF_TEXT_SELECT_MONO, 0}, {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground", DEF_TEXT_INSERT_BG, - -1, Tk_Offset(TkText, insertBorder), + -1, offsetof(TkText, insertBorder), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_TEXT_INSERT_BD_COLOR, -1, - Tk_Offset(TkText, insertBorderWidth), 0, + offsetof(TkText, insertBorderWidth), 0, (ClientData) DEF_TEXT_INSERT_BD_MONO, 0}, {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_TEXT_INSERT_OFF_TIME, -1, Tk_Offset(TkText, insertOffTime), + DEF_TEXT_INSERT_OFF_TIME, -1, offsetof(TkText, insertOffTime), 0, 0, 0}, {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_TEXT_INSERT_ON_TIME, -1, Tk_Offset(TkText, insertOnTime), + DEF_TEXT_INSERT_ON_TIME, -1, offsetof(TkText, insertOnTime), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-insertunfocussed", "insertUnfocussed", "InsertUnfocussed", - DEF_TEXT_INSERT_UNFOCUSSED, -1, Tk_Offset(TkText, insertUnfocussed), + DEF_TEXT_INSERT_UNFOCUSSED, -1, offsetof(TkText, insertUnfocussed), 0, insertUnfocussedStrings, 0}, {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_TEXT_INSERT_WIDTH, -1, Tk_Offset(TkText, insertWidth), + DEF_TEXT_INSERT_WIDTH, -1, offsetof(TkText, insertWidth), 0, 0, 0}, {TK_OPTION_INT, "-maxundo", "maxUndo", "MaxUndo", - DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo), + DEF_TEXT_MAX_UNDO, -1, offsetof(TkText, maxUndo), TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", - DEF_TEXT_PADX, -1, Tk_Offset(TkText, padX), 0, 0, + DEF_TEXT_PADX, -1, offsetof(TkText, padX), 0, 0, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", - DEF_TEXT_PADY, -1, Tk_Offset(TkText, padY), 0, 0, 0}, + DEF_TEXT_PADY, -1, offsetof(TkText, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_TEXT_RELIEF, -1, Tk_Offset(TkText, relief), 0, 0, 0}, + DEF_TEXT_RELIEF, -1, offsetof(TkText, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_TEXT_SELECT_COLOR, -1, Tk_Offset(TkText, selBorder), + DEF_TEXT_SELECT_COLOR, -1, offsetof(TkText, selBorder), 0, DEF_TEXT_SELECT_MONO, 0}, {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_TEXT_SELECT_BD_COLOR, - Tk_Offset(TkText, selBorderWidthPtr), - Tk_Offset(TkText, selBorderWidth), + offsetof(TkText, selBorderWidthPtr), + offsetof(TkText, selBorderWidth), TK_OPTION_NULL_OK, DEF_TEXT_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr), + DEF_TEXT_SELECT_FG_COLOR, -1, offsetof(TkText, selFgColorPtr), TK_OPTION_NULL_OK, DEF_TEXT_SELECT_FG_MONO, 0}, {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid", - DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0}, + DEF_TEXT_SET_GRID, -1, offsetof(TkText, setGrid), 0, 0, 0}, {TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing", - DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1), + DEF_TEXT_SPACING1, -1, offsetof(TkText, spacing1), 0, 0 , TK_TEXT_LINE_GEOMETRY }, {TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing", - DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2), + DEF_TEXT_SPACING2, -1, offsetof(TkText, spacing2), 0, 0 , TK_TEXT_LINE_GEOMETRY }, {TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing", - DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3), + DEF_TEXT_SPACING3, -1, offsetof(TkText, spacing3), 0, 0 , TK_TEXT_LINE_GEOMETRY }, {TK_OPTION_CUSTOM, "-startline", NULL, NULL, - NULL, -1, Tk_Offset(TkText, start), TK_OPTION_NULL_OK, + NULL, -1, offsetof(TkText, start), TK_OPTION_NULL_OK, &lineOption, TK_TEXT_LINE_RANGE}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_TEXT_STATE, -1, Tk_Offset(TkText, state), + DEF_TEXT_STATE, -1, offsetof(TkText, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-tabs", "tabs", "Tabs", - DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionPtr), -1, + DEF_TEXT_TABS, offsetof(TkText, tabOptionPtr), -1, TK_OPTION_NULL_OK, 0, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_STRING_TABLE, "-tabstyle", "tabStyle", "TabStyle", - DEF_TEXT_TABSTYLE, -1, Tk_Offset(TkText, tabStyle), + DEF_TEXT_TABSTYLE, -1, offsetof(TkText, tabStyle), 0, tabStyleStrings, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_TEXT_TAKE_FOCUS, -1, Tk_Offset(TkText, takeFocus), + DEF_TEXT_TAKE_FOCUS, -1, offsetof(TkText, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-undo", "undo", "Undo", - DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo), + DEF_TEXT_UNDO, -1, offsetof(TkText, undo), TK_OPTION_DONT_SET_DEFAULT, 0 , 0}, {TK_OPTION_INT, "-width", "width", "Width", - DEF_TEXT_WIDTH, -1, Tk_Offset(TkText, width), 0, 0, + DEF_TEXT_WIDTH, -1, offsetof(TkText, width), 0, 0, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_STRING_TABLE, "-wrap", "wrap", "Wrap", - DEF_TEXT_WRAP, -1, Tk_Offset(TkText, wrapMode), + DEF_TEXT_WRAP, -1, offsetof(TkText, wrapMode), 0, wrapStrings, TK_TEXT_LINE_GEOMETRY}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_TEXT_XSCROLL_COMMAND, -1, Tk_Offset(TkText, xScrollCmd), + DEF_TEXT_XSCROLL_COMMAND, -1, offsetof(TkText, xScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - DEF_TEXT_YSCROLL_COMMAND, -1, Tk_Offset(TkText, yScrollCmd), + DEF_TEXT_YSCROLL_COMMAND, -1, offsetof(TkText, yScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0} }; /* @@ -658,11 +658,11 @@ |LeaveWindowMask|PointerMotionMask|VirtualEventMask, TkTextBindProc, textPtr); Tk_CreateSelHandler(textPtr->tkwin, XA_PRIMARY, XA_STRING, TextFetchSelection, textPtr, XA_STRING); - if (Tk_InitOptions(interp, (char *) textPtr, optionTable, textPtr->tkwin) + if (Tk_InitOptions(interp, textPtr, optionTable, textPtr->tkwin) != TCL_OK) { Tk_DestroyWindow(textPtr->tkwin); return TCL_ERROR; } if (ConfigureText(interp, textPtr, objc-2, objv+2) != TCL_OK) { @@ -746,14 +746,14 @@ } if (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height, NULL) == 0) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height)); Tcl_SetObjResult(interp, listObj); } break; } @@ -761,11 +761,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; goto done; } else { - Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *) textPtr, + Tcl_Obj *objPtr = Tk_GetOptionValue(interp, textPtr, textPtr->optionTable, objv[2], textPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; goto done; @@ -824,11 +824,11 @@ result = TCL_ERROR; goto done; } case TEXT_CONFIGURE: if (objc <= 3) { - Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) textPtr, + Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, textPtr, textPtr->optionTable, ((objc == 3) ? objv[2] : NULL), textPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; @@ -862,15 +862,14 @@ goto done; } for (i = 2; i < objc-2; i++) { int value; - size_t length; - const char *option = Tcl_GetString(objv[i]); + TkSizeT length; + const char *option = TkGetStringFromObj(objv[i], &length); char c; - length = objv[i]->length; if (length < 2 || option[0] != '-') { goto badOption; } c = option[1]; if (c == 'c' && !strncmp("-chars", option, length)) { @@ -1018,11 +1017,11 @@ } countDone: found++; if (found == 1) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(value)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value)); } else { if (found == 2) { /* * Move the first item we put into the result into the * first element of the list object. @@ -1030,11 +1029,11 @@ objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_GetObjResult(interp)); } - Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(value)); + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj(value)); } } if (found == 0) { /* @@ -1042,11 +1041,11 @@ */ int value = CountIndices(textPtr, indexFromPtr, indexToPtr, COUNT_INDICES); - Tcl_SetObjResult(interp, Tcl_NewIntObj(value)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value)); } else if (found > 1) { Tcl_SetObjResult(interp, objPtr); } break; @@ -1153,18 +1152,18 @@ TkTextIndexForwChars(NULL, &indices[i], 1, &indices[i], COUNT_INDICES); objc++; } useIdx = ckalloc(objc); - memset(useIdx, 0, (size_t) objc); + memset(useIdx, 0, objc); /* * Do a decreasing order sort so that we delete the end ranges * first to maintain index consistency. */ - qsort(indices, (size_t) objc / 2, + qsort(indices, objc / 2, 2 * sizeof(TkTextIndex), TextIndexSortProc); lastStart = NULL; /* * Second pass will handle bogus ranges (end < start) and @@ -1238,15 +1237,15 @@ } if (TkTextDLineInfo(textPtr, indexPtr, &x, &y, &width, &height, &base) == 0) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height)); - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(base)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(base)); Tcl_SetObjResult(interp, listObj); } break; } @@ -1258,11 +1257,11 @@ break; case TEXT_GET: { Tcl_Obj *objPtr = NULL; int i, found = 0, visible = 0; const char *name; - size_t length; + TkSizeT length; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "?-displaychars? ?--? index1 ?index2 ...?"); result = TCL_ERROR; @@ -1274,18 +1273,16 @@ * -displaychars (or any unique prefix). */ i = 2; if (objc > 3) { - name = Tcl_GetString(objv[i]); - length = objv[i]->length; + name = TkGetStringFromObj(objv[i], &length); if (length > 1 && name[0] == '-') { if (strncmp("-displaychars", name, length) == 0) { i++; visible = 1; - name = Tcl_GetString(objv[i]); - length = objv[i]->length; + name = TkGetStringFromObj(objv[i], &length); } if ((i < objc-1) && (length == 2) && !strcmp("--", name)) { i++; } } @@ -2632,18 +2629,17 @@ Tcl_Obj *stringPtr, /* Null-terminated string containing new * information to add to text. */ int viewUpdate) /* Update the view if set. */ { int lineIndex; - size_t length; + TkSizeT length; TkText *tPtr; int *lineAndByteIndex; int resetViewCount; int pixels[2*PIXEL_CLIENTS]; - const char *string = Tcl_GetString(stringPtr); + const char *string = TkGetStringFromObj(stringPtr, &length); - length = stringPtr->length; if (sharedTextPtr == NULL) { sharedTextPtr = textPtr->sharedTextPtr; } /* @@ -2780,10 +2776,13 @@ const TkTextIndex *index2Ptr) /* Index describing second location. */ { TkUndoSubAtom *iAtom, *dAtom; int canUndo, canRedo; + char lMarkName[20] = "tk::undoMarkL"; + char rMarkName[20] = "tk::undoMarkR"; + char stringUndoMarkId[16] = ""; /* * Create the helpers. */ @@ -2790,10 +2789,14 @@ Tcl_Obj *seeInsertObj = Tcl_NewObj(); Tcl_Obj *markSet1InsertObj = Tcl_NewObj(); Tcl_Obj *markSet2InsertObj = NULL; Tcl_Obj *insertCmdObj = Tcl_NewObj(); Tcl_Obj *deleteCmdObj = Tcl_NewObj(); + Tcl_Obj *markSetLUndoMarkCmdObj = Tcl_NewObj(); + Tcl_Obj *markSetRUndoMarkCmdObj = NULL; + Tcl_Obj *markGravityLUndoMarkCmdObj = Tcl_NewObj(); + Tcl_Obj *markGravityRUndoMarkCmdObj = NULL; /* * Get the index positions. */ @@ -2839,10 +2842,44 @@ Tcl_ListObjAppendElement(NULL, deleteCmdObj, Tcl_NewStringObj("delete", 6)); Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj); Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1)); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj("mark", 4)); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj("set", 3)); + markSetRUndoMarkCmdObj = Tcl_DuplicateObj(markSetLUndoMarkCmdObj); + textPtr->sharedTextPtr->undoMarkId++; + sprintf(stringUndoMarkId, "%d", textPtr->sharedTextPtr->undoMarkId); + strcat(lMarkName, stringUndoMarkId); + strcat(rMarkName, stringUndoMarkId); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj(lMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj, + Tcl_NewStringObj(rMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, index1Obj); + Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj, index2Obj); + + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1)); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj("mark", 4)); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj("gravity", 7)); + markGravityRUndoMarkCmdObj = Tcl_DuplicateObj(markGravityLUndoMarkCmdObj); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj(lMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj, + Tcl_NewStringObj(rMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj("left", 4)); + Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj, + Tcl_NewStringObj("right", 5)); + /* * Note: we don't wish to use textPtr->widgetCmd in these callbacks * because if we delete the textPtr, but peers still exist, we will then * have references to a non-existent Tcl_Command in the undo stack, which * will lead to crashes later. Also, the behaviour of the widget w.r.t. @@ -2856,15 +2893,23 @@ iAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr, insertCmdObj, NULL); TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom); TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, iAtom); dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr, deleteCmdObj, NULL); TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom); TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, dAtom); Tcl_DecrRefCount(seeInsertObj); Tcl_DecrRefCount(index1Obj); Tcl_DecrRefCount(index2Obj); @@ -3462,11 +3507,11 @@ } } if ((segPtr->typePtr == &tkTextCharType) && !TkTextIsElided(textPtr, &textPtr->selIndex, NULL)) { memcpy(buffer, segPtr->body.chars + offsetInSeg, - (size_t) chunkSize); + chunkSize); buffer += chunkSize; maxBytes -= chunkSize; count += chunkSize; } TkTextIndexForwBytes(textPtr, &textPtr->selIndex, chunkSize, @@ -4226,11 +4271,11 @@ int matchOffset, /* Offset of found item in utf-8 bytes for * exact search, Unicode chars for regexp. */ int matchLength) /* Length also in bytes/chars as per search * type. */ { - int numChars; + TkSizeT numChars; int leftToScan; TkTextIndex curIndex, foundIndex; TkTextSegment *segPtr; TkTextLine *linePtr; TkText *textPtr = searchSpecPtr->clientData; @@ -4266,11 +4311,11 @@ * full length fits inside the given range. */ if (searchSpecPtr->strictLimits && lineNum == searchSpecPtr->stopLine) { if (searchSpecPtr->backwards ^ - ((matchOffset + numChars) > searchSpecPtr->stopOffset)) { + ((matchOffset + numChars + 1) > (TkSizeT) searchSpecPtr->stopOffset + 1)) { return 0; } } /* @@ -4419,11 +4464,11 @@ /* * Now store the count result, if it is wanted. */ if (searchSpecPtr->varPtr != NULL) { - Tcl_Obj *tmpPtr = Tcl_NewIntObj(numChars); + Tcl_Obj *tmpPtr = Tcl_NewWideIntObj(numChars); if (searchSpecPtr->all) { if (searchSpecPtr->countPtr == NULL) { searchSpecPtr->countPtr = Tcl_NewObj(); } Tcl_ListObjAppendElement(NULL, searchSpecPtr->countPtr, tmpPtr); @@ -4706,18 +4751,17 @@ arg++; atEnd = 0; if (objc == arg) { TkTextIndexForwChars(NULL, &index1, 1, &index2, COUNT_INDICES); } else { - size_t length; + TkSizeT length; const char *str; if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) { return TCL_ERROR; } - str = Tcl_GetString(objv[arg]); - length = objv[arg]->length; + str = TkGetStringFromObj(objv[arg], &length); if (strncmp(str, "end", length) == 0) { atEnd = 1; } } if (TkTextIndexCmp(&index1, &index2) >= 0) { @@ -4925,11 +4969,11 @@ } else if ((what & TK_DUMP_WIN) && (segPtr->typePtr == &tkTextEmbWindowType)) { TkTextEmbWindow *ewPtr = &segPtr->body.ew; const char *pathname; - if (ewPtr->tkwin == (Tk_Window) NULL) { + if (ewPtr->tkwin == NULL) { pathname = ""; } else { pathname = Tk_PathName(ewPtr->tkwin); } TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, @@ -5029,11 +5073,11 @@ if (command == NULL) { Tcl_ListObjAppendList(NULL, Tcl_GetObjResult(interp), tuple); Tcl_DecrRefCount(tuple); return 0; } else { - int oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree); + TkSizeT oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree); Tcl_DString buf; int code; Tcl_DStringInit(&buf); Tcl_DStringAppend(&buf, Tcl_GetString(command), -1); @@ -5072,10 +5116,12 @@ static int TextEditUndo( TkText *textPtr) /* Overall information about text widget. */ { int status; + Tcl_Obj *cmdObj; + int code; if (!textPtr->sharedTextPtr->undo) { return TCL_OK; } @@ -5095,10 +5141,26 @@ if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } textPtr->sharedTextPtr->undo = 1; + /* + * Convert undo/redo temporary marks set by TkUndoRevert() into + * indices left in the interp result. + */ + + cmdObj = Tcl_ObjPrintf("::tk::TextUndoRedoProcessMarks %s", + Tk_PathName(textPtr->tkwin)); + Tcl_IncrRefCount(cmdObj); + code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + Tcl_AddErrorInfo(textPtr->interp, + "\n (on undoing)"); + Tcl_BackgroundException(textPtr->interp, code); + } + Tcl_DecrRefCount(cmdObj); + return status; } /* *---------------------------------------------------------------------- @@ -5120,10 +5182,12 @@ static int TextEditRedo( TkText *textPtr) /* Overall information about text widget. */ { int status; + Tcl_Obj *cmdObj; + int code; if (!textPtr->sharedTextPtr->undo) { return TCL_OK; } @@ -5142,10 +5206,27 @@ if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } textPtr->sharedTextPtr->undo = 1; + + /* + * Convert undo/redo temporary marks set by TkUndoApply() into + * indices left in the interp result. + */ + + cmdObj = Tcl_ObjPrintf("::tk::TextUndoRedoProcessMarks %s", + Tk_PathName(textPtr->tkwin)); + Tcl_IncrRefCount(cmdObj); + code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + Tcl_AddErrorInfo(textPtr->interp, + "\n (on undoing)"); + Tcl_BackgroundException(textPtr->interp, code); + } + Tcl_DecrRefCount(cmdObj); + return status; } /* *---------------------------------------------------------------------- @@ -5521,11 +5602,11 @@ void TkTextRunAfterSyncCmd( ClientData clientData) /* Information about text widget. */ { - register TkText *textPtr = (TkText *) clientData; + register TkText *textPtr = clientData; int code; if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. @@ -5539,11 +5620,11 @@ Tcl_Preserve((ClientData) textPtr->interp); code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL); if (code == TCL_ERROR) { Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); - Tcl_BackgroundError(textPtr->interp); + Tcl_BackgroundException(textPtr->interp, TCL_ERROR); } Tcl_Release((ClientData) textPtr->interp); Tcl_DecrRefCount(textPtr->afterSyncCmd); textPtr->afterSyncCmd = NULL; } @@ -5676,11 +5757,12 @@ /* * For exact searches these are utf-8 char* offsets, for regexp searches * they are Unicode char offsets. */ - int firstOffset, lastOffset, matchOffset, matchLength; + int firstOffset, lastOffset; + TkSizeT matchOffset, matchLength; int passes; int lineNum = searchSpecPtr->startLine; int code = TCL_OK; Tcl_Obj *theLine; int alreadySearchOffset = -1; @@ -5697,13 +5779,13 @@ * text lines. */ #define LOTS_OF_MATCHES 20 int matchNum = LOTS_OF_MATCHES; - int smArray[2 * LOTS_OF_MATCHES]; - int *storeMatch = smArray; - int *storeLength = smArray + LOTS_OF_MATCHES; + TkSizeT smArray[2 * LOTS_OF_MATCHES]; + TkSizeT *storeMatch = smArray; + TkSizeT *storeLength = smArray + LOTS_OF_MATCHES; int lastBackwardsLineMatch = -1; int lastBackwardsMatchOffset = -1; if (searchSpecPtr->exact) { /* @@ -5749,12 +5831,11 @@ * We only need to set the matchLength once for exact searches, and we * do it here. It is also used below as the actual pattern length, so * it has dual purpose. */ - pattern = Tcl_GetString(patObj); - matchLength = patObj->length; + pattern = TkGetStringFromObj(patObj, &matchLength); nl = strchr(pattern, '\n'); /* * If there is no newline, or it is the very end of the string, then * we don't need any special treatment, since single-line matching @@ -5875,25 +5956,25 @@ * until we find the last match in the line. The 'lastOffset' is one * beyond the last position in the line at which a match is allowed to * begin. */ - matchOffset = -1; + matchOffset = TCL_INDEX_NONE; if (searchSpecPtr->exact) { int maxExtraLines = 0; const char *startOfLine = Tcl_GetString(theLine); CLANG_ASSERT(pattern); do { int ch; const char *p; - int lastFullLine = lastOffset; + TkSizeT lastFullLine = lastOffset; if (firstNewLine == -1) { if (searchSpecPtr->strictLimits - && (firstOffset + matchLength > lastOffset)) { + && (firstOffset + matchLength + 1 > (TkSizeT)lastOffset + 1)) { /* * Not enough characters to match. */ break; @@ -5919,11 +6000,11 @@ } else { p = startOfLine + lastOffset -1; } while (p >= startOfLine + firstOffset) { if (matchLength == 0 || (p[0] == c && !strncmp( - p, pattern, (size_t) matchLength))) { + p, pattern, matchLength))) { goto backwardsMatch; } p--; } break; @@ -5948,11 +6029,11 @@ * Multi-line match has only one possible match position, * because we know where the '\n' is. */ p = startOfLine + lastOffset - firstNewLine - 1; - if (strncmp(p, pattern, (unsigned) firstNewLine + 1)) { + if (strncmp(p, pattern, firstNewLine + 1)) { /* * No match. */ break; @@ -6007,18 +6088,18 @@ /* * Use the fact that 'matchLength = patLength' for * exact searches. */ - if ((lastTotal - skipFirst) >= matchLength) { + if ((TkSizeT)lastTotal - skipFirst + 1 >= matchLength + 1) { /* * We now have enough text to match, so we * make a final test and break whatever the * result. */ - if (strncmp(p,pattern,(size_t)matchLength)) { + if (strncmp(p, pattern, matchLength)) { p = NULL; } break; } else { /* @@ -6089,11 +6170,11 @@ break; } } } else { firstOffset = matchLength ? p - startOfLine + matchLength - : p - startOfLine + 1; + : p - startOfLine + (TkSizeT)1; if (firstOffset >= lastOffset) { /* * Now, we have to be careful not to find * overlapping matches either on the same or * following lines. Assume that if we did find @@ -6129,11 +6210,11 @@ int lastNonOverlap = -1; do { Tcl_RegExpInfo info; int match; - int lastFullLine = lastOffset; + TkSizeT lastFullLine = lastOffset; match = Tcl_RegExpExecObj(interp, regexp, theLine, firstOffset, 1, (firstOffset>0 ? TCL_REG_NOTBOL : 0)); if (match < 0) { code = TCL_ERROR; @@ -6147,13 +6228,13 @@ * full greedy match. */ if (!match || ((info.extendStart == info.matches[0].start) - && (info.matches[0].end == lastOffset-firstOffset))) { + && (info.matches[0].end == (TkSizeT) (lastOffset - firstOffset)))) { int extraLines = 0; - int prevFullLine; + TkSizeT prevFullLine; /* * If we find a match that overlaps more than one line, we * will use this value to determine the first allowed * starting offset for the following search (to avoid @@ -6165,11 +6246,11 @@ if ((lastBackwardsLineMatch != -1) && (lastBackwardsLineMatch == (lineNum + 1))) { lastNonOverlap = lastTotal; } - if (info.extendStart < 0) { + if (info.extendStart == TCL_INDEX_NONE) { /* * No multi-line match is possible. */ break; @@ -6262,13 +6343,13 @@ * a correct value of info.extendStart under all * circumstances. */ if ((match && - firstOffset+info.matches[0].end != lastTotal && - firstOffset+info.matches[0].end < prevFullLine) - || info.extendStart < 0) { + firstOffset + info.matches[0].end != (TkSizeT) lastTotal && + firstOffset + info.matches[0].end + 1 < prevFullLine + 1) + || info.extendStart == TCL_INDEX_NONE) { break; } /* * If there is a match, but that match starts after @@ -6275,11 +6356,11 @@ * the end of the first line, then we'll handle that * next time around, when we're actually looking at * that line. */ - if (match && (info.matches[0].start >= lastOffset)) { + if (match && (info.matches[0].start + 1 >= (TkSizeT) lastOffset + 1)) { break; } if (match && ((firstOffset + info.matches[0].end) >= prevFullLine)) { if (extraLines > 0) { @@ -6332,12 +6413,12 @@ if (lastNonOverlap != -1) { /* * Possible overlap or enclosure. */ - if (thisOffset-lastNonOverlap >= - lastBackwardsMatchOffset+matchLength){ + if ((TkSizeT)thisOffset - lastNonOverlap >= + lastBackwardsMatchOffset + matchLength + 1){ /* * Totally encloses previous match, so * forget the previous match. */ @@ -6414,16 +6495,16 @@ * yet found anything, or if we're doing '-all' or * '-backwards' _and_ this match isn't fully enclosed in the * previous match. */ - if (matchOffset == -1 || + if (matchOffset == TCL_INDEX_NONE || ((searchSpecPtr->all || searchSpecPtr->backwards) - && ((firstOffset < matchOffset) + && (((TkSizeT)firstOffset + 1 < matchOffset + 1) || ((firstOffset + info.matches[0].end - info.matches[0].start) - > (matchOffset + matchLength))))) { + > matchOffset + matchLength)))) { matchOffset = firstOffset; matchLength = info.matches[0].end - info.matches[0].start; if (searchSpecPtr->backwards) { @@ -6437,15 +6518,15 @@ * We've run out of space in our normal store, so * we must allocate space for these backwards * matches on the heap. */ - int *newArray = - ckalloc(4 * matchNum * sizeof(int)); - memcpy(newArray, storeMatch, matchNum*sizeof(int)); + TkSizeT *newArray = + ckalloc(4 * matchNum * sizeof(TkSizeT)); + memcpy(newArray, storeMatch, matchNum*sizeof(TkSizeT)); memcpy(newArray + 2*matchNum, storeLength, - matchNum * sizeof(int)); + matchNum * sizeof(TkSizeT)); if (storeMatch != smArray) { ckfree(storeMatch); } matchNum *= 2; storeMatch = newArray; @@ -6476,11 +6557,11 @@ * For forward matches, unless we allow overlaps, we move * this on by the length of the current match so that we * explicitly disallow overlapping matches. */ - if (matchLength > 0 && !searchSpecPtr->overlap + if (matchLength + 1 > 1 && !searchSpecPtr->overlap && !searchSpecPtr->backwards) { firstOffset += matchLength; if (firstOffset >= lastOffset) { /* * Now, we have to be careful not to find @@ -6533,12 +6614,12 @@ * * might be needed here, but no test case has been * found which would exercise such a problem. */ } - if (storeMatch[matches] + storeLength[matches] - >= matchOffset + matchLength) { + if (storeMatch[matches] + storeLength[matches] + 1 + >= matchOffset + matchLength + 1) { /* * The new match totally encloses the previous one, so * we overwrite the previous one. */ @@ -6582,11 +6663,11 @@ * * If not, and there is a match we need to store that information and * we are done. */ - if ((lastBackwardsLineMatch == -1) && (matchOffset >= 0) + if ((lastBackwardsLineMatch == -1) && (matchOffset != TCL_INDEX_NONE) && !searchSpecPtr->all) { searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr, lineInfo, theLine, matchOffset, matchLength); goto searchDone; } @@ -6709,11 +6790,11 @@ TkTextLine *linePtr = *(TkTextLine **)(recordPtr + internalOffset); if (linePtr == NULL) { return Tcl_NewObj(); } - return Tcl_NewIntObj(1 + TkBTreeLinesTo(NULL, linePtr)); + return Tcl_NewWideIntObj(1 + TkBTreeLinesTo(NULL, linePtr)); } /* *---------------------------------------------------------------------- * @@ -6750,11 +6831,11 @@ TkTextLine *linePtr = NULL; char *internalPtr; TkText *textPtr = (TkText *) recordPtr; if (internalOffset >= 0) { - internalPtr = recordPtr + internalOffset; + internalPtr = (char *)recordPtr + internalOffset; } else { internalPtr = NULL; } if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) { @@ -6857,11 +6938,11 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { TkText *textPtr; - size_t len; + TkSizeT len; int lineIndex, byteIndex, byteOffset; TkTextIndex index; char buf[64]; Tcl_CmdInfo info; Index: generic/tkText.h ================================================================== --- generic/tkText.h +++ generic/tkText.h @@ -529,13 +529,21 @@ /* * A data structure of the following type is shared between each text widget * that are peers. */ + +#ifndef TkSizeT +# if TCL_MAJOR_VERSION > 8 +# define TkSizeT size_t +# else +# define TkSizeT int +# endif +#endif typedef struct TkSharedText { - int refCount; /* Reference count this shared object. */ + TkSizeT refCount; /* Reference count this shared object. */ TkTextBTree tree; /* B-tree representation of text and tags for * widget. */ Tcl_HashTable tagTable; /* Hash table that maps from tag names to * pointers to TkTextTag structures. The "sel" * tag does not feature in this table, since @@ -560,11 +568,11 @@ /* Table of all bindings currently defined for * this widget. NULL means that no bindings * exist, so the table hasn't been created. * Each "object" used for this table is the * name of a tag. */ - int stateEpoch; /* This is incremented each time the B-tree's + TkSizeT stateEpoch; /* This is incremented each time the B-tree's * contents change structurally, or when the * start/end limits change, and means that any * cached TkTextIndex objects are no longer * valid. */ @@ -578,10 +586,12 @@ int maxUndo; /* The maximum depth of the undo stack * expressed as the maximum number of compound * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ + int undoMarkId; /* Counts undo marks temporarily used during + undo and redo operations. */ int isDirty; /* Flag indicating the 'dirtyness' of the * text widget. If the flag is not zero, * unsaved modifications have been applied to * the text widget. */ TkTextDirtyMode dirtyMode; /* The nature of the dirtyness characterized @@ -779,11 +789,11 @@ * vertical scrollbar when view changes. */ int flags; /* Miscellaneous flags; see below for * definitions. */ Tk_OptionTable optionTable; /* Token representing the configuration * specifications. */ - int refCount; /* Number of cached TkTextIndex objects + TkSizeT refCount; /* Number of cached TkTextIndex objects * refering to us. */ int insertCursorType; /* 0 = standard insertion cursor, 1 = block * cursor. */ /* @@ -1005,11 +1015,11 @@ MODULE_SCOPE void TkBTreeRemoveClient(TkTextBTree tree, TkText *textPtr); MODULE_SCOPE void TkBTreeDestroy(TkTextBTree tree); MODULE_SCOPE void TkBTreeDeleteIndexRange(TkTextBTree tree, TkTextIndex *index1Ptr, TkTextIndex *index2Ptr); -MODULE_SCOPE int TkBTreeEpoch(TkTextBTree tree); +MODULE_SCOPE TkSizeT TkBTreeEpoch(TkTextBTree tree); MODULE_SCOPE TkTextLine *TkBTreeFindLine(TkTextBTree tree, const TkText *textPtr, int line); MODULE_SCOPE TkTextLine *TkBTreeFindPixelLine(TkTextBTree tree, const TkText *textPtr, int pixels, int *pixelOffset); Index: generic/tkTextBTree.c ================================================================== --- generic/tkTextBTree.c +++ generic/tkTextBTree.c @@ -103,11 +103,11 @@ typedef struct BTree { Node *rootPtr; /* Pointer to root of B-tree. */ int clients; /* Number of clients of this B-tree. */ int pixelReferences; /* Number of clients of this B-tree which care * about pixel heights. */ - int stateEpoch; /* Updated each time any aspect of the B-tree + TkSizeT stateEpoch; /* Updated each time any aspect of the B-tree * changes. */ TkSharedText *sharedTextPtr;/* Used to find tagTable in consistency * checking code, and to access list of all * B-tree clients. */ int startEndCount; @@ -138,14 +138,14 @@ /* * Macros that determine how much space to allocate for new segments: */ -#define CSEG_SIZE(chars) ((unsigned) (Tk_Offset(TkTextSegment, body) \ - + 1 + (chars))) -#define TSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \ - + sizeof(TkTextToggle))) +#define CSEG_SIZE(chars) (offsetof(TkTextSegment, body) \ + + 1 + (chars)) +#define TSEG_SIZE (offsetof(TkTextSegment, body) \ + + sizeof(TkTextToggle)) /* * Forward declarations for functions defined in this file: */ @@ -499,11 +499,11 @@ * None. * *---------------------------------------------------------------------- */ -int +TkSizeT TkBTreeEpoch( TkTextBTree tree) /* Tree to get epoch for. */ { BTree *treePtr = (BTree *) tree; return treePtr->stateEpoch; @@ -1019,11 +1019,11 @@ * insert at beginning of line. */ TkTextLine *linePtr; /* Current line (new segments are added to * this line). */ register TkTextSegment *segPtr; TkTextLine *newLinePtr; - int chunkSize; /* # characters in current chunk. */ + size_t chunkSize; /* # characters in current chunk. */ register const char *eol; /* Pointer to character just after last one in * current chunk. */ int changeToLineCount; /* Counts change to total number of lines in * file. */ int *changeToPixelCount; /* Counts change to total number of pixels in @@ -1068,11 +1068,11 @@ } else { segPtr->nextPtr = curPtr->nextPtr; curPtr->nextPtr = segPtr; } segPtr->size = chunkSize; - memcpy(segPtr->body.chars, string, (size_t) chunkSize); + memcpy(segPtr->body.chars, string, chunkSize); segPtr->body.chars[chunkSize] = 0; if (eol[-1] != '\n') { break; } @@ -4561,11 +4561,11 @@ newPtr1 = ckalloc(CSEG_SIZE(index)); newPtr2 = ckalloc(CSEG_SIZE(segPtr->size - index)); newPtr1->typePtr = &tkTextCharType; newPtr1->nextPtr = newPtr2; newPtr1->size = index; - memcpy(newPtr1->body.chars, segPtr->body.chars, (size_t) index); + memcpy(newPtr1->body.chars, segPtr->body.chars, index); newPtr1->body.chars[index] = 0; newPtr2->typePtr = &tkTextCharType; newPtr2->nextPtr = segPtr->nextPtr; newPtr2->size = segPtr->size - index; memcpy(newPtr2->body.chars, segPtr->body.chars + index, newPtr2->size); Index: generic/tkTextDisp.c ================================================================== --- generic/tkTextDisp.c +++ generic/tkTextDisp.c @@ -14,16 +14,10 @@ */ #include "tkInt.h" #include "tkText.h" -#ifdef _WIN32 -#include "tkWinInt.h" -#elif defined(__CYGWIN__) -#include "tkUnixInt.h" -#endif - #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #define OK_TO_LOG (!TkpAppIsDrawing()) #define FORCE_DISPLAY(winPtr) TkpDisplayWindow(winPtr) #else @@ -171,11 +165,11 @@ * graphics contexts used to actually draw the characters. The entries in * dInfoPtr->styleTable point to structures of this type. */ typedef struct TextStyle { - int refCount; /* Number of times this structure is + TkSizeT refCount; /* Number of times this structure is * referenced in Chunks. */ GC bgGC; /* Graphics context for background. None means * use widget background. */ GC fgGC; /* Graphics context for foreground. */ GC ulGC; /* Graphics context for underline. */ @@ -418,11 +412,11 @@ * into very many display lines, then this is * used to keep track of what index we've got * to so far... */ int metricPixelHeight; /* ...and this is for the height calculation * so far...*/ - int metricEpoch; /* ...and this for the epoch of the partial + TkSizeT metricEpoch; /* ...and this for the epoch of the partial * calculation so it can be cancelled if * things change once more. This field will be * -1 if there is no long-line calculation in * progress, and take a non-negative value if * there is such a calculation in progress. */ @@ -624,11 +618,11 @@ int *intPtr); static void AsyncUpdateLineMetrics(ClientData clientData); static void GenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync); static void AsyncUpdateYScrollbar(ClientData clientData); static int IsStartOfNotMergedLine(TkText *textPtr, - CONST TkTextIndex *indexPtr); + const TkTextIndex *indexPtr); /* * Result values returned by TextGetScrollInfoObj: */ @@ -1072,12 +1066,11 @@ FreeStyle( TkText *textPtr, /* Information about overall widget. */ register TextStyle *stylePtr) /* Information about style to free. */ { - stylePtr->refCount--; - if (stylePtr->refCount == 0) { + if (stylePtr->refCount-- <= 1) { if (stylePtr->bgGC != NULL) { Tk_FreeGC(textPtr->display, stylePtr->bgGC); } if (stylePtr->fgGC != NULL) { Tk_FreeGC(textPtr->display, stylePtr->fgGC); @@ -3064,11 +3057,11 @@ /* * If we're not in the middle of a long-line calculation (metricEpoch==-1) * and we've reached the last line, then we're done. */ - if (dInfoPtr->metricEpoch == -1 + if (dInfoPtr->metricEpoch == TCL_AUTO_LENGTH && lineNum == dInfoPtr->lastMetricUpdateLine) { /* * We have looped over all lines, so we're done. We must release our * refCount on the widget (the timer token was already set to NULL * above). If there is a registered aftersync command, run that first. @@ -3082,11 +3075,11 @@ Tcl_Preserve((ClientData) textPtr->interp); code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL); if (code == TCL_ERROR) { Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); - Tcl_BackgroundError(textPtr->interp); + Tcl_BackgroundException(textPtr->interp, TCL_ERROR); } Tcl_Release((ClientData) textPtr->interp); Tcl_DecrRefCount(textPtr->afterSyncCmd); textPtr->afterSyncCmd = NULL; } @@ -3248,11 +3241,12 @@ /* * If we're in the middle of a partial-line height calculation, * then we can't be done. */ - if (textPtr->dInfoPtr->metricEpoch == -1 && lineNum == endLine) { + if (textPtr->dInfoPtr->metricEpoch == TCL_AUTO_LENGTH && lineNum == endLine) { + /* * We have looped over all lines, so we're done. */ @@ -6157,11 +6151,11 @@ * objv[1] is "yview". */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; int pickPlace, type; int pixels, count; - int switchLength; + TkSizeT switchLength; double fraction; TkTextIndex index; if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { UpdateDisplayInfo(textPtr); @@ -6176,12 +6170,12 @@ * Next, handle the old syntax: "pathName yview ?-pickplace? where" */ pickPlace = 0; if (Tcl_GetString(objv[2])[0] == '-') { - register const char *switchStr = - Tcl_GetStringFromObj(objv[2], &switchLength); + const char *switchStr = + TkGetStringFromObj(objv[2], &switchLength); if ((switchLength >= 2) && (strncmp(switchStr, "-pickplace", (unsigned) switchLength) == 0)) { pickPlace = 1; if (objc != 4) { @@ -6986,11 +6980,11 @@ */ static int IsStartOfNotMergedLine( TkText *textPtr, /* Widget record for text widget. */ - CONST TkTextIndex *indexPtr) /* Index to check. */ + const TkTextIndex *indexPtr) /* Index to check. */ { TkTextIndex indexPtr2; if (indexPtr->byteIndex != 0) { /* @@ -7761,13 +7755,13 @@ chunkPtr->minHeight = 0; chunkPtr->width = nextX - chunkPtr->x; chunkPtr->breakIndex = -1; #if !TK_LAYOUT_WITH_BASE_CHUNKS - ciPtr = ckalloc((Tk_Offset(CharInfo, chars) + 1) + bytesThatFit); + ciPtr = ckalloc(offsetof(CharInfo, chars) + 1 + bytesThatFit); chunkPtr->clientData = ciPtr; - memcpy(ciPtr->chars, p, (unsigned) bytesThatFit); + memcpy(ciPtr->chars, p, bytesThatFit); #endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ ciPtr->numBytes = bytesThatFit; if (p[bytesThatFit - 1] == '\n') { ciPtr->numBytes--; @@ -8774,14 +8768,14 @@ }; enum viewSubcmds { VIEW_MOVETO, VIEW_SCROLL }; static const char *const units[] = { - "units", "pages", "pixels", NULL + "pages", "pixels", "units", NULL }; enum viewUnits { - VIEW_SCROLL_UNITS, VIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS + VIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS, VIEW_SCROLL_UNITS }; int index; if (Tcl_GetIndexFromObjStruct(interp, objv[2], subcommands, sizeof(char *), "option", 0, &index) != TCL_OK) { @@ -8798,11 +8792,11 @@ return TKTEXT_SCROLL_ERROR; } return TKTEXT_SCROLL_MOVETO; case VIEW_SCROLL: if (objc != 5) { - Tcl_WrongNumArgs(interp, 3, objv, "number units|pages|pixels"); + Tcl_WrongNumArgs(interp, 3, objv, "number pages|pixels|units"); return TKTEXT_SCROLL_ERROR; } if (Tcl_GetIndexFromObjStruct(interp, objv[4], units, sizeof(char *), "argument", 0, &index) != TCL_OK) { return TKTEXT_SCROLL_ERROR; Index: generic/tkTextImage.c ================================================================== --- generic/tkTextImage.c +++ generic/tkTextImage.c @@ -16,11 +16,11 @@ /* * Macro that determines the size of an embedded image segment: */ #define EI_SEG_SIZE \ - ((unsigned) (Tk_Offset(TkTextSegment, body) + sizeof(TkTextEmbImage))) + (offsetof(TkTextSegment, body) + sizeof(TkTextEmbImage)) /* * Prototypes for functions defined in this file: */ @@ -81,21 +81,21 @@ * Information used for parsing image configuration options: */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING_TABLE, "-align", NULL, NULL, - "center", -1, Tk_Offset(TkTextEmbImage, align), + "center", -1, offsetof(TkTextEmbImage, align), 0, alignStrings, 0}, {TK_OPTION_PIXELS, "-padx", NULL, NULL, - "0", -1, Tk_Offset(TkTextEmbImage, padX), 0, 0, 0}, + "0", -1, offsetof(TkTextEmbImage, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", NULL, NULL, - "0", -1, Tk_Offset(TkTextEmbImage, padY), 0, 0, 0}, + "0", -1, offsetof(TkTextEmbImage, padY), 0, 0, 0}, {TK_OPTION_STRING, "-image", NULL, NULL, - NULL, -1, Tk_Offset(TkTextEmbImage, imageString), + NULL, -1, offsetof(TkTextEmbImage, imageString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-name", NULL, NULL, - NULL, -1, Tk_Offset(TkTextEmbImage, imageName), + NULL, -1, offsetof(TkTextEmbImage, imageName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /* @@ -159,11 +159,11 @@ "no embedded image at index \"%s\"", Tcl_GetString(objv[3]))); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_IMAGE", NULL); return TCL_ERROR; } - objPtr = Tk_GetOptionValue(interp, (char *) &eiPtr->body.ei, + objPtr = Tk_GetOptionValue(interp, &eiPtr->body.ei, eiPtr->body.ei.optionTable, objv[4], textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } else { Tcl_SetObjResult(interp, objPtr); @@ -186,11 +186,11 @@ Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_IMAGE", NULL); return TCL_ERROR; } if (objc <= 5) { Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, - (char *) &eiPtr->body.ei, eiPtr->body.ei.optionTable, + &eiPtr->body.ei, eiPtr->body.ei.optionTable, (objc == 5) ? objv[4] : NULL, textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } else { @@ -335,11 +335,11 @@ int dummy; int count = 0; /* The counter for picking a unique name */ int conflict = 0; /* True if we have a name conflict */ size_t len; /* length of image name */ - if (Tk_SetOptions(textPtr->interp, (char *) &eiPtr->body.ei, + if (Tk_SetOptions(textPtr->interp, &eiPtr->body.ei, eiPtr->body.ei.optionTable, objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) { return TCL_ERROR; } Index: generic/tkTextIndex.c ================================================================== --- generic/tkTextIndex.c +++ generic/tkTextIndex.c @@ -9,13 +9,13 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" #include "tkText.h" +#include "default.h" /* * Index to use to select last character in line (very large integer): */ @@ -38,13 +38,13 @@ static const char * StartEnd(TkText *textPtr, const char *string, TkTextIndex *indexPtr); static int GetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr, TkText *textPtr, const char *string, TkTextIndex *indexPtr, int *canCachePtr); -static int IndexCountBytesOrdered(CONST TkText *textPtr, - CONST TkTextIndex *indexPtr1, - CONST TkTextIndex *indexPtr2); +static int IndexCountBytesOrdered(const TkText *textPtr, + const TkTextIndex *indexPtr1, + const TkTextIndex *indexPtr2); /* * The "textindex" Tcl_Obj definition: */ @@ -62,11 +62,11 @@ #define GET_INDEXEPOCH(objPtr) \ (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2)) #define SET_TEXTINDEX(objPtr, indexPtr) \ ((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (indexPtr)) #define SET_INDEXEPOCH(objPtr, epoch) \ - ((objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(epoch)) + ((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (size_t) (epoch)) /* * Define the 'textindex' object type, which Tk uses to represent indices in * text widgets internally. */ @@ -102,11 +102,11 @@ static void DupTextIndexInternalRep( Tcl_Obj *srcPtr, /* TextIndex obj with internal rep to copy. */ Tcl_Obj *copyPtr) /* TextIndex obj with internal rep to set. */ { - int epoch; + TkSizeT epoch; TkTextIndex *dupIndexPtr, *indexPtr; dupIndexPtr = ckalloc(sizeof(TkTextIndex)); indexPtr = GET_TEXTINDEX(srcPtr); epoch = GET_INDEXEPOCH(srcPtr); @@ -204,11 +204,11 @@ TkTextIndex index; TkTextIndex *indexPtr = NULL; int cache; if (objPtr->typePtr == &tkTextIndexType) { - int epoch; + TkSizeT epoch; indexPtr = GET_TEXTINDEX(objPtr); epoch = GET_INDEXEPOCH(objPtr); if (epoch == textPtr->sharedTextPtr->stateEpoch) { @@ -921,11 +921,11 @@ goto gotBase; } } if ((string[0] == 'e') && (strncmp(string, "end", - (size_t) (endOfBase-Tcl_DStringValue(©))) == 0)) { + endOfBase-Tcl_DStringValue(©)) == 0)) { /* * Base position is end of text. */ TkTextMakeByteIndex(sharedPtr->tree, textPtr, @@ -1634,13 +1634,13 @@ *--------------------------------------------------------------------------- */ int TkTextIndexCountBytes( - CONST TkText *textPtr, - CONST TkTextIndex *indexPtr1, /* Index describing one location. */ - CONST TkTextIndex *indexPtr2) /* Index describing second location. */ + const TkText *textPtr, + const TkTextIndex *indexPtr1, /* Index describing one location. */ + const TkTextIndex *indexPtr2) /* Index describing second location. */ { int compare = TkTextIndexCmp(indexPtr1, indexPtr2); if (compare == 0) { return 0; @@ -1651,15 +1651,15 @@ } } static int IndexCountBytesOrdered( - CONST TkText *textPtr, - CONST TkTextIndex *indexPtr1, + const TkText *textPtr, + const TkTextIndex *indexPtr1, /* Index describing location of character from * which to count. */ - CONST TkTextIndex *indexPtr2) + const TkTextIndex *indexPtr2) /* Index describing location of last character * at which to stop the count. */ { int byteCount, offset; TkTextSegment *segPtr, *segPtr1; Index: generic/tkTextMark.c ================================================================== --- generic/tkTextMark.c +++ generic/tkTextMark.c @@ -17,12 +17,12 @@ /* * Macro that determines the size of a mark segment: */ -#define MSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \ - + sizeof(TkTextMark))) +#define MSEG_SIZE (offsetof(TkTextSegment, body) \ + + sizeof(TkTextMark)) /* * Forward references for functions defined in this file: */ @@ -124,18 +124,18 @@ } switch ((enum markOptions) optionIndex) { case MARK_GRAVITY: { char c; - int length; + TkSizeT length; const char *str; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "markName ?gravity?"); return TCL_ERROR; } - str = Tcl_GetStringFromObj(objv[3], &length); + str = TkGetStringFromObj(objv[3], &length); if (length == 6 && !strcmp(str, "insert")) { markPtr = textPtr->insertMarkPtr; } else if (length == 7 && !strcmp(str, "current")) { markPtr = textPtr->currentMarkPtr; } else { @@ -158,16 +158,16 @@ typeStr = "left"; } Tcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, -1)); return TCL_OK; } - str = Tcl_GetStringFromObj(objv[4],&length); + str = TkGetStringFromObj(objv[4],&length); c = str[0]; - if ((c == 'l') && (strncmp(str, "left", (unsigned) length) == 0)) { + if ((c == 'l') && (strncmp(str, "left", length) == 0)) { newTypePtr = &tkTextLeftMarkType; } else if ((c == 'r') && - (strncmp(str, "right", (unsigned) length) == 0)) { + (strncmp(str, "right", length) == 0)) { newTypePtr = &tkTextRightMarkType; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad mark gravity \"%s\": must be left or right", str)); Tcl_SetErrorCode(interp, "TK", "VALUE", "MARK_GRAVITY", NULL); Index: generic/tkTextTag.c ================================================================== --- generic/tkTextTag.c +++ generic/tkTextTag.c @@ -10,13 +10,13 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" #include "tkText.h" +#include "default.h" /* * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap * option of tags in a Text widget. These values are used as indices into the * string table below. Tags are allowed an empty wrap value, but the widget as @@ -38,70 +38,70 @@ "tabular", "wordprocessor", "", NULL }; static const Tk_OptionSpec tagOptionSpecs[] = { {TK_OPTION_BORDER, "-background", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BITMAP, "-bgstipple", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", NULL, NULL, - NULL, Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth), + NULL, offsetof(TkTextTag, borderWidthPtr), offsetof(TkTextTag, borderWidth), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_STRING, "-elide", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, elideString), + NULL, -1, offsetof(TkTextTag, elideString), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_BITMAP, "-fgstipple", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_FONT, "-font", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-foreground", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-justify", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0,0}, + NULL, -1, offsetof(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0,0}, {TK_OPTION_STRING, "-lmargin1", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, lMargin1String), TK_OPTION_NULL_OK,0,0}, + NULL, -1, offsetof(TkTextTag, lMargin1String), TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-lmargin2", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, lMargin2String), TK_OPTION_NULL_OK,0,0}, + NULL, -1, offsetof(TkTextTag, lMargin2String), TK_OPTION_NULL_OK,0,0}, {TK_OPTION_BORDER, "-lmargincolor", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-offset", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-overstrike", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, overstrikeString), + NULL, -1, offsetof(TkTextTag, overstrikeString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-overstrikefg", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, overstrikeColor), + NULL, -1, offsetof(TkTextTag, overstrikeColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-relief", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-rmargin", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0,0}, + NULL, -1, offsetof(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0,0}, {TK_OPTION_BORDER, "-rmargincolor", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-selectforeground", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-spacing1", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0}, + NULL, -1, offsetof(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-spacing2", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, spacing2String), TK_OPTION_NULL_OK,0,0}, + NULL, -1, offsetof(TkTextTag, spacing2String), TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-spacing3", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, spacing3String), TK_OPTION_NULL_OK,0,0}, + NULL, -1, offsetof(TkTextTag, spacing3String), TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-tabs", NULL, NULL, - NULL, Tk_Offset(TkTextTag, tabStringPtr), -1, TK_OPTION_NULL_OK, 0, 0}, + NULL, offsetof(TkTextTag, tabStringPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-tabstyle", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, tabStyle), + NULL, -1, offsetof(TkTextTag, tabStyle), TK_OPTION_NULL_OK, tabStyleStrings, 0}, {TK_OPTION_STRING, "-underline", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, underlineString), + NULL, -1, offsetof(TkTextTag, underlineString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-underlinefg", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, underlineColor), + NULL, -1, offsetof(TkTextTag, underlineColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL, - NULL, -1, Tk_Offset(TkTextTag, wrapMode), + NULL, -1, offsetof(TkTextTag, wrapMode), TK_OPTION_NULL_OK, wrapStrings, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /* @@ -290,11 +290,11 @@ (ClientData) tagPtr->name, Tcl_GetString(objv[4]), fifth, append); if (mask == 0) { return TCL_ERROR; } - if (mask & (unsigned long) ~(ButtonMotionMask|Button1MotionMask + if (mask & ~(unsigned long)(ButtonMotionMask|Button1MotionMask |Button2MotionMask|Button3MotionMask|Button4MotionMask |Button5MotionMask|ButtonPressMask|ButtonReleaseMask |EnterWindowMask|LeaveWindowMask|KeyPressMask |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) { Tk_DeleteBinding(interp, textPtr->sharedTextPtr->bindingTable, @@ -341,11 +341,11 @@ tagPtr = FindTag(interp, textPtr, objv[3]); if (tagPtr == NULL) { return TCL_ERROR; } - objPtr = Tk_GetOptionValue(interp, (char *) tagPtr, + objPtr = Tk_GetOptionValue(interp, tagPtr, tagPtr->optionTable, objv[4], textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); @@ -360,11 +360,11 @@ "tagName ?-option? ?value? ?-option value ...?"); return TCL_ERROR; } tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), &newTag); if (objc <= 5) { - Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) tagPtr, + Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, tagPtr, tagPtr->optionTable, (objc == 5) ? objv[4] : NULL, textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; @@ -372,11 +372,11 @@ Tcl_SetObjResult(interp, objPtr); return TCL_OK; } else { int result = TCL_OK; - if (Tk_SetOptions(interp, (char *) tagPtr, tagPtr->optionTable, + if (Tk_SetOptions(interp, tagPtr, tagPtr->optionTable, objc-4, objv+4, textPtr->tkwin, NULL, NULL) != TCL_OK) { return TCL_ERROR; } /* @@ -1106,14 +1106,14 @@ * message. */ TkText *textPtr, /* Widget in which tag is being used. */ Tcl_Obj *tagName) /* Name of desired tag. */ { Tcl_HashEntry *hPtr; - int len; + TkSizeT len; const char *str; - str = Tcl_GetStringFromObj(tagName, &len); + str = TkGetStringFromObj(tagName, &len); if (len == 3 && !strcmp(str, "sel")) { return textPtr->selTagPtr; } hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable, Tcl_GetString(tagName)); @@ -1444,13 +1444,10 @@ XEvent *eventPtr) /* Pointer to X event that just happened. */ { TkText *textPtr = clientData; int repick = 0; -# define AnyButtonMask \ - (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask) - textPtr->refCount++; /* * This code simulates grabs for mouse buttons by keeping track of whether * a button is pressed and refusing to pick a new current character while @@ -1460,45 +1457,26 @@ if (eventPtr->type == ButtonPress) { textPtr->flags |= BUTTON_DOWN; } else if (eventPtr->type == ButtonRelease) { unsigned long mask; - switch (eventPtr->xbutton.button) { - case Button1: - mask = Button1Mask; - break; - case Button2: - mask = Button2Mask; - break; - case Button3: - mask = Button3Mask; - break; - case Button4: - mask = Button4Mask; - break; - case Button5: - mask = Button5Mask; - break; - default: - mask = 0; - break; - } - if ((eventPtr->xbutton.state & AnyButtonMask) == mask) { + mask = TkGetButtonMask(eventPtr->xbutton.button); + if ((eventPtr->xbutton.state & ALL_BUTTONS) == mask) { textPtr->flags &= ~BUTTON_DOWN; repick = 1; } } else if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) { - if (eventPtr->xcrossing.state & AnyButtonMask) { + if (eventPtr->xcrossing.state & ALL_BUTTONS) { textPtr->flags |= BUTTON_DOWN; } else { textPtr->flags &= ~BUTTON_DOWN; } TkTextPickCurrent(textPtr, eventPtr); goto done; } else if (eventPtr->type == MotionNotify) { - if (eventPtr->xmotion.state & AnyButtonMask) { + if (eventPtr->xmotion.state & ALL_BUTTONS) { textPtr->flags |= BUTTON_DOWN; } else { textPtr->flags &= ~BUTTON_DOWN; } TkTextPickCurrent(textPtr, eventPtr); @@ -1511,12 +1489,11 @@ } if (repick) { unsigned int oldState; oldState = eventPtr->xbutton.state; - eventPtr->xbutton.state &= ~(Button1Mask|Button2Mask - |Button3Mask|Button4Mask|Button5Mask); + eventPtr->xbutton.state &= ~(unsigned long)ALL_BUTTONS; if (!(textPtr->flags & DESTROYED)) { TkTextPickCurrent(textPtr, eventPtr); } eventPtr->xbutton.state = oldState; } @@ -1561,11 +1538,12 @@ TkTextIndex index; TkTextTag **oldArrayPtr, **newArrayPtr; TkTextTag **copyArrayPtr = NULL; /* Initialization needed to prevent compiler * warning. */ - int numOldTags, numNewTags, i, j, size, nearby; + int numOldTags, numNewTags, i, j, nearby; + size_t size; XEvent event; /* * If a button is down, then don't do anything at all; we'll be called * again when all buttons are up, and we can repick then. This implements @@ -1654,11 +1632,11 @@ SortTags(textPtr->numCurTags, textPtr->curTagArrayPtr); if (numNewTags > 0) { size = numNewTags * sizeof(TkTextTag *); copyArrayPtr = ckalloc(size); - memcpy(copyArrayPtr, newArrayPtr, (size_t) size); + memcpy(copyArrayPtr, newArrayPtr, size); for (i = 0; i < textPtr->numCurTags; i++) { for (j = 0; j < numNewTags; j++) { if (textPtr->curTagArrayPtr[i] == copyArrayPtr[j]) { textPtr->curTagArrayPtr[i] = NULL; copyArrayPtr[j] = NULL; Index: generic/tkTextWind.c ================================================================== --- generic/tkTextWind.c +++ generic/tkTextWind.c @@ -33,12 +33,12 @@ /* * Macro that determines the size of an embedded window segment: */ -#define EW_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \ - + sizeof(TkTextEmbWindow))) +#define EW_SEG_SIZE (offsetof(TkTextSegment, body) \ + + sizeof(TkTextEmbWindow)) /* * Prototypes for functions defined in this file: */ @@ -97,22 +97,22 @@ * Information used for parsing window configuration options: */ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING_TABLE, "-align", NULL, NULL, - "center", -1, Tk_Offset(TkTextEmbWindow, align), + "center", -1, offsetof(TkTextEmbWindow, align), 0, alignStrings, 0}, {TK_OPTION_STRING, "-create", NULL, NULL, - NULL, -1, Tk_Offset(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-padx", NULL, NULL, - "0", -1, Tk_Offset(TkTextEmbWindow, padX), 0, 0, 0}, + "0", -1, offsetof(TkTextEmbWindow, padX), 0, 0, 0}, {TK_OPTION_PIXELS, "-pady", NULL, NULL, - "0", -1, Tk_Offset(TkTextEmbWindow, padY), 0, 0, 0}, + "0", -1, offsetof(TkTextEmbWindow, padY), 0, 0, 0}, {TK_OPTION_BOOLEAN, "-stretch", NULL, NULL, - "0", -1, Tk_Offset(TkTextEmbWindow, stretch), 0, 0, 0}, + "0", -1, offsetof(TkTextEmbWindow, stretch), 0, 0, 0}, {TK_OPTION_WINDOW, "-window", NULL, NULL, - NULL, -1, Tk_Offset(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, offsetof(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /* *-------------------------------------------------------------- @@ -189,11 +189,11 @@ ewPtr->body.ew.tkwin = client->tkwin; } else { ewPtr->body.ew.tkwin = NULL; } - objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew, + objPtr = Tk_GetOptionValue(interp, &ewPtr->body.ew, ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); @@ -231,11 +231,11 @@ ewPtr->body.ew.tkwin = client->tkwin; } else { ewPtr->body.ew.tkwin = NULL; } - objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew, + objPtr = Tk_GetOptionInfo(interp, &ewPtr->body.ew, ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL, textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } @@ -401,11 +401,11 @@ } else { ewPtr->body.ew.tkwin = NULL; } oldWindow = ewPtr->body.ew.tkwin; - if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew, + if (Tk_SetOptions(textPtr->interp, &ewPtr->body.ew, ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) { return TCL_ERROR; } Index: generic/tkUtil.c ================================================================== --- generic/tkUtil.c +++ generic/tkUtil.c @@ -666,11 +666,11 @@ } else if ((c == 's') && (strncmp(argv[2], "scroll", length) == 0)) { if (argc != 5) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s %s %s\"", - argv[0], argv[1], "scroll number units|pages")); + argv[0], argv[1], "scroll number pages|units")); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); return TK_SCROLL_ERROR; } if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) { return TK_SCROLL_ERROR; @@ -682,11 +682,11 @@ } else if ((c == 'u') && (strncmp(argv[4], "units", length) == 0)) { return TK_SCROLL_UNITS; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad argument \"%s\": must be units or pages", argv[4])); + "bad argument \"%s\": must be pages or units", argv[4])); Tcl_SetErrorCode(interp, "TK", "VALUE", "SCROLL_UNITS", NULL); return TK_SCROLL_ERROR; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown option \"%s\": must be moveto or scroll", argv[2])); @@ -727,12 +727,12 @@ double *dblPtr, /* Filled in with argument "moveto" option, if * any. */ int *intPtr) /* Filled in with number of pages or lines to * scroll, if any. */ { - const char *arg = Tcl_GetString(objv[2]); - size_t length = objv[2]->length; + TkSizeT length; + const char *arg = TkGetStringFromObj(objv[2], &length); #define ArgPfxEq(str) \ ((arg[0] == str[0]) && !strncmp(arg, str, length)) if (ArgPfxEq("moveto")) { @@ -744,27 +744,26 @@ return TK_SCROLL_ERROR; } return TK_SCROLL_MOVETO; } else if (ArgPfxEq("scroll")) { if (objc != 5) { - Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages"); + Tcl_WrongNumArgs(interp, 2, objv, "scroll number pages|units"); return TK_SCROLL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) { return TK_SCROLL_ERROR; } - arg = Tcl_GetString(objv[4]); - length = objv[4]->length; + arg = TkGetStringFromObj(objv[4], &length); if (ArgPfxEq("pages")) { return TK_SCROLL_PAGES; } else if (ArgPfxEq("units")) { return TK_SCROLL_UNITS; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad argument \"%s\": must be units or pages", arg)); + "bad argument \"%s\": must be pages or units", arg)); Tcl_SetErrorCode(interp, "TK", "VALUE", "SCROLL_UNITS", NULL); return TK_SCROLL_ERROR; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown option \"%s\": must be moveto or scroll", arg)); @@ -1185,11 +1184,11 @@ event.general.xany.send_event = False; event.general.xany.window = Tk_WindowId(target); event.general.xany.display = Tk_Display(target); event.virtual.name = Tk_GetUid(eventName); if (detail != NULL) { - event.virtual.user_data = detail; + event.virtual.user_data = detail; } Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL); } @@ -1211,24 +1210,24 @@ * None. * *--------------------------------------------------------------------------- */ -int +size_t TkUtfToUniChar( const char *src, /* The UTF-8 string. */ int *chPtr) /* Filled with the Tcl_UniChar represented by * the UTF-8 string. */ { Tcl_UniChar uniChar = 0; - int len = Tcl_UtfToUniChar(src, &uniChar); + size_t len = Tcl_UtfToUniChar(src, &uniChar); if ((uniChar & 0xfc00) == 0xd800) { Tcl_UniChar high = uniChar; /* This can only happen if Tcl is compiled with TCL_UTF_MAX=4, * or when a high surrogate character is detected in UTF-8 form */ - int len2 = Tcl_UtfToUniChar(src+len, &uniChar); + size_t len2 = Tcl_UtfToUniChar(src+len, &uniChar); if ((uniChar & 0xfc00) == 0xdc00) { *chPtr = (((high & 0x3ff) << 10) | (uniChar & 0x3ff)) + 0x10000; len += len2; } else { *chPtr = high; @@ -1255,13 +1254,13 @@ * None. * *--------------------------------------------------------------------------- */ -int TkUniCharToUtf(int ch, char *buf) +size_t TkUniCharToUtf(int ch, char *buf) { - int size = Tcl_UniCharToUtf(ch, buf); + size_t size = Tcl_UniCharToUtf(ch, buf); if ((((unsigned)(ch - 0x10000) <= 0xFFFFF)) && (size < 4)) { /* Hey, this is wrong, we must be running TCL_UTF_MAX==3 * The best thing we can do is spit out 2 surrogates */ ch -= 0x10000; size = Tcl_UniCharToUtf(((ch >> 10) | 0xd800), buf); @@ -1270,12 +1269,25 @@ return size; } #endif + +#if TCL_MAJOR_VERSION > 8 +unsigned char * +TkGetByteArrayFromObj( + Tcl_Obj *objPtr, + size_t *lengthPtr +) { + unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, NULL); + *lengthPtr = *(size_t *) objPtr->internalRep.twoPtrValue.ptr1; + return result; +} +#endif /* TCL_MAJOR_VERSION > 8 */ + /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tkVisual.c ================================================================== --- generic/tkVisual.c +++ generic/tkVisual.c @@ -19,13 +19,13 @@ * associated X class symbols. */ typedef struct VisualDictionary { const char *name; /* Textual name of class. */ - int minLength; /* Minimum # characters that must be specified + unsigned short minLength; /* Minimum # characters that must be specified * for an unambiguous match. */ - int class; /* X symbol for class. */ + short class; /* X symbol for class. */ } VisualDictionary; static const VisualDictionary visualNames[] = { {"best", 1, 0}, {"directcolor", 2, DirectColor}, {"grayscale", 1, GrayScale}, @@ -44,11 +44,11 @@ */ struct TkColormap { Colormap colormap; /* X's identifier for the colormap. */ Visual *visual; /* Visual for which colormap was allocated. */ - int refCount; /* How many uses of the colormap are still + size_t refCount; /* How many uses of the colormap are still * outstanding (calls to Tk_GetColormap minus * calls to Tk_FreeColormap). */ int shareable; /* 0 means this colormap was allocated by a * call to Tk_GetColormap with "new", implying * that the window wants it all for itself. 1 @@ -97,11 +97,11 @@ { Tk_Window tkwin2; XVisualInfo template, *visInfoList, *bestPtr; long mask; Visual *visual; - ptrdiff_t length; + size_t length; int c, numVisuals, prio, bestPrio, i; const char *p; const VisualDictionary *dictPtr; TkColormap *cmapPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -135,11 +135,11 @@ *colormapPtr = Tk_Colormap(tkwin2); for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == *colormapPtr) { - cmapPtr->refCount += 1; + cmapPtr->refCount++; break; } } } return visual; @@ -193,12 +193,11 @@ } length = p - string; template.class = -1; for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) { if ((dictPtr->name[0] == c) && (length >= dictPtr->minLength) - && (strncmp(string, dictPtr->name, - (size_t) length) == 0)) { + && (strncmp(string, dictPtr->name, length) == 0)) { template.class = dictPtr->class; break; } } if (template.class == -1) { @@ -322,11 +321,11 @@ } else { for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->shareable && (cmapPtr->visual == visual)) { *colormapPtr = cmapPtr->colormap; - cmapPtr->refCount += 1; + cmapPtr->refCount++; goto done; } } cmapPtr = ckalloc(sizeof(TkColormap)); cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin), @@ -425,11 +424,11 @@ */ for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == colormap) { - cmapPtr->refCount += 1; + cmapPtr->refCount++; } } return colormap; } @@ -474,12 +473,11 @@ Tcl_Panic("unknown display passed to Tk_FreeColormap"); } for (prevPtr = NULL, cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; prevPtr = cmapPtr, cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == colormap) { - cmapPtr->refCount -= 1; - if (cmapPtr->refCount == 0) { + if (cmapPtr->refCount-- <= 1) { XFreeColormap(display, colormap); if (prevPtr == NULL) { dispPtr->cmapPtr = cmapPtr->nextPtr; } else { prevPtr->nextPtr = cmapPtr->nextPtr; @@ -532,11 +530,11 @@ Tcl_Panic("unknown display passed to Tk_PreserveColormap"); } for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == colormap) { - cmapPtr->refCount += 1; + cmapPtr->refCount++; return; } } } Index: generic/tkWindow.c ================================================================== --- generic/tkWindow.c +++ generic/tkWindow.c @@ -35,11 +35,11 @@ int flags; struct TkWindow *winPtr; struct TkHalfdeadWindow *nextPtr; } TkHalfdeadWindow; -typedef struct ThreadSpecificData { +typedef struct { int numMainWindows; /* Count of numver of main windows currently * open in this thread. */ TkMainInfo *mainWindowList; /* First in list of all main windows managed * by this thread. */ @@ -334,13 +334,15 @@ /* * Create built-in photo image formats. */ + Tk_CreatePhotoImageFormat(&tkImgFmtDefault); Tk_CreatePhotoImageFormat(&tkImgFmtGIF); Tk_CreatePhotoImageFormat(&tkImgFmtPNG); Tk_CreatePhotoImageFormat(&tkImgFmtPPM); + Tk_CreatePhotoImageFormat(&tkImgFmtSVGnano); } if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) { dispPtr = ((TkWindow *) parent)->dispPtr; screenId = Tk_ScreenNumber(parent); @@ -662,10 +664,12 @@ winPtr->numTags = 0; winPtr->optionLevel = -1; winPtr->selHandlerList = NULL; winPtr->geomMgrPtr = NULL; winPtr->geomData = NULL; + winPtr->geomMgrName = NULL; + winPtr->maintainerPtr = NULL; winPtr->reqWidth = winPtr->reqHeight = 1; winPtr->internalBorderLeft = 0; winPtr->wmInfoPtr = NULL; winPtr->classProcsPtr = NULL; winPtr->instanceData = NULL; @@ -673,11 +677,10 @@ winPtr->internalBorderRight = 0; winPtr->internalBorderTop = 0; winPtr->internalBorderBottom = 0; winPtr->minReqWidth = 0; winPtr->minReqHeight = 0; - winPtr->geometryMaster = NULL; return winPtr; } /* @@ -849,11 +852,11 @@ /* * Create the basic TkWindow structure. */ - tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName, + tkwin = CreateTopLevelWindow(interp, NULL, baseName, screenName, /* flags */ 0); if (tkwin == NULL) { return NULL; } @@ -947,11 +950,11 @@ Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name); } } /* - * Set variables for the intepreter. + * Set variables for the interpreter. */ Tcl_SetVar2(interp, "tk_patchLevel", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "tk_version", NULL, TK_VERSION, TCL_GLOBAL_ONLY); @@ -1133,11 +1136,11 @@ { #define FIXED_SPACE 5 char fixedSpace[FIXED_SPACE+1]; char *p; Tk_Window parent; - int numChars; + size_t numChars; /* * Strip the parent's name out of pathName (it's everything up to the last * dot). There are two tricky parts: (a) must copy the parent's name * somewhere else to avoid modifying the pathName string (for large names, @@ -1150,21 +1153,21 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad window path name \"%s\"", pathName)); Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW_PATH", NULL); return NULL; } - numChars = (int) (p-pathName); + numChars = p-pathName; if (numChars > FIXED_SPACE) { p = ckalloc(numChars + 1); } else { p = fixedSpace; } if (numChars == 0) { *p = '.'; p[1] = '\0'; } else { - strncpy(p, pathName, (size_t) numChars); + strncpy(p, pathName, numChars); p[numChars] = '\0'; } /* * Find the parent window. @@ -1440,11 +1443,11 @@ XDestroyWindow(winPtr->display, winPtr->window); } #endif Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->winTable, - (char *) winPtr->window)); + winPtr->window)); winPtr->window = None; } UnlinkWindow(winPtr); TkEventDeadWindow(winPtr); #ifdef TK_USE_INPUT_METHODS @@ -1458,13 +1461,13 @@ TkFreeBindingTags(winPtr); } TkOptionDeadWindow(winPtr); TkSelDeadWindow(winPtr); TkGrabDeadWindow(winPtr); - if (winPtr->geometryMaster != NULL) { - ckfree(winPtr->geometryMaster); - winPtr->geometryMaster = NULL; + if (winPtr->geomMgrName != NULL) { + ckfree(winPtr->geomMgrName); + winPtr->geomMgrName = NULL; } if (winPtr->mainPtr != NULL) { if (winPtr->pathName != NULL) { Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable, winPtr->pathName); @@ -2359,11 +2362,11 @@ } if (window == None) { return NULL; } - hPtr = Tcl_FindHashEntry(&dispPtr->winTable, (char *) window); + hPtr = Tcl_FindHashEntry(&dispPtr->winTable, window); if (hPtr == NULL) { return NULL; } return Tcl_GetHashValue(hPtr); } @@ -2831,11 +2834,11 @@ static HMODULE tkcygwindll = NULL; /* * Run Tk_MainEx from libtk8.?.dll * - * This function is only ever called from wish8.4.exe, the cygwin port of Tcl. + * This function is only ever called from wish8.?.exe, the cygwin port of Tcl. * This means that the system encoding is utf-8, so we don't have to do any * encoding conversions. */ int @@ -2846,20 +2849,20 @@ /* Application-specific initialization * procedure to call after most initialization * but before starting to execute commands. */ Tcl_Interp *interp) { - TCHAR name[MAX_PATH]; - int len; + WCHAR name[MAX_PATH]; + size_t len; void (*tkmainex)(int, char **, Tcl_AppInitProc *, Tcl_Interp *); /* construct "/libtk8.?.dll", from "/tk8?.dll" */ len = GetModuleFileNameW(Tk_GetHINSTANCE(), name, MAX_PATH); - name[len-2] = TEXT('.'); + name[len-2] = '.'; name[len-1] = name[len-5]; - _tcscpy(name+len, TEXT(".dll")); - memcpy(name+len-8, TEXT("libtk8"), 6 * sizeof(TCHAR)); + wcscpy(name+len, L".dll"); + memcpy(name+len-8, L"libtk8", 6 * sizeof(WCHAR)); tkcygwindll = LoadLibrary(name); if (!tkcygwindll) { /* dll is not present */ return 0; @@ -3057,14 +3060,20 @@ /* * Ensure that we are getting a compatible version of Tcl. */ - if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) { return TCL_ERROR; } + /* + * TIP #59: Make embedded configuration information available. + */ + + TkInitEmbeddedConfigurationInformation(interp); + /* * Ensure that our obj-types are registered with the Tcl runtime. */ TkRegisterObjTypes(); @@ -3167,11 +3176,11 @@ } if (code == TCL_OK) { Tcl_SetVar2Ex(interp, "argv", NULL, Tcl_NewListObj(objc-1, rest+1), TCL_GLOBAL_ONLY); Tcl_SetVar2Ex(interp, "argc", NULL, - Tcl_NewIntObj(objc-1), TCL_GLOBAL_ONLY); + Tcl_NewWideIntObj(objc-1), TCL_GLOBAL_ONLY); ckfree(rest); } Tcl_DecrRefCount(parseList); if (code != TCL_OK) { goto done; @@ -3199,12 +3208,12 @@ /* * The -class argument is always the ToTitle of the -name */ { - int numBytes; - const char *bytes = Tcl_GetStringFromObj(nameObj, &numBytes); + TkSizeT numBytes; + const char *bytes = TkGetStringFromObj(nameObj, &numBytes); classObj = Tcl_NewStringObj(bytes, numBytes); numBytes = Tcl_UtfToTitle(Tcl_GetString(classObj)); Tcl_SetObjLength(classObj, numBytes); Index: generic/ttk/ttkBlink.c ================================================================== --- generic/ttk/ttkBlink.c +++ generic/ttk/ttkBlink.c @@ -12,11 +12,11 @@ * * TODO: * Add script-level access to configure application-wide blink rate. */ -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #define DEF_CURSOR_ON_TIME 600 /* milliseconds */ #define DEF_CURSOR_OFF_TIME 300 /* milliseconds */ @@ -66,11 +66,11 @@ * Timer handler to blink the insert cursor on and off. */ static void CursorBlinkProc(ClientData clientData) { - CursorManager *cm = (CursorManager*)clientData; + CursorManager *cm = clientData; int blinkTime; if (cm->owner->flags & CURSOR_ON) { cm->owner->flags &= ~CURSOR_ON; blinkTime = cm->offTime; Index: generic/ttk/ttkButton.c ================================================================== --- generic/ttk/ttkButton.c +++ generic/ttk/ttkButton.c @@ -2,12 +2,11 @@ * Copyright (c) 2003, Joe English * * label, button, checkbutton, radiobutton, and menubutton widgets. */ -#include -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" /* Bit fields for OptionSpec mask field: */ @@ -21,10 +20,11 @@ { /* * Text element resources: */ Tcl_Obj *textObj; + Tcl_Obj *justifyObj; Tcl_Obj *textVariableObj; Tcl_Obj *underlineObj; Tcl_Obj *widthObj; Ttk_TraceHandle *textVariableTrace; @@ -54,46 +54,49 @@ BasePart base; } Base; static Tk_OptionSpec BaseOptionSpecs[] = { + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "left", offsetof(Base,base.justifyObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-text", "text", "Text", "", - Tk_Offset(Base,base.textObj), -1, + offsetof(Base,base.textObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", "", - Tk_Offset(Base,base.textVariableObj), -1, + offsetof(Base,base.textVariableObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_INT, "-underline", "underline", "Underline", - "-1", Tk_Offset(Base,base.underlineObj), -1, + "-1", offsetof(Base,base.underlineObj), -1, 0,0,0 }, /* SB: OPTION_INT, see <> */ {TK_OPTION_STRING, "-width", "width", "Width", - NULL, Tk_Offset(Base,base.widthObj), -1, + NULL, offsetof(Base,base.widthObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, /* * Image options */ {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/, - Tk_Offset(Base,base.imageObj), -1, + offsetof(Base,base.imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, /* * Compound base/image options */ {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - "none", Tk_Offset(Base,base.compoundObj), -1, + "none", offsetof(Base,base.compoundObj), -1, 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-padding", "padding", "Pad", - NULL, Tk_Offset(Base,base.paddingObj), -1, + NULL, offsetof(Base,base.paddingObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED}, /* * Compatibility/legacy options */ {TK_OPTION_STRING, "-state", "state", "State", - "normal", Tk_Offset(Base,base.stateObj), -1, + "normal", offsetof(Base,base.stateObj), -1, 0,0,STATE_CHANGED }, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -227,32 +230,32 @@ } Label; static Tk_OptionSpec LabelOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "frameColor", "FrameColor", - NULL, Tk_Offset(Label,label.backgroundObj), -1, + NULL, offsetof(Label,label.backgroundObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", - NULL, Tk_Offset(Label,label.foregroundObj), -1, + NULL, offsetof(Label,label.foregroundObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_FONT, "-font", "font", "Font", - NULL, Tk_Offset(Label,label.fontObj), -1, + NULL, offsetof(Label,label.fontObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - NULL, Tk_Offset(Label,label.borderWidthObj), -1, + NULL, offsetof(Label,label.borderWidthObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - NULL, Tk_Offset(Label,label.reliefObj), -1, + NULL, offsetof(Label,label.reliefObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - NULL, Tk_Offset(Label,label.anchorObj), -1, + NULL, offsetof(Label,label.anchorObj), -1, TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - NULL, Tk_Offset(Label, label.justifyObj), -1, + NULL, offsetof(Label, label.justifyObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", - NULL, Tk_Offset(Label, label.wrapLengthObj), -1, + NULL, offsetof(Label, label.wrapLengthObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED /*SB: SIZE_CHANGED*/ }, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) }; @@ -310,13 +313,13 @@ * Option specifications: */ static Tk_OptionSpec ButtonOptionSpecs[] = { {TK_OPTION_STRING, "-command", "command", "Command", - "", Tk_Offset(Button, button.commandObj), -1, 0,0,0}, + "", offsetof(Button, button.commandObj), -1, 0,0,0}, {TK_OPTION_STRING_TABLE, "-default", "default", "Default", - "normal", Tk_Offset(Button, button.defaultStateObj), -1, + "normal", offsetof(Button, button.defaultStateObj), -1, 0, (ClientData) ttkDefaultStrings, DEFAULTSTATE_CHANGED}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) }; @@ -420,20 +423,20 @@ * Option specifications: */ static Tk_OptionSpec CheckbuttonOptionSpecs[] = { {TK_OPTION_STRING, "-variable", "variable", "Variable", - NULL, Tk_Offset(Checkbutton, checkbutton.variableObj), -1, + NULL, offsetof(Checkbutton, checkbutton.variableObj), -1, TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-onvalue", "onValue", "OnValue", - "1", Tk_Offset(Checkbutton, checkbutton.onValueObj), -1, + "1", offsetof(Checkbutton, checkbutton.onValueObj), -1, 0,0,0}, {TK_OPTION_STRING, "-offvalue", "offValue", "OffValue", - "0", Tk_Offset(Checkbutton, checkbutton.offValueObj), -1, + "0", offsetof(Checkbutton, checkbutton.offValueObj), -1, 0,0,0}, {TK_OPTION_STRING, "-command", "command", "Command", - "", Tk_Offset(Checkbutton, checkbutton.commandObj), -1, + "", offsetof(Checkbutton, checkbutton.commandObj), -1, 0,0,0}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) }; @@ -489,11 +492,11 @@ CheckbuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask) { Checkbutton *checkPtr = recordPtr; Tcl_Obj *varName = checkPtr->checkbutton.variableObj; Ttk_TraceHandle *vt = NULL; - + if (varName != NULL && *Tcl_GetString(varName) != '\0') { vt = Ttk_TraceVariable(interp, varName, CheckbuttonVariableChanged, checkPtr); if (!vt) { return TCL_ERROR; @@ -628,17 +631,17 @@ * Option specifications: */ static Tk_OptionSpec RadiobuttonOptionSpecs[] = { {TK_OPTION_STRING, "-variable", "variable", "Variable", - "::selectedButton", Tk_Offset(Radiobutton, radiobutton.variableObj),-1, + "::selectedButton", offsetof(Radiobutton, radiobutton.variableObj),-1, 0,0,0}, {TK_OPTION_STRING, "-value", "Value", "Value", - "1", Tk_Offset(Radiobutton, radiobutton.valueObj), -1, + "1", offsetof(Radiobutton, radiobutton.valueObj), -1, 0,0,0}, {TK_OPTION_STRING, "-command", "command", "Command", - "", Tk_Offset(Radiobutton, radiobutton.commandObj), -1, + "", offsetof(Radiobutton, radiobutton.commandObj), -1, 0,0,0}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) }; @@ -803,13 +806,13 @@ "above", "below", "left", "right", "flush", NULL }; static Tk_OptionSpec MenubuttonOptionSpecs[] = { {TK_OPTION_STRING, "-menu", "menu", "Menu", - "", Tk_Offset(Menubutton, menubutton.menuObj), -1, 0,0,0}, + "", offsetof(Menubutton, menubutton.menuObj), -1, 0,0,0}, {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction", - "below", Tk_Offset(Menubutton, menubutton.directionObj), -1, + "below", offsetof(Menubutton, menubutton.directionObj), -1, 0,(ClientData)directionStrings,GEOMETRY_CHANGED}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) }; Index: generic/ttk/ttkCache.c ================================================================== --- generic/ttk/ttkCache.c +++ generic/ttk/ttkCache.c @@ -26,12 +26,11 @@ * * @@@ Colormap flashing on PseudoColor visuals is still possible, * but this will be a transient effect. */ -#include /* for sprintf */ -#include +#include "tkInt.h" #include "ttkTheme.h" struct Ttk_ResourceCache_ { Tcl_Interp *interp; /* Interpreter for error reporting */ Tk_Window tkwin; /* Cache window. */ Index: generic/ttk/ttkClamTheme.c ================================================================== --- generic/ttk/ttkClamTheme.c +++ generic/ttk/ttkClamTheme.c @@ -2,15 +2,15 @@ * Copyright (C) 2004 Joe English * * "clam" theme; inspired by the XFCE family of Gnome themes. */ -#include +#include "tkInt.h" #include "ttkTheme.h" -/* - * Under windows, the Tk-provided XDrawLine and XDrawArc have an +/* + * Under windows, the Tk-provided XDrawLine and XDrawArc have an * off-by-one error in the end point. This is especially apparent with this * theme. Defining this macro as true handles this case. */ #if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK) # define WIN32_XDRAWLINE_HACK 1 @@ -106,27 +106,27 @@ Tcl_Obj *borderWidthObj; /* See <> */ } BorderElement; static Ttk_ElementOptionSpec BorderElementOptions[] = { { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR }, + offsetof(BorderElement,borderColorObj), DARKEST_COLOR }, { "-lightcolor", TK_OPTION_COLOR, - Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR }, + offsetof(BorderElement,lightColorObj), LIGHT_COLOR }, { "-darkcolor", TK_OPTION_COLOR, - Tk_Offset(BorderElement,darkColorObj), DARK_COLOR }, + offsetof(BorderElement,darkColorObj), DARK_COLOR }, { "-relief", TK_OPTION_RELIEF, - Tk_Offset(BorderElement,reliefObj), "flat" }, + offsetof(BorderElement,reliefObj), "flat" }, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(BorderElement,borderWidthObj), "2" }, + offsetof(BorderElement,borderWidthObj), "2" }, { NULL, 0, 0, NULL } }; /* * <>: -borderwidth is only partially supported: * in this theme, borders are always exactly 2 pixels thick. - * With -borderwidth 0, border is not drawn at all; - * otherwise a 2-pixel border is used. For -borderwidth > 2, + * With -borderwidth 0, border is not drawn at all; + * otherwise a 2-pixel border is used. For -borderwidth > 2, * the excess is used as padding. */ static void BorderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -196,17 +196,17 @@ Tcl_Obj *backgroundObj; } FieldElement; static Ttk_ElementOptionSpec FieldElementOptions[] = { { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR }, + offsetof(FieldElement,borderColorObj), DARKEST_COLOR }, { "-lightcolor", TK_OPTION_COLOR, - Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR }, + offsetof(FieldElement,lightColorObj), LIGHT_COLOR }, { "-darkcolor", TK_OPTION_COLOR, - Tk_Offset(FieldElement,darkColorObj), DARK_COLOR }, + offsetof(FieldElement,darkColorObj), DARK_COLOR }, { "-fieldbackground", TK_OPTION_BORDER, - Tk_Offset(FieldElement,backgroundObj), "white" }, + offsetof(FieldElement,backgroundObj), "white" }, { NULL, 0, 0, NULL } }; static void FieldElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -278,21 +278,21 @@ Tcl_Obj *lowerColorObj; } IndicatorElement; static Ttk_ElementOptionSpec IndicatorElementOptions[] = { { "-indicatorsize", TK_OPTION_PIXELS, - Tk_Offset(IndicatorElement,sizeObj), "10" }, + offsetof(IndicatorElement,sizeObj), "10" }, { "-indicatormargin", TK_OPTION_STRING, - Tk_Offset(IndicatorElement,marginObj), "1" }, + offsetof(IndicatorElement,marginObj), "1" }, { "-indicatorbackground", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,backgroundObj), "white" }, + offsetof(IndicatorElement,backgroundObj), "white" }, { "-indicatorforeground", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,foregroundObj), "black" }, + offsetof(IndicatorElement,foregroundObj), "black" }, { "-upperbordercolor", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR }, + offsetof(IndicatorElement,upperColorObj), DARKEST_COLOR }, { "-lowerbordercolor", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR }, + offsetof(IndicatorElement,lowerColorObj), DARK_COLOR }, { NULL, 0, 0, NULL } }; static void IndicatorElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -400,17 +400,17 @@ } MenuIndicatorElement; static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = { { "-arrowsize", TK_OPTION_PIXELS, - Tk_Offset(MenuIndicatorElement,sizeObj), + offsetof(MenuIndicatorElement,sizeObj), STR(MENUBUTTON_ARROW_SIZE)}, { "-arrowcolor",TK_OPTION_COLOR, - Tk_Offset(MenuIndicatorElement,colorObj), + offsetof(MenuIndicatorElement,colorObj), "black" }, { "-arrowpadding",TK_OPTION_STRING, - Tk_Offset(MenuIndicatorElement,paddingObj), + offsetof(MenuIndicatorElement,paddingObj), "3" }, { NULL, 0, 0, NULL } }; static void MenuIndicatorElementSize( @@ -469,15 +469,15 @@ Tcl_Obj *gripCountObj; } GripElement; static Ttk_ElementOptionSpec GripElementOptions[] = { { "-lightcolor", TK_OPTION_COLOR, - Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR }, + offsetof(GripElement,lightColorObj), LIGHT_COLOR }, { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR }, + offsetof(GripElement,borderColorObj), DARKEST_COLOR }, { "-gripcount", TK_OPTION_INT, - Tk_Offset(GripElement,gripCountObj), "5" }, + offsetof(GripElement,gripCountObj), "5" }, { NULL, 0, 0, NULL } }; static void GripElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -554,29 +554,29 @@ Tcl_Obj *sliderlengthObj; } ScrollbarElement; static Ttk_ElementOptionSpec ScrollbarElementOptions[] = { { "-orient", TK_OPTION_ANY, - Tk_Offset(ScrollbarElement, orientObj), "horizontal" }, + offsetof(ScrollbarElement, orientObj), "horizontal" }, { "-background", TK_OPTION_BORDER, - Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR }, + offsetof(ScrollbarElement,backgroundObj), FRAME_COLOR }, { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR }, + offsetof(ScrollbarElement,borderColorObj), DARKEST_COLOR }, { "-troughcolor", TK_OPTION_COLOR, - Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR }, + offsetof(ScrollbarElement,troughColorObj), DARKER_COLOR }, { "-lightcolor", TK_OPTION_COLOR, - Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR }, + offsetof(ScrollbarElement,lightColorObj), LIGHT_COLOR }, { "-darkcolor", TK_OPTION_COLOR, - Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR }, + offsetof(ScrollbarElement,darkColorObj), DARK_COLOR }, { "-arrowcolor", TK_OPTION_COLOR, - Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" }, + offsetof(ScrollbarElement,arrowColorObj), "#000000" }, { "-arrowsize", TK_OPTION_PIXELS, - Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) }, + offsetof(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) }, { "-gripcount", TK_OPTION_INT, - Tk_Offset(ScrollbarElement,gripCountObj), "5" }, + offsetof(ScrollbarElement,gripCountObj), "5" }, { "-sliderlength", TK_OPTION_INT, - Tk_Offset(ScrollbarElement,sliderlengthObj), "30" }, + offsetof(ScrollbarElement,sliderlengthObj), "30" }, { NULL, 0, 0, NULL } }; static void TroughElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -628,11 +628,11 @@ */ Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient); Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount); lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d); darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d); - + if (orient == TTK_ORIENT_HORIZONTAL) { dx = 1; dy = 0; x1 = x2 = b.x + b.width / 2 - gripCount; y1 = b.y + 2; y2 = b.y + b.height - 3 + w; @@ -708,16 +708,16 @@ static void PbarElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned state) { ScrollbarElement *sb = elementRecord; - + b = Ttk_PadBox(b, Ttk_UniformPadding(2)); if (b.width > 4 && b.height > 4) { DrawSmoothBorder(tkwin, d, b, sb->borderColorObj, sb->lightColorObj, sb->darkColorObj); - XFillRectangle(Tk_Display(tkwin), d, + XFillRectangle(Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj), b.x+2, b.y+2, b.width-4, b.height-4); } } @@ -778,12 +778,12 @@ }; /*------------------------------------------------------------------------ * +++ Notebook elements. - * - * Note: Tabs, except for the rightmost, overlap the neighbor to + * + * Note: Tabs, except for the rightmost, overlap the neighbor to * their right by one pixel. */ typedef struct { Tcl_Obj *backgroundObj; @@ -792,17 +792,17 @@ Tcl_Obj *darkColorObj; } NotebookElement; static Ttk_ElementOptionSpec NotebookElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR }, + offsetof(NotebookElement,backgroundObj), FRAME_COLOR }, { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR }, + offsetof(NotebookElement,borderColorObj), DARKEST_COLOR }, { "-lightcolor", TK_OPTION_COLOR, - Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR }, + offsetof(NotebookElement,lightColorObj), LIGHT_COLOR }, { "-darkcolor", TK_OPTION_COLOR, - Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR }, + offsetof(NotebookElement,darkColorObj), DARK_COLOR }, { NULL, 0, 0, NULL } }; static void TabElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, Index: generic/ttk/ttkClassicTheme.c ================================================================== --- generic/ttk/ttkClassicTheme.c +++ generic/ttk/ttkClassicTheme.c @@ -21,13 +21,13 @@ Tcl_Obj *highlightThicknessObj; } HighlightElement; static Ttk_ElementOptionSpec HighlightElementOptions[] = { { "-highlightcolor",TK_OPTION_COLOR, - Tk_Offset(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND }, + offsetof(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND }, { "-highlightthickness",TK_OPTION_PIXELS, - Tk_Offset(HighlightElement,highlightThicknessObj), "0" }, + offsetof(HighlightElement,highlightThicknessObj), "0" }, { NULL, 0, 0, NULL } }; static void HighlightElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -64,11 +64,11 @@ HighlightElementDraw }; /*------------------------------------------------------------------------ * +++ Button Border element: - * + * * The Motif-style button border on X11 consists of (from outside-in): * * + focus indicator (controlled by -highlightcolor and -highlightthickness), * + default ring (if -default active; blank if -default normal) * + shaded border (controlled by -background, -borderwidth, and -relief) @@ -81,18 +81,18 @@ Tcl_Obj *defaultStateObj; } ButtonBorderElement; static Ttk_ElementOptionSpec ButtonBorderElementOptions[] = { - { "-background", TK_OPTION_BORDER, - Tk_Offset(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND }, - { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, - { "-relief", TK_OPTION_RELIEF, - Tk_Offset(ButtonBorderElement,reliefObj), "flat" }, - { "-default", TK_OPTION_ANY, - Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" }, + { "-background", TK_OPTION_BORDER, + offsetof(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, + offsetof(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { "-relief", TK_OPTION_RELIEF, + offsetof(ButtonBorderElement,reliefObj), "flat" }, + { "-default", TK_OPTION_ANY, + offsetof(ButtonBorderElement,defaultStateObj), "disabled" }, { NULL, 0, 0, NULL } }; static void ButtonBorderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -111,11 +111,11 @@ *paddingPtr = Ttk_UniformPadding((short)borderWidth); } /* * (@@@ Note: ButtonBorderElement still still still buggy: - * padding for default ring is drawn in the wrong color + * padding for default ring is drawn in the wrong color * when the button is active.) */ static void ButtonBorderElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) @@ -195,17 +195,17 @@ Tcl_Obj *reliefObj; } ArrowElement; static Ttk_ElementOptionSpec ArrowElementOptions[] = { - { "-arrowsize", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,sizeObj), + { "-arrowsize", TK_OPTION_PIXELS, offsetof(ArrowElement,sizeObj), DEFAULT_ARROW_SIZE }, - { "-background", TK_OPTION_BORDER, Tk_Offset(ArrowElement,borderObj), + { "-background", TK_OPTION_BORDER, offsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND }, - { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,borderWidthObj), + { "-borderwidth", TK_OPTION_PIXELS, offsetof(ArrowElement,borderWidthObj), DEFAULT_BORDERWIDTH }, - { "-relief", TK_OPTION_RELIEF, Tk_Offset(ArrowElement,reliefObj),"raised" }, + { "-relief", TK_OPTION_RELIEF, offsetof(ArrowElement,reliefObj),"raised" }, { NULL, 0, 0, NULL } }; static void ArrowElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -277,23 +277,23 @@ /*------------------------------------------------------------------------ * +++ Sash element (for ttk::panedwindow) * - * NOTES: + * NOTES: * * panedwindows with -orient horizontal use vertical sashes, and vice versa. * * Interpretation of -sashrelief 'groove' and 'ridge' are * swapped wrt. the core panedwindow, which (I think) has them backwards. * - * Default -sashrelief is sunken; the core panedwindow has default + * Default -sashrelief is sunken; the core panedwindow has default * -sashrelief raised, but that looks wrong to me. */ static Ttk_Orient SashClientData[] = { - TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL + TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL }; typedef struct { Tcl_Obj *borderObj; /* background color */ Tcl_Obj *sashReliefObj; /* sash relief */ @@ -302,22 +302,22 @@ Tcl_Obj *handleSizeObj; /* handle width and height */ Tcl_Obj *handlePadObj; /* handle's distance from edge */ } SashElement; static Ttk_ElementOptionSpec SashOptions[] = { - { "-background", TK_OPTION_BORDER, - Tk_Offset(SashElement,borderObj), DEFAULT_BACKGROUND }, - { "-sashrelief", TK_OPTION_RELIEF, - Tk_Offset(SashElement,sashReliefObj), "sunken" }, + { "-background", TK_OPTION_BORDER, + offsetof(SashElement,borderObj), DEFAULT_BACKGROUND }, + { "-sashrelief", TK_OPTION_RELIEF, + offsetof(SashElement,sashReliefObj), "sunken" }, { "-sashthickness", TK_OPTION_PIXELS, - Tk_Offset(SashElement,sashThicknessObj), "6" }, - { "-sashpad", TK_OPTION_PIXELS, - Tk_Offset(SashElement,sashPadObj), "2" }, + offsetof(SashElement,sashThicknessObj), "6" }, + { "-sashpad", TK_OPTION_PIXELS, + offsetof(SashElement,sashPadObj), "2" }, { "-handlesize", TK_OPTION_PIXELS, - Tk_Offset(SashElement,handleSizeObj), "8" }, + offsetof(SashElement,handleSizeObj), "8" }, { "-handlepad", TK_OPTION_PIXELS, - Tk_Offset(SashElement,handlePadObj), "8" }, + offsetof(SashElement,handlePadObj), "8" }, { NULL, 0, 0, NULL } }; static void SashElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -363,14 +363,14 @@ break; case TK_RELIEF_SUNKEN: case TK_RELIEF_GROOVE: gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); break; - case TK_RELIEF_SOLID: + case TK_RELIEF_SOLID: gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); break; - case TK_RELIEF_FLAT: + case TK_RELIEF_FLAT: default: gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC); break; } @@ -394,11 +394,11 @@ hb.x += handlePad; } else { hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_N); hb.y += handlePad; } - Tk_Fill3DRectangle(tkwin, d, border, + Tk_Fill3DRectangle(tkwin, d, border, hb.x, hb.y, hb.width, hb.height, 1, TK_RELIEF_RAISED); } } static Ttk_ElementSpec SashElementSpec = { @@ -491,11 +491,11 @@ Ttk_RegisterElement(interp, theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]); Ttk_RegisterElement(interp, theme, "arrow", &ArrowElementSpec, &ArrowElements[0]); - Ttk_RegisterElement(interp, theme, "hsash", + Ttk_RegisterElement(interp, theme, "hsash", &SashElementSpec, &SashClientData[0]); Ttk_RegisterElement(interp, theme, "vsash", &SashElementSpec, &SashClientData[1]); /* Index: generic/ttk/ttkDefaultTheme.c ================================================================== --- generic/ttk/ttkDefaultTheme.c +++ generic/ttk/ttkDefaultTheme.c @@ -243,19 +243,19 @@ Tcl_Obj *reliefObj; Tcl_Obj *defaultStateObj; /* for buttons */ } BorderElement; static Ttk_ElementOptionSpec BorderElementOptions[] = { - { "-background", TK_OPTION_BORDER, Tk_Offset(BorderElement,borderObj), + { "-background", TK_OPTION_BORDER, offsetof(BorderElement,borderObj), DEFAULT_BACKGROUND }, { "-bordercolor",TK_OPTION_COLOR, - Tk_Offset(BorderElement,borderColorObj), "black" }, - { "-default", TK_OPTION_ANY, Tk_Offset(BorderElement,defaultStateObj), + offsetof(BorderElement,borderColorObj), "black" }, + { "-default", TK_OPTION_ANY, offsetof(BorderElement,defaultStateObj), "disabled" }, - { "-borderwidth",TK_OPTION_PIXELS,Tk_Offset(BorderElement,borderWidthObj), + { "-borderwidth",TK_OPTION_PIXELS, offsetof(BorderElement,borderWidthObj), STRINGIFY(BORDERWIDTH) }, - { "-relief", TK_OPTION_RELIEF, Tk_Offset(BorderElement,reliefObj), + { "-relief", TK_OPTION_RELIEF, offsetof(BorderElement,reliefObj), "flat" }, { NULL, 0, 0, NULL } }; static void BorderElementSize( @@ -323,13 +323,13 @@ Tcl_Obj *borderObj; Tcl_Obj *borderColorObj; /* Extra border color */ } FieldElement; static Ttk_ElementOptionSpec FieldElementOptions[] = { - { "-fieldbackground", TK_OPTION_BORDER, Tk_Offset(FieldElement,borderObj), + { "-fieldbackground", TK_OPTION_BORDER, offsetof(FieldElement,borderObj), "white" }, - { "-bordercolor",TK_OPTION_COLOR, Tk_Offset(FieldElement,borderColorObj), + { "-bordercolor",TK_OPTION_COLOR, offsetof(FieldElement,borderColorObj), "black" }, { NULL, 0, 0, NULL } }; static void FieldElementSize( @@ -465,23 +465,23 @@ Tcl_Obj *marginObj; } IndicatorElement; static Ttk_ElementOptionSpec IndicatorElementOptions[] = { { "-background", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, { "-foreground", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND }, + offsetof(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND }, { "-indicatorcolor", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,colorObj), "#FFFFFF" }, + offsetof(IndicatorElement,colorObj), "#FFFFFF" }, { "-lightcolor", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,lightColorObj), "#DDDDDD" }, + offsetof(IndicatorElement,lightColorObj), "#DDDDDD" }, { "-shadecolor", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,shadeColorObj), "#888888" }, + offsetof(IndicatorElement,shadeColorObj), "#888888" }, { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(IndicatorElement,borderColorObj), "black" }, + offsetof(IndicatorElement,borderColorObj), "black" }, { "-indicatormargin", TK_OPTION_STRING, - Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" }, + offsetof(IndicatorElement,marginObj), "0 2 4 2" }, { NULL, 0, 0, NULL } }; static void IndicatorElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -652,19 +652,19 @@ Tcl_Obj *colorObj; /* Arrow color */ } ArrowElement; static Ttk_ElementOptionSpec ArrowElementOptions[] = { { "-arrowsize", TK_OPTION_PIXELS, - Tk_Offset(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) }, + offsetof(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) }, { "-background", TK_OPTION_BORDER, - Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND }, + offsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND }, { "-bordercolor", TK_OPTION_COLOR, - Tk_Offset(ArrowElement,borderColorObj), "black" }, + offsetof(ArrowElement,borderColorObj), "black" }, { "-relief", TK_OPTION_RELIEF, - Tk_Offset(ArrowElement,reliefObj),"raised"}, + offsetof(ArrowElement,reliefObj),"raised"}, { "-arrowcolor", TK_OPTION_COLOR, - Tk_Offset(ArrowElement,colorObj),"black"}, + offsetof(ArrowElement,colorObj),"black"}, { NULL, 0, 0, NULL } }; /* * Note asymmetric padding: @@ -729,22 +729,22 @@ Tcl_Obj *directionObj; Tcl_Obj *sizeObj; Tcl_Obj *colorObj; } MenubuttonArrowElement; -static const char *directionStrings[] = { /* See also: button.c */ +static const char *const directionStrings[] = { /* See also: button.c */ "above", "below", "left", "right", "flush", NULL }; enum { POST_ABOVE, POST_BELOW, POST_LEFT, POST_RIGHT, POST_FLUSH }; static Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] = { { "-direction", TK_OPTION_STRING, - Tk_Offset(MenubuttonArrowElement,directionObj), "below" }, + offsetof(MenubuttonArrowElement,directionObj), "below" }, { "-arrowsize", TK_OPTION_PIXELS, - Tk_Offset(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)}, + offsetof(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)}, { "-arrowcolor",TK_OPTION_COLOR, - Tk_Offset(MenubuttonArrowElement,colorObj), "black"}, + offsetof(MenubuttonArrowElement,colorObj), "black"}, { NULL, 0, 0, NULL } }; static Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 }; @@ -820,19 +820,19 @@ Tcl_Obj *orientObj; } TroughElement; static Ttk_ElementOptionSpec TroughElementOptions[] = { { "-orient", TK_OPTION_ANY, - Tk_Offset(TroughElement, orientObj), "horizontal" }, + offsetof(TroughElement, orientObj), "horizontal" }, { "-troughborderwidth", TK_OPTION_PIXELS, - Tk_Offset(TroughElement,borderWidthObj), "1" }, + offsetof(TroughElement,borderWidthObj), "1" }, { "-troughcolor", TK_OPTION_BORDER, - Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND }, + offsetof(TroughElement,colorObj), DEFAULT_BACKGROUND }, { "-troughrelief",TK_OPTION_RELIEF, - Tk_Offset(TroughElement,reliefObj), "sunken" }, + offsetof(TroughElement,reliefObj), "sunken" }, { "-groovewidth", TK_OPTION_PIXELS, - Tk_Offset(TroughElement,grooveWidthObj), "-1" }, + offsetof(TroughElement,grooveWidthObj), "-1" }, { NULL, 0, 0, NULL } }; static void TroughElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -899,18 +899,18 @@ Tcl_Obj *reliefObj; Tcl_Obj *orientObj; } ThumbElement; static Ttk_ElementOptionSpec ThumbElementOptions[] = { - { "-width", TK_OPTION_PIXELS, Tk_Offset(ThumbElement,sizeObj), + { "-width", TK_OPTION_PIXELS, offsetof(ThumbElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) }, - { "-background", TK_OPTION_BORDER, Tk_Offset(ThumbElement,borderObj), + { "-background", TK_OPTION_BORDER, offsetof(ThumbElement,borderObj), DEFAULT_BACKGROUND }, - { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj), + { "-bordercolor", TK_OPTION_COLOR, offsetof(ThumbElement,borderColorObj), "black" }, - { "-relief", TK_OPTION_RELIEF,Tk_Offset(ThumbElement,reliefObj),"raised" }, - { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"}, + { "-relief", TK_OPTION_RELIEF, offsetof(ThumbElement,reliefObj),"raised" }, + { "-orient", TK_OPTION_ANY, offsetof(ThumbElement,orientObj),"horizontal"}, { NULL, 0, 0, NULL } }; static void ThumbElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -982,23 +982,23 @@ Tcl_Obj *borderWidthObj; Tcl_Obj *orientObj; /* Orientation of overall slider */ } SliderElement; static Ttk_ElementOptionSpec SliderElementOptions[] = { - { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj), + { "-sliderlength", TK_OPTION_PIXELS, offsetof(SliderElement,lengthObj), "15" }, - { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj), + { "-sliderthickness",TK_OPTION_PIXELS, offsetof(SliderElement,thicknessObj), "15" }, - { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj), + { "-sliderrelief", TK_OPTION_RELIEF, offsetof(SliderElement,reliefObj), "raised" }, - { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj), + { "-borderwidth", TK_OPTION_PIXELS, offsetof(SliderElement,borderWidthObj), STRINGIFY(BORDERWIDTH) }, - { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj), + { "-background", TK_OPTION_BORDER, offsetof(SliderElement,borderObj), DEFAULT_BACKGROUND }, - { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj), + { "-bordercolor", TK_OPTION_COLOR, offsetof(ThumbElement,borderColorObj), "black" }, - { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj), + { "-orient", TK_OPTION_ANY, offsetof(SliderElement,orientObj), "horizontal" }, { NULL, 0, 0, NULL } }; static void SliderElementSize( @@ -1065,15 +1065,15 @@ Tcl_Obj *diameterObj; } TreeitemIndicator; static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = { { "-foreground", TK_OPTION_COLOR, - Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND }, + offsetof(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND }, { "-diameter", TK_OPTION_PIXELS, - Tk_Offset(TreeitemIndicator,diameterObj), "9" }, + offsetof(TreeitemIndicator,diameterObj), "9" }, { "-indicatormargins", TK_OPTION_STRING, - Tk_Offset(TreeitemIndicator,marginObj), "2 2 4 2" }, + offsetof(TreeitemIndicator,marginObj), "2 2 4 2" }, { NULL, 0, 0, NULL } }; static void TreeitemIndicatorSize( void *clientData, void *elementRecord, Tk_Window tkwin, Index: generic/ttk/ttkElements.c ================================================================== --- generic/ttk/ttkElements.c +++ generic/ttk/ttkElements.c @@ -3,13 +3,11 @@ * * Default implementation for themed elements. * */ -#include -#include -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #define DEFAULT_BORDERWIDTH "2" #define DEFAULT_ARROW_SIZE "15" @@ -58,11 +56,11 @@ Tcl_Obj *backgroundObj; } BackgroundElement; static Ttk_ElementOptionSpec BackgroundElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND }, { NULL, 0, 0, NULL } }; static void FillElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -111,15 +109,15 @@ Tcl_Obj *reliefObj; } BorderElement; static Ttk_ElementOptionSpec BorderElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(BorderElement,borderObj), DEFAULT_BACKGROUND }, + offsetof(BorderElement,borderObj), DEFAULT_BACKGROUND }, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + offsetof(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, { "-relief", TK_OPTION_RELIEF, - Tk_Offset(BorderElement,reliefObj), "flat" }, + offsetof(BorderElement,reliefObj), "flat" }, { NULL, 0, 0, NULL } }; static void BorderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -166,13 +164,13 @@ Tcl_Obj *borderWidthObj; } FieldElement; static Ttk_ElementOptionSpec FieldElementOptions[] = { { "-fieldbackground", TK_OPTION_BORDER, - Tk_Offset(FieldElement,borderObj), "white" }, + offsetof(FieldElement,borderObj), "white" }, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(FieldElement,borderWidthObj), "2" }, + offsetof(FieldElement,borderWidthObj), "2" }, { NULL, 0, 0, NULL } }; static void FieldElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -222,15 +220,15 @@ Tcl_Obj *shiftreliefObj; } PaddingElement; static Ttk_ElementOptionSpec PaddingElementOptions[] = { { "-padding", TK_OPTION_STRING, - Tk_Offset(PaddingElement,paddingObj), "0" }, + offsetof(PaddingElement,paddingObj), "0" }, { "-relief", TK_OPTION_RELIEF, - Tk_Offset(PaddingElement,reliefObj), "flat" }, + offsetof(PaddingElement,reliefObj), "flat" }, { "-shiftrelief", TK_OPTION_INT, - Tk_Offset(PaddingElement,shiftreliefObj), "0" }, + offsetof(PaddingElement,shiftreliefObj), "0" }, { NULL, 0, 0, NULL } }; static void PaddingElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -288,13 +286,13 @@ Tk_FreeGC(Tk_Display(tkwin), gc); } static Ttk_ElementOptionSpec FocusElementOptions[] = { { "-focuscolor",TK_OPTION_COLOR, - Tk_Offset(FocusElement,focusColorObj), "black" }, + offsetof(FocusElement,focusColorObj), "black" }, { "-focusthickness",TK_OPTION_PIXELS, - Tk_Offset(FocusElement,focusThicknessObj), "1" }, + offsetof(FocusElement,focusThicknessObj), "1" }, { NULL, 0, 0, NULL } }; static void FocusElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -340,13 +338,13 @@ Tcl_Obj *borderObj; } SeparatorElement; static Ttk_ElementOptionSpec SeparatorElementOptions[] = { { "-orient", TK_OPTION_ANY, - Tk_Offset(SeparatorElement, orientObj), "horizontal" }, + offsetof(SeparatorElement, orientObj), "horizontal" }, { "-background", TK_OPTION_BORDER, - Tk_Offset(SeparatorElement,borderObj), DEFAULT_BACKGROUND }, + offsetof(SeparatorElement,borderObj), DEFAULT_BACKGROUND }, { NULL, 0, 0, NULL } }; static void SeparatorElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -432,11 +430,11 @@ Tcl_Obj *backgroundObj; } SizegripElement; static Ttk_ElementOptionSpec SizegripOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(SizegripElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(SizegripElement,backgroundObj), DEFAULT_BACKGROUND }, {0,0,0,0} }; static void SizegripSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -493,21 +491,21 @@ Tcl_Obj *borderWidthObj; } IndicatorElement; static Ttk_ElementOptionSpec IndicatorElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, { "-indicatorcolor", TK_OPTION_BORDER, - Tk_Offset(IndicatorElement,colorObj), DEFAULT_BACKGROUND }, + offsetof(IndicatorElement,colorObj), DEFAULT_BACKGROUND }, { "-indicatorrelief", TK_OPTION_RELIEF, - Tk_Offset(IndicatorElement,reliefObj), "raised" }, + offsetof(IndicatorElement,reliefObj), "raised" }, { "-indicatordiameter", TK_OPTION_PIXELS, - Tk_Offset(IndicatorElement,diameterObj), "12" }, + offsetof(IndicatorElement,diameterObj), "12" }, { "-indicatormargin", TK_OPTION_STRING, - Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" }, + offsetof(IndicatorElement,marginObj), "0 2 4 2" }, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + offsetof(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH }, { NULL, 0, 0, NULL } }; /* * Checkbutton indicators (default): 3-D square. @@ -639,21 +637,21 @@ Tcl_Obj *marginObj; } MenuIndicatorElement; static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, { "-indicatorwidth", TK_OPTION_PIXELS, - Tk_Offset(MenuIndicatorElement,widthObj), "4.0m" }, + offsetof(MenuIndicatorElement,widthObj), "4.0m" }, { "-indicatorheight", TK_OPTION_PIXELS, - Tk_Offset(MenuIndicatorElement,heightObj), "1.7m" }, + offsetof(MenuIndicatorElement,heightObj), "1.7m" }, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + offsetof(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH }, { "-indicatorrelief", TK_OPTION_RELIEF, - Tk_Offset(MenuIndicatorElement,reliefObj),"raised" }, + offsetof(MenuIndicatorElement,reliefObj),"raised" }, { "-indicatormargin", TK_OPTION_STRING, - Tk_Offset(MenuIndicatorElement,marginObj), "5 0" }, + offsetof(MenuIndicatorElement,marginObj), "5 0" }, { NULL, 0, 0, NULL } }; static void MenuIndicatorElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -708,19 +706,19 @@ Tcl_Obj *colorObj; } ArrowElement; static Ttk_ElementOptionSpec ArrowElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND }, + offsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND }, { "-relief",TK_OPTION_RELIEF, - Tk_Offset(ArrowElement,reliefObj),"raised"}, + offsetof(ArrowElement,reliefObj),"raised"}, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(ArrowElement,borderWidthObj), "1" }, + offsetof(ArrowElement,borderWidthObj), "1" }, { "-arrowcolor",TK_OPTION_COLOR, - Tk_Offset(ArrowElement,colorObj),"black"}, + offsetof(ArrowElement,colorObj),"black"}, { "-arrowsize", TK_OPTION_PIXELS, - Tk_Offset(ArrowElement,sizeObj), "14" }, + offsetof(ArrowElement,sizeObj), "14" }, { NULL, 0, 0, NULL } }; static Ttk_Padding ArrowMargins = { 3,3,3,3 }; @@ -779,15 +777,15 @@ Tcl_Obj *reliefObj; } TroughElement; static Ttk_ElementOptionSpec TroughElementOptions[] = { { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + offsetof(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH }, { "-troughcolor", TK_OPTION_BORDER, - Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND }, + offsetof(TroughElement,colorObj), DEFAULT_BACKGROUND }, { "-troughrelief",TK_OPTION_RELIEF, - Tk_Offset(TroughElement,reliefObj), "sunken" }, + offsetof(TroughElement,reliefObj), "sunken" }, { NULL, 0, 0, NULL } }; static void TroughElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -839,19 +837,19 @@ Tcl_Obj *borderWidthObj; } ThumbElement; static Ttk_ElementOptionSpec ThumbElementOptions[] = { { "-orient", TK_OPTION_ANY, - Tk_Offset(ThumbElement, orientObj), "horizontal" }, + offsetof(ThumbElement, orientObj), "horizontal" }, { "-width", TK_OPTION_PIXELS, - Tk_Offset(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE }, + offsetof(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE }, { "-relief", TK_OPTION_RELIEF, - Tk_Offset(ThumbElement,reliefObj), "raised" }, + offsetof(ThumbElement,reliefObj), "raised" }, { "-background", TK_OPTION_BORDER, - Tk_Offset(ThumbElement,borderObj), DEFAULT_BACKGROUND }, + offsetof(ThumbElement,borderObj), DEFAULT_BACKGROUND }, { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + offsetof(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH }, { NULL, 0, 0, NULL } }; static void ThumbElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -909,21 +907,21 @@ Tcl_Obj *borderObj; /* the background color */ Tcl_Obj *borderWidthObj; /* the size of the border */ } SliderElement; static Ttk_ElementOptionSpec SliderElementOptions[] = { - { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj), + { "-sliderlength", TK_OPTION_PIXELS, offsetof(SliderElement,lengthObj), "30" }, - { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj), + { "-sliderthickness",TK_OPTION_PIXELS, offsetof(SliderElement,thicknessObj), "15" }, - { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj), + { "-sliderrelief", TK_OPTION_RELIEF, offsetof(SliderElement,reliefObj), "raised" }, - { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj), + { "-borderwidth", TK_OPTION_PIXELS, offsetof(SliderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, - { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj), + { "-background", TK_OPTION_BORDER, offsetof(SliderElement,borderObj), DEFAULT_BACKGROUND }, - { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj), + { "-orient", TK_OPTION_ANY, offsetof(SliderElement,orientObj), "horizontal" }, { NULL, 0, 0, NULL } }; static void SliderElementSize( @@ -1020,21 +1018,21 @@ Tcl_Obj *borderObj; /* background color */ Tcl_Obj *borderWidthObj; /* thickness of the border */ } PbarElement; static Ttk_ElementOptionSpec PbarElementOptions[] = { - { "-orient", TK_OPTION_ANY, Tk_Offset(PbarElement,orientObj), + { "-orient", TK_OPTION_ANY, offsetof(PbarElement,orientObj), "horizontal" }, - { "-thickness", TK_OPTION_PIXELS, Tk_Offset(PbarElement,thicknessObj), + { "-thickness", TK_OPTION_PIXELS, offsetof(PbarElement,thicknessObj), DEFAULT_PBAR_THICKNESS }, - { "-barsize", TK_OPTION_PIXELS, Tk_Offset(PbarElement,lengthObj), + { "-barsize", TK_OPTION_PIXELS, offsetof(PbarElement,lengthObj), DEFAULT_PBAR_LENGTH }, - { "-pbarrelief", TK_OPTION_RELIEF, Tk_Offset(PbarElement,reliefObj), + { "-pbarrelief", TK_OPTION_RELIEF, offsetof(PbarElement,reliefObj), "raised" }, - { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(PbarElement,borderWidthObj), + { "-borderwidth", TK_OPTION_PIXELS, offsetof(PbarElement,borderWidthObj), DEFAULT_BORDERWIDTH }, - { "-background", TK_OPTION_BORDER, Tk_Offset(PbarElement,borderObj), + { "-background", TK_OPTION_BORDER, offsetof(PbarElement,borderObj), DEFAULT_BACKGROUND }, { NULL, 0, 0, NULL } }; static void PbarElementSize( @@ -1094,13 +1092,13 @@ Tcl_Obj *backgroundObj; } TabElement; static Ttk_ElementOptionSpec TabElementOptions[] = { { "-borderwidth", TK_OPTION_PIXELS, - Tk_Offset(TabElement,borderWidthObj),"1" }, + offsetof(TabElement,borderWidthObj),"1" }, { "-background", TK_OPTION_BORDER, - Tk_Offset(TabElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(TabElement,backgroundObj), DEFAULT_BACKGROUND }, {0,0,0,0} }; static void TabElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, Index: generic/ttk/ttkEntry.c ================================================================== --- generic/ttk/ttkEntry.c +++ generic/ttk/ttkEntry.c @@ -67,10 +67,11 @@ */ /* Style parameters: */ typedef struct { + Tcl_Obj *placeholderForegroundObj;/* Foreground color for placeholder text */ Tcl_Obj *foregroundObj; /* Foreground color for normal text */ Tcl_Obj *backgroundObj; /* Entry widget background color */ Tcl_Obj *selBorderObj; /* Border and background for selection */ Tcl_Obj *selBorderWidthObj; /* Width of selection border */ Tcl_Obj *selForegroundObj; /* Foreground color for selected text */ @@ -112,10 +113,12 @@ EntryStyleData styleData; /* Display style data (widget options) */ EntryStyleData styleDefaults;/* Style defaults (fallback values) */ Tcl_Obj *stateObj; /* Compatibility option -- see CheckStateObj */ + Tcl_Obj *placeholderObj; /* Text to display for placeholder text */ + /* * Derived resources: */ Ttk_TraceHandle *textVariableTrace; @@ -141,59 +144,67 @@ #define SCROLLCMD_CHANGED (0x400) /* -xscrollcommand option changed */ /* * Default option values: */ -#define DEF_SELECT_BG "#000000" -#define DEF_SELECT_FG "#ffffff" -#define DEF_INSERT_BG "black" -#define DEF_ENTRY_WIDTH "20" -#define DEF_ENTRY_FONT "TkTextFont" -#define DEF_LIST_HEIGHT "10" +#define DEF_SELECT_BG "#000000" +#define DEF_SELECT_FG "#ffffff" +#define DEF_PLACEHOLDER_FG "#b3b3b3" +#define DEF_INSERT_BG "black" +#define DEF_ENTRY_WIDTH "20" +#define DEF_ENTRY_FONT "TkTextFont" +#define DEF_LIST_HEIGHT "10" static Tk_OptionSpec EntryOptionSpecs[] = { {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", - "ExportSelection", "1", -1, Tk_Offset(Entry, entry.exportSelection), + "ExportSelection", "1", -1, offsetof(Entry, entry.exportSelection), 0,0,0 }, {TK_OPTION_FONT, "-font", "font", "Font", - DEF_ENTRY_FONT, Tk_Offset(Entry, entry.fontObj),-1, + DEF_ENTRY_FONT, offsetof(Entry, entry.fontObj),-1, 0,0,GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand", - NULL, -1, Tk_Offset(Entry, entry.invalidCmd), + NULL, -1, offsetof(Entry, entry.invalidCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - "left", -1, Tk_Offset(Entry, entry.justify), + "left", -1, offsetof(Entry, entry.justify), 0, 0, GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder", + NULL, offsetof(Entry, entry.placeholderObj), -1, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-show", "show", "Show", - NULL, -1, Tk_Offset(Entry, entry.showChar), + NULL, -1, offsetof(Entry, entry.showChar), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-state", "state", "State", - "normal", Tk_Offset(Entry, entry.stateObj), -1, + "normal", offsetof(Entry, entry.stateObj), -1, 0,0,STATE_CHANGED}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - NULL, Tk_Offset(Entry, entry.textVariableObj), -1, + NULL, offsetof(Entry, entry.textVariableObj), -1, TK_OPTION_NULL_OK,0,TEXTVAR_CHANGED}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", - "none", -1, Tk_Offset(Entry, entry.validate), + "none", -1, offsetof(Entry, entry.validate), 0, (ClientData) validateStrings, 0}, {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand", - NULL, -1, Tk_Offset(Entry, entry.validateCmd), + NULL, -1, offsetof(Entry, entry.validateCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-width", "width", "Width", - DEF_ENTRY_WIDTH, Tk_Offset(Entry, entry.widthObj), -1, + DEF_ENTRY_WIDTH, offsetof(Entry, entry.widthObj), -1, 0,0,GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - NULL, -1, Tk_Offset(Entry, entry.xscroll.scrollCmd), + NULL, -1, offsetof(Entry, entry.xscroll.scrollCmd), TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, /* EntryStyleData options: */ + {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", + NULL, offsetof(Entry, entry.styleData.backgroundObj), -1, + TK_OPTION_NULL_OK,0,0}, {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", - NULL, Tk_Offset(Entry, entry.styleData.foregroundObj), -1, + NULL, offsetof(Entry, entry.styleData.foregroundObj), -1, TK_OPTION_NULL_OK,0,0}, - {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", - NULL, Tk_Offset(Entry, entry.styleData.backgroundObj), -1, + {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground", + "PlaceholderForeground", NULL, + offsetof(Entry, entry.styleData.placeholderForegroundObj), -1, TK_OPTION_NULL_OK,0,0}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -210,10 +221,11 @@ static void EntryInitStyleDefaults(EntryStyleData *es) { #define INIT(member, value) \ es->member = Tcl_NewStringObj(value, -1); \ Tcl_IncrRefCount(es->member); + INIT(placeholderForegroundObj, DEF_PLACEHOLDER_FG) INIT(foregroundObj, DEFAULT_FOREGROUND) INIT(selBorderObj, DEF_SELECT_BG) INIT(selForegroundObj, DEF_SELECT_FG) INIT(insertColorObj, DEFAULT_FOREGROUND) INIT(selBorderWidthObj, "0") @@ -221,10 +233,11 @@ #undef INIT } static void EntryFreeStyleDefaults(EntryStyleData *es) { + Tcl_DecrRefCount(es->placeholderForegroundObj); Tcl_DecrRefCount(es->foregroundObj); Tcl_DecrRefCount(es->selBorderObj); Tcl_DecrRefCount(es->selForegroundObj); Tcl_DecrRefCount(es->insertColorObj); Tcl_DecrRefCount(es->selBorderWidthObj); @@ -247,10 +260,11 @@ *es = entryPtr->entry.styleDefaults; # define INIT(member, name) \ if ((tmp=Ttk_QueryOption(entryPtr->core.layout,name,state))) \ es->member=tmp; + INIT(placeholderForegroundObj, "-placeholderforeground"); INIT(foregroundObj, "-foreground"); INIT(selBorderObj, "-selectbackground") INIT(selBorderWidthObj, "-selectborderwidth") INIT(selForegroundObj, "-selectforeground") INIT(insertColorObj, "-insertcolor") @@ -257,10 +271,11 @@ INIT(insertWidthObj, "-insertwidth") #undef INIT /* Reacquire color & border resources from resource cache. */ + es->placeholderForegroundObj = Ttk_UseColor(cache, tkwin, es->placeholderForegroundObj); es->foregroundObj = Ttk_UseColor(cache, tkwin, es->foregroundObj); es->selForegroundObj = Ttk_UseColor(cache, tkwin, es->selForegroundObj); es->insertColorObj = Ttk_UseColor(cache, tkwin, es->insertColorObj); es->selBorderObj = Ttk_UseBorder(cache, tkwin, es->selBorderObj); } @@ -298,16 +313,27 @@ * Recompute textLayout, layoutWidth, and layoutHeight * from displayString and fontObj. */ static void EntryUpdateTextLayout(Entry *entryPtr) { + TkSizeT length; + char *text; Tk_FreeTextLayout(entryPtr->entry.textLayout); - entryPtr->entry.textLayout = Tk_ComputeTextLayout( + if ((entryPtr->entry.numChars != 0) || (entryPtr->entry.placeholderObj == NULL)) { + entryPtr->entry.textLayout = Tk_ComputeTextLayout( Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj), entryPtr->entry.displayString, entryPtr->entry.numChars, 0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES, &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight); + } else { + text = TkGetStringFromObj(entryPtr->entry.placeholderObj, &length); + entryPtr->entry.textLayout = Tk_ComputeTextLayout( + Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj), + text, length, + 0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES, + &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight); + } } /* EntryEditable -- * Returns 1 if the entry widget accepts user changes, 0 otherwise */ @@ -326,11 +352,11 @@ */ static int EntryFetchSelection( ClientData clientData, int offset, char *buffer, int maxBytes) { - Entry *entryPtr = (Entry *) clientData; + Entry *entryPtr = clientData; int byteCount; const char *string; const char *selStart, *selEnd; if (entryPtr->entry.selectFirst < 0 || (!entryPtr->entry.exportSelection) @@ -359,11 +385,11 @@ * Tk_LostSelProc for Entry widgets; called when an entry * loses ownership of the selection. */ static void EntryLostSelection(ClientData clientData) { - Entry *entryPtr = (Entry *) clientData; + Entry *entryPtr = clientData; entryPtr->core.flags &= ~GOT_SELECTION; entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1; TtkRedisplayWidget(&entryPtr->core); } @@ -555,11 +581,11 @@ * Call the -invalidcommand if validation fails. * * Returns: * TCL_OK if the change is accepted * TCL_BREAK if the change is rejected - * TCL_ERROR if any errors occured + * TCL_ERROR if any errors occurred * * The change will be rejected if -validatecommand returns 0, * or if -validatecommand or -invalidcommand modifies the value. */ static int @@ -894,11 +920,11 @@ */ #define EntryEventMask (FocusChangeMask) static void EntryEventProc(ClientData clientData, XEvent *eventPtr) { - Entry *entryPtr = (Entry *) clientData; + Entry *entryPtr = clientData; Tcl_Preserve(clientData); switch (eventPtr->type) { case DestroyNotify: Tk_DeleteEventHandler(entryPtr->core.tkwin, @@ -973,11 +999,11 @@ Entry *entryPtr = recordPtr; Tcl_Obj *textVarName = entryPtr->entry.textVariableObj; Ttk_TraceHandle *vt = 0; if (mask & TEXTVAR_CHANGED) { - if (textVarName && *Tcl_GetString(textVarName)) { + if (textVarName && *Tcl_GetString(textVarName) != '\0') { vt = Ttk_TraceVariable(interp, textVarName,EntryTextVariableTrace,entryPtr); if (!vt) return TCL_ERROR; } } @@ -1172,10 +1198,11 @@ GC gc; int showSelection, showCursor; Ttk_Box textarea; TkRegion clipRegion; XRectangle rect; + Tcl_Obj *foregroundObj; EntryInitStyleData(entryPtr, &es); textarea = Ttk_ClientRegion(entryPtr->core.layout, "textarea"); showCursor = @@ -1267,11 +1294,25 @@ Tk_FreeGC(Tk_Display(tkwin), gc); } /* Draw the text: */ - gc = EntryGetGC(entryPtr, es.foregroundObj, clipRegion); + if ((*(entryPtr->entry.displayString) == '\0') + && (entryPtr->entry.placeholderObj != NULL)) { + /* No text displayed, but -placeholder is given */ + if (Tcl_GetCharLength(es.placeholderForegroundObj) > 0) { + foregroundObj = es.placeholderForegroundObj; + } else { + foregroundObj = es.foregroundObj; + } + /* Use placeholder text width */ + leftIndex = 0; + Tcl_GetStringFromObj(entryPtr->entry.placeholderObj,&rightIndex); + } else { + foregroundObj = es.foregroundObj; + } + gc = EntryGetGC(entryPtr, foregroundObj, clipRegion); Tk_DrawTextLayout( Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, entryPtr->entry.layoutX, entryPtr->entry.layoutY, leftIndex, rightIndex); XSetClipMask(Tk_Display(tkwin), gc, None); @@ -1319,12 +1360,12 @@ Entry *entryPtr, /* Entry widget to query */ Tcl_Obj *indexObj, /* Symbolic index name */ int *indexPtr) /* Return value */ { # define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */ - const char *string = Tcl_GetString(indexObj); - size_t length = indexObj->length; + TkSizeT length; + const char *string = TkGetStringFromObj(indexObj, &length); if (strncmp(string, "end", length) == 0) { *indexPtr = entryPtr->entry.numChars; } else if (strncmp(string, "insert", length) == 0) { *indexPtr = entryPtr->entry.insertPos; @@ -1360,10 +1401,11 @@ roundUp = 1; } *indexPtr = Tk_PointToChar(entryPtr->entry.textLayout, x - entryPtr->entry.layoutX, 0); + TtkUpdateScrollInfo(entryPtr->entry.xscrollHandle); if (*indexPtr < entryPtr->entry.xscroll.first) { *indexPtr = entryPtr->entry.xscroll.first; } /* @@ -1562,11 +1604,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, - Tcl_NewBooleanObj(entryPtr->entry.selectFirst >= 0)); + Tcl_NewWideIntObj(entryPtr->entry.selectFirst >= 0)); return TCL_OK; } /* $entry selection range $start $end -- * Explicitly set the selection range. @@ -1639,11 +1681,11 @@ code = EntryRevalidate(interp, entryPtr, VALIDATE_FORCED); if (code == TCL_ERROR) return code; - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(code == TCL_OK)); return TCL_OK; } /* $entry xview -- horizontal scrolling interface */ @@ -1654,11 +1696,11 @@ if (objc == 3) { int newFirst; if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { return TCL_ERROR; } - TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst); + TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst, 1); return TCL_OK; } return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle); } @@ -1696,10 +1738,20 @@ TtkWidgetGetLayout, /* getLayoutProc */ TtkWidgetSize, /* sizeProc */ EntryDoLayout, /* layoutProc */ EntryDisplay /* displayProc */ }; + +/*------------------------------------------------------------------------ + * Named indices for the combobox "current" command + */ +static const char *const comboboxCurrentIndexNames[] = { + "end", NULL +}; +enum comboboxCurrentIndices { + INDEX_END +}; /*------------------------------------------------------------------------ * +++ Combobox widget record. */ @@ -1716,17 +1768,17 @@ ComboboxPart combobox; } Combobox; static Tk_OptionSpec ComboboxOptionSpecs[] = { {TK_OPTION_STRING, "-height", "height", "Height", - DEF_LIST_HEIGHT, Tk_Offset(Combobox, combobox.heightObj), -1, + DEF_LIST_HEIGHT, offsetof(Combobox, combobox.heightObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-postcommand", "postCommand", "PostCommand", - "", Tk_Offset(Combobox, combobox.postCommandObj), -1, + "", offsetof(Combobox, combobox.postCommandObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-values", "values", "Values", - "", Tk_Offset(Combobox, combobox.valuesObj), -1, + "", offsetof(Combobox, combobox.valuesObj), -1, 0,0,0 }, WIDGET_INHERIT_OPTIONS(EntryOptionSpecs) }; /* ComboboxInitialize -- @@ -1798,19 +1850,46 @@ } cbPtr->combobox.currentIndex = currentIndex; Tcl_SetObjResult(interp, Tcl_NewIntObj(currentIndex)); return TCL_OK; } else if (objc == 3) { - if (Tcl_GetIntFromObj(interp, objv[2], ¤tIndex) != TCL_OK) { - return TCL_ERROR; - } - if (currentIndex < 0 || currentIndex >= nValues) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "Index %s out of range", Tcl_GetString(objv[2]))); - Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL); - return TCL_ERROR; - } + int result, index; + + result = Tcl_GetIndexFromObj(NULL, objv[2], comboboxCurrentIndexNames, + "", 0, &index); + if (result == TCL_OK) { + + /* + * The index is one of the named indices. + */ + + switch (index) { + case INDEX_END: + /* "end" index */ + currentIndex = nValues - 1; + break; + } + } else { + + /* + * The index should be just an integer. + */ + + if (Tcl_GetIntFromObj(NULL, objv[2], ¤tIndex) != TCL_OK) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "Incorrect index %s", Tcl_GetString(objv[2]))); + Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_VALUE", NULL); + return TCL_ERROR; + } + + if (currentIndex < 0 || currentIndex >= nValues) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "Index %s out of range", Tcl_GetString(objv[2]))); + Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL); + return TCL_ERROR; + } + } cbPtr->combobox.currentIndex = currentIndex; return EntrySetValue(recordPtr, Tcl_GetString(values[currentIndex])); } else { @@ -1880,31 +1959,31 @@ SpinboxPart spinbox; } Spinbox; static Tk_OptionSpec SpinboxOptionSpecs[] = { {TK_OPTION_STRING, "-values", "values", "Values", - "", Tk_Offset(Spinbox, spinbox.valuesObj), -1, + "", offsetof(Spinbox, spinbox.valuesObj), -1, 0,0,0 }, {TK_OPTION_DOUBLE, "-from", "from", "From", - "0", Tk_Offset(Spinbox,spinbox.fromObj), -1, + "0", offsetof(Spinbox,spinbox.fromObj), -1, 0,0,0 }, {TK_OPTION_DOUBLE, "-to", "to", "To", - "0", Tk_Offset(Spinbox,spinbox.toObj), -1, + "0", offsetof(Spinbox,spinbox.toObj), -1, 0,0,0 }, {TK_OPTION_DOUBLE, "-increment", "increment", "Increment", - "1", Tk_Offset(Spinbox,spinbox.incrementObj), -1, + "1", offsetof(Spinbox,spinbox.incrementObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-format", "format", "Format", - "", Tk_Offset(Spinbox, spinbox.formatObj), -1, + "", offsetof(Spinbox, spinbox.formatObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-command", "command", "Command", - "", Tk_Offset(Spinbox, spinbox.commandObj), -1, + "", offsetof(Spinbox, spinbox.commandObj), -1, 0,0,0 }, {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap", - "0", Tk_Offset(Spinbox,spinbox.wrapObj), -1, + "0", offsetof(Spinbox,spinbox.wrapObj), -1, 0,0,0 }, WIDGET_INHERIT_OPTIONS(EntryOptionSpecs) }; @@ -1982,13 +2061,13 @@ Tcl_Obj *widthObj; } TextareaElement; static Ttk_ElementOptionSpec TextareaElementOptions[] = { { "-font", TK_OPTION_FONT, - Tk_Offset(TextareaElement,fontObj), DEF_ENTRY_FONT }, + offsetof(TextareaElement,fontObj), DEF_ENTRY_FONT }, { "-width", TK_OPTION_INT, - Tk_Offset(TextareaElement,widthObj), "20" }, + offsetof(TextareaElement,widthObj), "20" }, { NULL, 0, 0, NULL } }; static void TextareaElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, Index: generic/ttk/ttkFrame.c ================================================================== --- generic/ttk/ttkFrame.c +++ generic/ttk/ttkFrame.c @@ -2,12 +2,11 @@ * Copyright (c) 2004, Joe English * * ttk::frame and ttk::labelframe widgets. */ -#include - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #include "ttkManager.h" /* ====================================================================== @@ -27,23 +26,23 @@ FramePart frame; } Frame; static Tk_OptionSpec FrameOptionSpecs[] = { {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", NULL, - Tk_Offset(Frame,frame.borderWidthObj), -1, + offsetof(Frame,frame.borderWidthObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL, - Tk_Offset(Frame,frame.paddingObj), -1, + offsetof(Frame,frame.paddingObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", NULL, - Tk_Offset(Frame,frame.reliefObj), -1, + offsetof(Frame,frame.reliefObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_PIXELS, "-width", "width", "Width", "0", - Tk_Offset(Frame,frame.widthObj), -1, + offsetof(Frame,frame.widthObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_PIXELS, "-height", "height", "Height", "0", - Tk_Offset(Frame,frame.heightObj), -1, + offsetof(Frame,frame.heightObj), -1, 0,0,GEOMETRY_CHANGED }, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -248,20 +247,20 @@ #define LABELWIDGET_CHANGED 0x100 static Tk_OptionSpec LabelframeOptionSpecs[] = { {TK_OPTION_STRING, "-labelanchor", "labelAnchor", "LabelAnchor", - "nw", Tk_Offset(Labelframe, label.labelAnchorObj),-1, + "nw", offsetof(Labelframe, label.labelAnchorObj),-1, 0,0,GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-text", "text", "Text", "", - Tk_Offset(Labelframe,label.textObj), -1, + offsetof(Labelframe,label.textObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_INT, "-underline", "underline", "Underline", - "-1", Tk_Offset(Labelframe,label.underlineObj), -1, + "-1", offsetof(Labelframe,label.underlineObj), -1, 0,0,0 }, {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL, - -1, Tk_Offset(Labelframe,label.labelWidget), + -1, offsetof(Labelframe,label.labelWidget), TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED }, WIDGET_INHERIT_OPTIONS(FrameOptionSpecs) }; DELETED generic/ttk/ttkGenStubs.tcl Index: generic/ttk/ttkGenStubs.tcl ================================================================== --- generic/ttk/ttkGenStubs.tcl +++ /dev/null @@ -1,963 +0,0 @@ -# ttkGenStubs.tcl -- -# -# This script generates a set of stub files for a given -# interface. -# -# -# Copyright (c) 1998-1999 by Scriptics Corporation. -# Copyright (c) 2007 Daniel A. Steffen -# -# See the file "license.terms" for information on usage and redistribution -# of this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# SOURCE: tcl/tools/genStubs.tcl, revision 1.44 -# -# CHANGES: -# + Second argument to "declare" is used as a status guard -# instead of a platform guard. -# + Allow trailing semicolon in function declarations -# - -namespace eval genStubs { - # libraryName -- - # - # The name of the entire library. This value is used to compute - # the USE_*_STUBS macro and the name of the init file. - - variable libraryName "UNKNOWN" - - # interfaces -- - # - # An array indexed by interface name that is used to maintain - # the set of valid interfaces. The value is empty. - - array set interfaces {} - - # curName -- - # - # The name of the interface currently being defined. - - variable curName "UNKNOWN" - - # scspec -- - # - # Storage class specifier for external function declarations. - # Normally "EXTERN", may be set to something like XYZAPI - # - variable scspec "EXTERN" - - # epoch, revision -- - # - # The epoch and revision numbers of the interface currently being defined. - # (@@@TODO: should be an array mapping interface names -> numbers) - # - - variable epoch {} - variable revision 0 - - # hooks -- - # - # An array indexed by interface name that contains the set of - # subinterfaces that should be defined for a given interface. - - array set hooks {} - - # stubs -- - # - # This three dimensional array is indexed first by interface name, - # second by field name, and third by a numeric offset or the - # constant "lastNum". The lastNum entry contains the largest - # numeric offset used for a given interface. - # - # Field "decl,$i" contains the C function specification that - # should be used for the given entry in the stub table. The spec - # consists of a list in the form returned by parseDecl. - # Other fields TBD later. - - array set stubs {} - - # outDir -- - # - # The directory where the generated files should be placed. - - variable outDir . -} - -# genStubs::library -- -# -# This function is used in the declarations file to set the name -# of the library that the interfaces are associated with (e.g. "tcl"). -# This value will be used to define the inline conditional macro. -# -# Arguments: -# name The library name. -# -# Results: -# None. - -proc genStubs::library {name} { - variable libraryName $name -} - -# genStubs::interface -- -# -# This function is used in the declarations file to set the name -# of the interface currently being defined. -# -# Arguments: -# name The name of the interface. -# -# Results: -# None. - -proc genStubs::interface {name} { - variable curName $name - variable interfaces - variable stubs - - set interfaces($name) {} - set stubs($name,lastNum) 0 - return -} - -# genStubs::scspec -- -# -# Define the storage class macro used for external function declarations. -# Typically, this will be a macro like XYZAPI or EXTERN that -# expands to either DLLIMPORT or DLLEXPORT, depending on whether -# -DBUILD_XYZ has been set. -# -proc genStubs::scspec {value} { - variable scspec $value -} - -# genStubs::epoch -- -# -# Define the epoch number for this library. The epoch -# should be incrememented when a release is made that -# contains incompatible changes to the public API. -# -proc genStubs::epoch {value} { - variable epoch $value -} - -# genStubs::hooks -- -# -# This function defines the subinterface hooks for the current -# interface. -# -# Arguments: -# names The ordered list of interfaces that are reachable through the -# hook vector. -# -# Results: -# None. - -proc genStubs::hooks {names} { - variable curName - variable hooks - - set hooks($curName) $names - return -} - -# genStubs::declare -- -# -# This function is used in the declarations file to declare a new -# interface entry. -# -# Arguments: -# index The index number of the interface. -# status Status of the interface: one of "current", -# "deprecated", or "obsolete". -# decl The C function declaration, or {} for an undefined -# entry. -# -# Results: -# None. - -proc genStubs::declare {args} { - variable stubs - variable curName - variable revision - - incr revision - if {[llength $args] == 2} { - lassign $args index decl - set status current - } elseif {[llength $args] == 3} { - lassign $args index status decl - } else { - puts stderr "wrong # args: declare $args" - return - } - - # Check for duplicate declarations, then add the declaration and - # bump the lastNum counter if necessary. - - if {[info exists stubs($curName,decl,$index)]} { - puts stderr "Duplicate entry: $index" - } - regsub -all "\[ \t\n\]+" [string trim $decl] " " decl - set decl [parseDecl $decl] - - set stubs($curName,status,$index) $status - set stubs($curName,decl,$index) $decl - - if {$index > $stubs($curName,lastNum)} { - set stubs($curName,lastNum) $index - } - return -} - -# genStubs::export -- -# -# This function is used in the declarations file to declare a symbol -# that is exported from the library but is not in the stubs table. -# -# Arguments: -# decl The C function declaration, or {} for an undefined -# entry. -# -# Results: -# None. - -proc genStubs::export {args} { - if {[llength $args] != 1} { - puts stderr "wrong # args: export $args" - } - return -} - -# genStubs::rewriteFile -- -# -# This function replaces the machine generated portion of the -# specified file with new contents. It looks for the !BEGIN! and -# !END! comments to determine where to place the new text. -# -# Arguments: -# file The name of the file to modify. -# text The new text to place in the file. -# -# Results: -# None. - -proc genStubs::rewriteFile {file text} { - if {![file exists $file]} { - puts stderr "Cannot find file: $file" - return - } - set in [open ${file} r] - set out [open ${file}.new w] - fconfigure $out -translation lf - - while {![eof $in]} { - set line [gets $in] - if {[string match "*!BEGIN!*" $line]} { - break - } - puts $out $line - } - puts $out "/* !BEGIN!: Do not edit below this line. */" - puts $out $text - while {![eof $in]} { - set line [gets $in] - if {[string match "*!END!*" $line]} { - break - } - } - puts $out "/* !END!: Do not edit above this line. */" - puts -nonewline $out [read $in] - close $in - close $out - file rename -force ${file}.new ${file} - return -} - -# genStubs::addPlatformGuard -- -# -# Wrap a string inside a platform #ifdef. -# -# Arguments: -# plat Platform to test. -# -# Results: -# Returns the original text inside an appropriate #ifdef. - -proc genStubs::addPlatformGuard {plat iftxt {eltxt {}}} { - set text "" - switch $plat { - win { - append text "#ifdef _WIN32 /* WIN */\n${iftxt}" - if {$eltxt ne ""} { - append text "#else /* WIN */\n${eltxt}" - } - append text "#endif /* WIN */\n" - } - unix { - append text "#if !defined(_WIN32) && !defined(MAC_OSX_TCL)\ - /* UNIX */\n${iftxt}" - if {$eltxt ne ""} { - append text "#else /* UNIX */\n${eltxt}" - } - append text "#endif /* UNIX */\n" - } - macosx { - append text "#ifdef MAC_OSX_TCL /* MACOSX */\n${iftxt}" - if {$eltxt ne ""} { - append text "#else /* MACOSX */\n${eltxt}" - } - append text "#endif /* MACOSX */\n" - } - aqua { - append text "#ifdef MAC_OSX_TK /* AQUA */\n${iftxt}" - if {$eltxt ne ""} { - append text "#else /* AQUA */\n${eltxt}" - } - append text "#endif /* AQUA */\n" - } - x11 { - append text "#if !(defined(_WIN32) || defined(MAC_OSX_TK))\ - /* X11 */\n${iftxt}" - if {$eltxt ne ""} { - append text "#else /* X11 */\n${eltxt}" - } - append text "#endif /* X11 */\n" - } - default { - append text "${iftxt}${eltxt}" - } - } - return $text -} - -# genStubs::emitSlots -- -# -# Generate the stub table slots for the given interface. If there -# are no generic slots, then one table is generated for each -# platform, otherwise one table is generated for all platforms. -# -# Arguments: -# name The name of the interface being emitted. -# textVar The variable to use for output. -# -# Results: -# None. - -proc genStubs::emitSlots {name textVar} { - upvar $textVar text - - forAllStubs $name makeSlot noGuard text {" void (*reserved$i)(void);\n"} - return -} - -# genStubs::parseDecl -- -# -# Parse a C function declaration into its component parts. -# -# Arguments: -# decl The function declaration. -# -# Results: -# Returns a list of the form {returnType name args}. The args -# element consists of a list of type/name pairs, or a single -# element "void". If the function declaration is malformed -# then an error is displayed and the return value is {}. - -proc genStubs::parseDecl {decl} { - if {![regexp {^(.*)\((.*)\);?$} $decl all prefix args]} { - set prefix $decl - set args {} - } - set prefix [string trim $prefix] - if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} { - puts stderr "Bad return type: $decl" - return - } - set rtype [string trim $rtype] - if {$args eq ""} { - return [list $rtype $fname {}] - } - foreach arg [split $args ,] { - lappend argList [string trim $arg] - } - if {![string compare [lindex $argList end] "..."]} { - set args TCL_VARARGS - foreach arg [lrange $argList 0 end-1] { - set argInfo [parseArg $arg] - if {[llength $argInfo] == 2 || [llength $argInfo] == 3} { - lappend args $argInfo - } else { - puts stderr "Bad argument: '$arg' in '$decl'" - return - } - } - } else { - set args {} - foreach arg $argList { - set argInfo [parseArg $arg] - if {![string compare $argInfo "void"]} { - lappend args "void" - break - } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} { - lappend args $argInfo - } else { - puts stderr "Bad argument: '$arg' in '$decl'" - return - } - } - } - return [list $rtype $fname $args] -} - -# genStubs::parseArg -- -# -# This function parses a function argument into a type and name. -# -# Arguments: -# arg The argument to parse. -# -# Results: -# Returns a list of type and name with an optional third array -# indicator. If the argument is malformed, returns "". - -proc genStubs::parseArg {arg} { - if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} { - if {$arg eq "void"} { - return $arg - } else { - return - } - } - set result [list [string trim $type] $name] - if {$array ne ""} { - lappend result $array - } - return $result -} - -# genStubs::makeDecl -- -# -# Generate the prototype for a function. -# -# Arguments: -# name The interface name. -# decl The function declaration. -# index The slot index for this function. -# -# Results: -# Returns the formatted declaration string. - -proc genStubs::makeDecl {name decl index} { - variable scspec - lassign $decl rtype fname args - - append text "/* $index */\n" - set line "$scspec $rtype" - set count [expr {2 - ([string length $line] / 8)}] - append line [string range "\t\t\t" 0 $count] - set pad [expr {24 - [string length $line]}] - if {$pad <= 0} { - append line " " - set pad 0 - } - if {$args eq ""} { - append line $fname - append text $line - append text ";\n" - return $text - } - append line $fname - - set arg1 [lindex $args 0] - switch -exact $arg1 { - void { - append line "(void)" - } - TCL_VARARGS { - set sep "(" - foreach arg [lrange $args 1 end] { - append line $sep - set next {} - append next [lindex $arg 0] - if {[string index $next end] ne "*"} { - append next " " - } - append next [lindex $arg 1] [lindex $arg 2] - if {[string length $line] + [string length $next] \ - + $pad > 76} { - append text [string trimright $line] \n - set line "\t\t\t\t" - set pad 28 - } - append line $next - set sep ", " - } - append line ", ...)" - } - default { - set sep "(" - foreach arg $args { - append line $sep - set next {} - append next [lindex $arg 0] - if {[string index $next end] ne "*"} { - append next " " - } - append next [lindex $arg 1] [lindex $arg 2] - if {[string length $line] + [string length $next] \ - + $pad > 76} { - append text [string trimright $line] \n - set line "\t\t\t\t" - set pad 28 - } - append line $next - set sep ", " - } - append line ")" - } - } - return "$text$line;\n" -} - -# genStubs::makeMacro -- -# -# Generate the inline macro for a function. -# -# Arguments: -# name The interface name. -# decl The function declaration. -# index The slot index for this function. -# -# Results: -# Returns the formatted macro definition. - -proc genStubs::makeMacro {name decl index} { - lassign $decl rtype fname args - - set lfname [string tolower [string index $fname 0]] - append lfname [string range $fname 1 end] - - set text "#define $fname \\\n\t(" - if {$args eq ""} { - append text "*" - } - append text "${name}StubsPtr->$lfname)" - append text " /* $index */\n" - return $text -} - -# genStubs::makeSlot -- -# -# Generate the stub table entry for a function. -# -# Arguments: -# name The interface name. -# decl The function declaration. -# index The slot index for this function. -# -# Results: -# Returns the formatted table entry. - -proc genStubs::makeSlot {name decl index} { - lassign $decl rtype fname args - - set lfname [string tolower [string index $fname 0]] - append lfname [string range $fname 1 end] - - set text " " - if {$args eq ""} { - append text $rtype " *" $lfname "; /* $index */\n" - return $text - } - if {[string range $rtype end-8 end] eq "__stdcall"} { - append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") " - } else { - append text $rtype " (*" $lfname ") " - } - set arg1 [lindex $args 0] - switch -exact $arg1 { - void { - append text "(void)" - } - TCL_VARARGS { - set sep "(" - foreach arg [lrange $args 1 end] { - append text $sep [lindex $arg 0] - if {[string index $text end] ne "*"} { - append text " " - } - append text [lindex $arg 1] [lindex $arg 2] - set sep ", " - } - append text ", ...)" - } - default { - set sep "(" - foreach arg $args { - append text $sep [lindex $arg 0] - if {[string index $text end] ne "*"} { - append text " " - } - append text [lindex $arg 1] [lindex $arg 2] - set sep ", " - } - append text ")" - } - } - - append text "; /* $index */\n" - return $text -} - -# genStubs::makeInit -- -# -# Generate the prototype for a function. -# -# Arguments: -# name The interface name. -# decl The function declaration. -# index The slot index for this function. -# -# Results: -# Returns the formatted declaration string. - -proc genStubs::makeInit {name decl index} { - if {[lindex $decl 2] eq ""} { - append text " &" [lindex $decl 1] ", /* " $index " */\n" - } else { - append text " " [lindex $decl 1] ", /* " $index " */\n" - } - return $text -} - -# genStubs::forAllStubs -- -# -# This function iterates over all of the slots and invokes -# a callback for each slot. The result of the callback is then -# placed inside appropriate guards. -# -# Arguments: -# name The interface name. -# slotProc The proc to invoke to handle the slot. It will -# have the interface name, the declaration, and -# the index appended. -# guardProc The proc to invoke to add guards. It will have -# the slot status and text appended. -# textVar The variable to use for output. -# skipString The string to emit if a slot is skipped. This -# string will be subst'ed in the loop so "$i" can -# be used to substitute the index value. -# -# Results: -# None. - -proc genStubs::forAllStubs {name slotProc guardProc textVar - {skipString {"/* Slot $i is reserved */\n"}}} { - variable stubs - upvar $textVar text - - set lastNum $stubs($name,lastNum) - - for {set i 0} {$i <= $lastNum} {incr i} { - if {[info exists stubs($name,decl,$i)]} { - append text [$guardProc $stubs($name,status,$i) \ - [$slotProc $name $stubs($name,decl,$i) $i]] - } else { - eval {append text} $skipString - } - } -} - -proc genStubs::noGuard {status text} { return $text } - -proc genStubs::addGuard {status text} { - variable libraryName - set upName [string toupper $libraryName] - - switch -- $status { - current { - # No change - } - deprecated { - set text [ifdeffed "${upName}_DEPRECATED" $text] - } - obsolete { - set text "" - } - default { - puts stderr "Unrecognized status code $status" - } - } - return $text -} - -proc genStubs::ifdeffed {macro text} { - join [list "#ifdef $macro" $text "#endif" ""] \n -} - -# genStubs::emitDeclarations -- -# -# This function emits the function declarations for this interface. -# -# Arguments: -# name The interface name. -# textVar The variable to use for output. -# -# Results: -# None. - -proc genStubs::emitDeclarations {name textVar} { - upvar $textVar text - - append text "\n/*\n * Exported function declarations:\n */\n\n" - forAllStubs $name makeDecl noGuard text - return -} - -# genStubs::emitMacros -- -# -# This function emits the inline macros for an interface. -# -# Arguments: -# name The name of the interface being emitted. -# textVar The variable to use for output. -# -# Results: -# None. - -proc genStubs::emitMacros {name textVar} { - variable libraryName - upvar $textVar text - - set upName [string toupper $libraryName] - append text "\n#if defined(USE_${upName}_STUBS)\n" - append text "\n/*\n * Inline function declarations:\n */\n\n" - - forAllStubs $name makeMacro addGuard text - - append text "\n#endif /* defined(USE_${upName}_STUBS) */\n" - return -} - -# genStubs::emitHeader -- -# -# This function emits the body of the Decls.h file for -# the specified interface. -# -# Arguments: -# name The name of the interface being emitted. -# -# Results: -# None. - -proc genStubs::emitHeader {name} { - variable outDir - variable hooks - variable epoch - variable revision - - set capName [string toupper [string index $name 0]] - append capName [string range $name 1 end] - - if {$epoch ne ""} { - set CAPName [string toupper $name] - append text "\n" - append text "#define ${CAPName}_STUBS_EPOCH $epoch\n" - append text "#define ${CAPName}_STUBS_REVISION $revision\n" - } - - append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n" - - emitDeclarations $name text - - if {[info exists hooks($name)]} { - append text "\ntypedef struct {\n" - foreach hook $hooks($name) { - set capHook [string toupper [string index $hook 0]] - append capHook [string range $hook 1 end] - append text " const struct ${capHook}Stubs *${hook}Stubs;\n" - } - append text "} ${capName}StubHooks;\n" - } - append text "\ntypedef struct ${capName}Stubs {\n" - append text " int magic;\n" - if {$epoch ne ""} { - append text " int epoch;\n" - append text " int revision;\n" - } - if {[info exists hooks($name)]} { - append text " const ${capName}StubHooks *hooks;\n\n" - } else { - append text " void *hooks;\n\n" - } - - emitSlots $name text - - append text "} ${capName}Stubs;\n\n" - - append text "extern const ${capName}Stubs *${name}StubsPtr;\n\n" - append text "#ifdef __cplusplus\n}\n#endif\n" - - emitMacros $name text - - rewriteFile [file join $outDir ${name}Decls.h] $text - return -} - -# genStubs::emitInit -- -# -# Generate the table initializers for an interface. -# -# Arguments: -# name The name of the interface to initialize. -# textVar The variable to use for output. -# -# Results: -# Returns the formatted output. - -proc genStubs::emitInit {name textVar} { - variable hooks - variable interfaces - variable epoch - upvar $textVar text - set root 1 - - set capName [string toupper [string index $name 0]] - append capName [string range $name 1 end] - - if {[info exists hooks($name)]} { - append text "\nstatic const ${capName}StubHooks ${name}StubHooks = \{\n" - set sep " " - foreach sub $hooks($name) { - append text $sep "&${sub}Stubs" - set sep ",\n " - } - append text "\n\};\n" - } - foreach intf [array names interfaces] { - if {[info exists hooks($intf)]} { - if {[lsearch -exact $hooks($intf) $name] >= 0} { - set root 0 - break - } - } - } - - append text "\n" - if {!$root} { - append text "static " - } - append text "const ${capName}Stubs ${name}Stubs = \{\n TCL_STUB_MAGIC,\n" - if {$epoch ne ""} { - set CAPName [string toupper $name] - append text " ${CAPName}_STUBS_EPOCH,\n" - append text " ${CAPName}_STUBS_REVISION,\n" - } - if {[info exists hooks($name)]} { - append text " &${name}StubHooks,\n" - } else { - append text " 0,\n" - } - - forAllStubs $name makeInit noGuard text {" 0, /* $i */\n"} - - append text "\};\n" - return -} - -# genStubs::emitInits -- -# -# This function emits the body of the StubInit.c file for -# the specified interface. -# -# Arguments: -# name The name of the interface being emitted. -# -# Results: -# None. - -proc genStubs::emitInits {} { - variable hooks - variable outDir - variable libraryName - variable interfaces - - # Assuming that dependencies only go one level deep, we need to emit - # all of the leaves first to avoid needing forward declarations. - - set leaves {} - set roots {} - foreach name [lsort [array names interfaces]] { - if {[info exists hooks($name)]} { - lappend roots $name - } else { - lappend leaves $name - } - } - foreach name $leaves { - emitInit $name text - } - foreach name $roots { - emitInit $name text - } - - rewriteFile [file join $outDir ${libraryName}StubInit.c] $text -} - -# genStubs::init -- -# -# This is the main entry point. -# -# Arguments: -# None. -# -# Results: -# None. - -proc genStubs::init {} { - global argv argv0 - variable outDir - variable interfaces - - if {[llength $argv] < 2} { - puts stderr "usage: $argv0 outDir declFile ?declFile...?" - exit 1 - } - - set outDir [lindex $argv 0] - - foreach file [lrange $argv 1 end] { - source $file - } - - foreach name [lsort [array names interfaces]] { - puts "Emitting $name" - emitHeader $name - } - - emitInits -} - -# lassign -- -# -# This function emulates the TclX lassign command. -# -# Arguments: -# valueList A list containing the values to be assigned. -# args The list of variables to be assigned. -# -# Results: -# Returns any values that were not assigned to variables. - -if {[string length [namespace which lassign]] == 0} { - proc lassign {valueList args} { - if {[llength $args] == 0} { - error "wrong # args: should be \"lassign list varName ?varName ...?\"" - } - uplevel [list foreach $args $valueList {break}] - return [lrange $valueList [llength $args] end] - } -} - -genStubs::init Index: generic/ttk/ttkImage.c ================================================================== --- generic/ttk/ttkImage.c +++ generic/ttk/ttkImage.c @@ -8,12 +8,11 @@ * is the name of the default image to use, the remainder of the * list is a sequence of statespec/imagename options as per * [style map]. */ -#include -#include +#include "tkInt.h" #include "ttkTheme.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) /*------------------------------------------------------------------------ @@ -343,11 +342,11 @@ void *clientData, Ttk_Theme theme, const char *elementName, int objc, Tcl_Obj *const objv[]) { - static const char *optionStrings[] = + static const char *const optionStrings[] = { "-border","-height","-padding","-sticky","-width",NULL }; enum { O_BORDER, O_HEIGHT, O_PADDING, O_STICKY, O_WIDTH }; Ttk_ImageSpec *imageSpec = 0; ImageData *imageData = 0; Index: generic/ttk/ttkInit.c ================================================================== --- generic/ttk/ttkInit.c +++ generic/ttk/ttkInit.c @@ -2,12 +2,11 @@ * Copyright (c) 2003, Joe English * * Ttk package: initialization routine and miscellaneous utilities. */ -#include -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" /* * Legal values for the button -default option. @@ -60,11 +59,11 @@ /* * Recognized values for the -state compatibility option. * Other options are accepted and interpreted as synonyms for "normal". */ -static const char *ttkStateStrings[] = { +static const char *const ttkStateStrings[] = { "normal", "readonly", "disabled", "active", NULL }; enum { TTK_COMPAT_STATE_NORMAL, TTK_COMPAT_STATE_READONLY, @@ -177,15 +176,15 @@ /* public */ Tk_OptionSpec ttkCoreOptionSpecs[] = { {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", NULL, - Tk_Offset(WidgetCore, cursorObj), -1, TK_OPTION_NULL_OK,0,0 }, + offsetof(WidgetCore, cursorObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_STRING, "-style", "style", "Style", "", - Tk_Offset(WidgetCore,styleObj), -1, 0,0,STYLE_CHANGED}, + offsetof(WidgetCore,styleObj), -1, 0,0,STYLE_CHANGED}, {TK_OPTION_STRING, "-class", "", "", NULL, - Tk_Offset(WidgetCore,classObj), -1, 0,0,READONLY_OPTION}, + offsetof(WidgetCore,classObj), -1, 0,0,READONLY_OPTION}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; /*------------------------------------------------------------------------ * +++ Initialization: elements and element factories. Index: generic/ttk/ttkLabel.c ================================================================== --- generic/ttk/ttkLabel.c +++ generic/ttk/ttkLabel.c @@ -46,27 +46,27 @@ /* Text element options table. * NB: Keep in sync with label element option table. */ static Ttk_ElementOptionSpec TextElementOptions[] = { { "-text", TK_OPTION_STRING, - Tk_Offset(TextElement,textObj), "" }, + offsetof(TextElement,textObj), "" }, { "-font", TK_OPTION_FONT, - Tk_Offset(TextElement,fontObj), DEFAULT_FONT }, + offsetof(TextElement,fontObj), DEFAULT_FONT }, { "-foreground", TK_OPTION_COLOR, - Tk_Offset(TextElement,foregroundObj), "black" }, + offsetof(TextElement,foregroundObj), "black" }, { "-underline", TK_OPTION_INT, - Tk_Offset(TextElement,underlineObj), "-1"}, + offsetof(TextElement,underlineObj), "-1"}, { "-width", TK_OPTION_INT, - Tk_Offset(TextElement,widthObj), "-1"}, + offsetof(TextElement,widthObj), "-1"}, { "-anchor", TK_OPTION_ANCHOR, - Tk_Offset(TextElement,anchorObj), "w"}, + offsetof(TextElement,anchorObj), "w"}, { "-justify", TK_OPTION_JUSTIFY, - Tk_Offset(TextElement,justifyObj), "left" }, + offsetof(TextElement,justifyObj), "left" }, { "-wraplength", TK_OPTION_PIXELS, - Tk_Offset(TextElement,wrapLengthObj), "0" }, + offsetof(TextElement,wrapLengthObj), "0" }, { "-embossed", TK_OPTION_INT, - Tk_Offset(TextElement,embossedObj), "0"}, + offsetof(TextElement,embossedObj), "0"}, { NULL, 0, 0, NULL } }; static int TextSetup(TextElement *text, Tk_Window tkwin) { @@ -136,11 +136,11 @@ gcValues.foreground = color->pixel; gc1 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin)); gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); - /* + /* * Place text according to -anchor: */ Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor); b = Ttk_AnchorBox(b, text->width, text->height, anchor); @@ -246,15 +246,15 @@ /* ===> NB: Keep in sync with label element option table. <=== */ static Ttk_ElementOptionSpec ImageElementOptions[] = { { "-image", TK_OPTION_STRING, - Tk_Offset(ImageElement,imageObj), "" }, + offsetof(ImageElement,imageObj), "" }, { "-stipple", TK_OPTION_STRING, /* Really: TK_OPTION_BITMAP */ - Tk_Offset(ImageElement,stippleObj), "gray50" }, + offsetof(ImageElement,stippleObj), "gray50" }, { "-background", TK_OPTION_COLOR, - Tk_Offset(ImageElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(ImageElement,backgroundObj), DEFAULT_BACKGROUND }, { NULL, 0, 0, NULL } }; /* * ImageSetup() -- @@ -339,19 +339,19 @@ return; } Tk_RedrawImage(image->tkimg, 0,0, width, height, d, b.x, b.y); - /* If we're disabled there's no state-specific 'disabled' image, + /* If we're disabled there's no state-specific 'disabled' image, * stipple the image. * @@@ Possibly: Don't do disabled-stippling at all; * @@@ it's ugly and out of fashion. - * Do not stipple at all under Aqua, just draw the image: it shows up + * Do not stipple at all under Aqua, just draw the image: it shows up * as a white rectangle otherwise. */ - + if (state & TTK_STATE_DISABLED) { if (TtkSelectImage(image->imageSpec, 0ul) == image->tkimg) { #ifndef MAC_OSX_TK StippleOver(image, tkwin, d, b.x,b.y); #endif @@ -440,45 +440,45 @@ int totalWidth, totalHeight; } LabelElement; static Ttk_ElementOptionSpec LabelElementOptions[] = { { "-compound", TK_OPTION_ANY, - Tk_Offset(LabelElement,compoundObj), "none" }, + offsetof(LabelElement,compoundObj), "none" }, { "-space", TK_OPTION_PIXELS, - Tk_Offset(LabelElement,spaceObj), "4" }, + offsetof(LabelElement,spaceObj), "4" }, /* Text element part: * NB: Keep in sync with TextElementOptions. */ { "-text", TK_OPTION_STRING, - Tk_Offset(LabelElement,text.textObj), "" }, + offsetof(LabelElement,text.textObj), "" }, { "-font", TK_OPTION_FONT, - Tk_Offset(LabelElement,text.fontObj), DEFAULT_FONT }, + offsetof(LabelElement,text.fontObj), DEFAULT_FONT }, { "-foreground", TK_OPTION_COLOR, - Tk_Offset(LabelElement,text.foregroundObj), "black" }, + offsetof(LabelElement,text.foregroundObj), "black" }, { "-underline", TK_OPTION_INT, - Tk_Offset(LabelElement,text.underlineObj), "-1"}, + offsetof(LabelElement,text.underlineObj), "-1"}, { "-width", TK_OPTION_INT, - Tk_Offset(LabelElement,text.widthObj), ""}, + offsetof(LabelElement,text.widthObj), ""}, { "-anchor", TK_OPTION_ANCHOR, - Tk_Offset(LabelElement,text.anchorObj), "w"}, + offsetof(LabelElement,text.anchorObj), "w"}, { "-justify", TK_OPTION_JUSTIFY, - Tk_Offset(LabelElement,text.justifyObj), "left" }, + offsetof(LabelElement,text.justifyObj), "left" }, { "-wraplength", TK_OPTION_PIXELS, - Tk_Offset(LabelElement,text.wrapLengthObj), "0" }, + offsetof(LabelElement,text.wrapLengthObj), "0" }, { "-embossed", TK_OPTION_INT, - Tk_Offset(LabelElement,text.embossedObj), "0"}, + offsetof(LabelElement,text.embossedObj), "0"}, /* Image element part: * NB: Keep in sync with ImageElementOptions. */ { "-image", TK_OPTION_STRING, - Tk_Offset(LabelElement,image.imageObj), "" }, + offsetof(LabelElement,image.imageObj), "" }, { "-stipple", TK_OPTION_STRING, /* Really: TK_OPTION_BITMAP */ - Tk_Offset(LabelElement,image.stippleObj), "gray50" }, + offsetof(LabelElement,image.stippleObj), "gray50" }, { "-background", TK_OPTION_COLOR, - Tk_Offset(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND }, + offsetof(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND }, { NULL, 0, 0, NULL } }; /* * LabelSetup -- @@ -574,11 +574,11 @@ /* Requested width based on -width option, not actual text width: */ if (label->compound != TTK_COMPOUND_IMAGE) textReqWidth = TextReqWidth(&label->text); - switch (label->compound) + switch (label->compound) { case TTK_COMPOUND_TEXT: *widthPtr = textReqWidth; break; case TTK_COMPOUND_IMAGE: @@ -585,15 +585,15 @@ *widthPtr = label->image.width; break; case TTK_COMPOUND_TOP: case TTK_COMPOUND_BOTTOM: case TTK_COMPOUND_CENTER: - *widthPtr = MAX(label->image.width, textReqWidth); + *widthPtr = MAX(label->image.width, textReqWidth); break; case TTK_COMPOUND_LEFT: case TTK_COMPOUND_RIGHT: - *widthPtr = label->image.width + textReqWidth + label->space; + *widthPtr = label->image.width + textReqWidth + label->space; break; case TTK_COMPOUND_NONE: break; /* Can't happen */ } Index: generic/ttk/ttkLayout.c ================================================================== --- generic/ttk/ttkLayout.c +++ generic/ttk/ttkLayout.c @@ -4,11 +4,10 @@ * Generic layout processing. * * Copyright (c) 2003 Joe English. Freely redistributable. */ -#include #include "tkInt.h" #include "ttkThemeInt.h" #define MAX(a,b) (a > b ? a : b) #define MIN(a,b) (a < b ? a : b) @@ -602,17 +601,17 @@ * Syntax: * layoutSpec ::= { elementName ?-option value ...? }+ */ /* NB: This must match bit definitions TTK_PACK_LEFT etc. */ -static const char *packSideStrings[] = +static const char *const packSideStrings[] = { "left", "right", "top", "bottom", NULL }; Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr) { enum { OP_SIDE, OP_STICKY, OP_EXPAND, OP_BORDER, OP_UNIT, OP_CHILDREN }; - static const char *optStrings[] = { + static const char *const optStrings[] = { "-side", "-sticky", "-expand", "-border", "-unit", "-children", 0 }; int i = 0, objc; Tcl_Obj **objv; Ttk_TemplateNode *head = 0, *tail = 0; Index: generic/ttk/ttkManager.c ================================================================== --- generic/ttk/ttkManager.c +++ generic/ttk/ttkManager.c @@ -2,12 +2,11 @@ * Copyright 2005, Joe English. Freely redistributable. * * Support routines for geometry managers. */ -#include -#include +#include "tkInt.h" #include "ttkManager.h" /*------------------------------------------------------------------------ * +++ The Geometry Propagation Dance. * @@ -318,11 +317,11 @@ int slaveIndex = Ttk_SlaveIndex(mgr, slaveWindow); int reqWidth = Tk_ReqWidth(slaveWindow); int reqHeight= Tk_ReqHeight(slaveWindow); if (mgr->managerSpec->SlaveRequest( - mgr->managerData, slaveIndex, reqWidth, reqHeight)) + mgr->managerData, slaveIndex, reqWidth, reqHeight)) { ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); } } Index: generic/ttk/ttkManager.h ================================================================== --- generic/ttk/ttkManager.h +++ generic/ttk/ttkManager.h @@ -20,11 +20,11 @@ * by calling Ttk_PlaceSlave(). * * SlaveRemoved() is called immediately before a slave is removed. * NB: the associated slave window may have been destroyed when this * routine is called. - * + * * SlaveRequest() is called when a slave requests a size change. * It should return 1 if the request should propagate, 0 otherwise. */ typedef struct { /* Manager hooks */ Tk_GeomMgr tkGeomMgr; /* "real" Tk Geometry Manager */ Index: generic/ttk/ttkNotebook.c ================================================================== --- generic/ttk/ttkNotebook.c +++ generic/ttk/ttkNotebook.c @@ -1,14 +1,10 @@ /* * Copyright (c) 2004, Joe English */ -#include -#include -#include -#include - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #include "ttkManager.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -60,30 +56,30 @@ * and is used to configure the slave. */ static Tk_OptionSpec TabOptionSpecs[] = { {TK_OPTION_STRING_TABLE, "-state", "", "", - "normal", -1,Tk_Offset(Tab,state), + "normal", -1, offsetof(Tab,state), 0,(ClientData)TabStateStrings,0 }, {TK_OPTION_STRING, "-text", "text", "Text", "", - Tk_Offset(Tab,textObj), -1, 0,0,GEOMETRY_CHANGED }, + offsetof(Tab,textObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/, - Tk_Offset(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + offsetof(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - "none", Tk_Offset(Tab,compoundObj), -1, + "none", offsetof(Tab,compoundObj), -1, 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED }, {TK_OPTION_INT, "-underline", "underline", "Underline", "-1", - Tk_Offset(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED }, + offsetof(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 } }; static Tk_OptionSpec PaneOptionSpecs[] = { {TK_OPTION_STRING, "-padding", "padding", "Padding", "0", - Tk_Offset(Tab,paddingObj), -1, 0,0,GEOMETRY_CHANGED }, + offsetof(Tab,paddingObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-sticky", "sticky", "Sticky", "nsew", - Tk_Offset(Tab,stickyObj), -1, 0,0,GEOMETRY_CHANGED }, + offsetof(Tab,stickyObj), -1, 0,0,GEOMETRY_CHANGED }, WIDGET_INHERIT_OPTIONS(TabOptionSpecs) }; /*------------------------------------------------------------------------ @@ -112,17 +108,17 @@ } Notebook; static Tk_OptionSpec NotebookOptionSpecs[] = { {TK_OPTION_INT, "-width", "width", "Width", "0", - Tk_Offset(Notebook,notebook.widthObj),-1, + offsetof(Notebook,notebook.widthObj),-1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_INT, "-height", "height", "Height", "0", - Tk_Offset(Notebook,notebook.heightObj),-1, + offsetof(Notebook,notebook.heightObj),-1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-padding", "padding", "Padding", NULL, - Tk_Offset(Notebook,notebook.paddingObj),-1, + offsetof(Notebook,notebook.paddingObj),-1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -219,11 +215,11 @@ Ttk_Sticky sticky = tab->sticky; Ttk_Padding padding = tab->padding; Tk_SavedOptions savedOptions; int mask = 0; - if (Tk_SetOptions(interp, (ClientData)tab, nb->notebook.paneOptionTable, + if (Tk_SetOptions(interp, tab, nb->notebook.paneOptionTable, objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK) { return TCL_ERROR; } @@ -1051,11 +1047,11 @@ * Returns name of tab element at $x,$y; empty string if none. */ static int NotebookIdentifyCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - static const char *whatTable[] = { "element", "tab", NULL }; + static const char *const whatTable[] = { "element", "tab", NULL }; enum { IDENTIFY_ELEMENT, IDENTIFY_TAB }; int what = IDENTIFY_ELEMENT; Notebook *nb = recordPtr; Ttk_Element element = NULL; int x, y, tabIndex; Index: generic/ttk/ttkPanedwindow.c ================================================================== --- generic/ttk/ttkPanedwindow.c +++ generic/ttk/ttkPanedwindow.c @@ -4,12 +4,11 @@ * ttk::panedwindow widget implementation. * * TODO: track active/pressed sash. */ -#include -#include +#include "tkInt.h" #include "ttkManager.h" #include "ttkTheme.h" #include "ttkWidget.h" /*------------------------------------------------------------------------ @@ -75,17 +74,17 @@ /* @@@ NOTE: -orient is readonly 'cause dynamic oriention changes NYI */ static Tk_OptionSpec PanedOptionSpecs[] = { {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical", - Tk_Offset(Paned,paned.orientObj), Tk_Offset(Paned,paned.orient), + offsetof(Paned,paned.orientObj), offsetof(Paned,paned.orient), 0,(ClientData)ttkOrientStrings,READONLY_OPTION|STYLE_CHANGED }, {TK_OPTION_INT, "-width", "width", "Width", "0", - -1,Tk_Offset(Paned,paned.width), + -1, offsetof(Paned,paned.width), 0,0,GEOMETRY_CHANGED }, {TK_OPTION_INT, "-height", "height", "Height", "0", - -1,Tk_Offset(Paned,paned.height), + -1, offsetof(Paned,paned.height), 0,0,GEOMETRY_CHANGED }, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -99,11 +98,11 @@ int weight; /* Pane -weight, for resizing */ } Pane; static Tk_OptionSpec PaneOptionSpecs[] = { {TK_OPTION_INT, "-weight", "weight", "Weight", "0", - -1,Tk_Offset(Pane,weight), 0,0,GEOMETRY_CHANGED }, + -1, offsetof(Pane,weight), 0,0,GEOMETRY_CHANGED }, {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; /* CreatePane -- * Create a new pane record. @@ -146,11 +145,11 @@ { Ttk_Manager *mgr = pw->paned.mgr; Tk_SavedOptions savedOptions; int mask = 0; - if (Tk_SetOptions(interp, (void*)pane, pw->paned.paneOptionTable, + if (Tk_SetOptions(interp, pane, pw->paned.paneOptionTable, objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK) { return TCL_ERROR; } @@ -713,11 +712,11 @@ * Return index of sash at $x,$y */ static int PanedIdentifyCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - static const char *whatTable[] = { "element", "sash", NULL }; + static const char *const whatTable[] = { "element", "sash", NULL }; enum { IDENTIFY_ELEMENT, IDENTIFY_SASH }; int what = IDENTIFY_SASH; Paned *pw = recordPtr; int sashThickness = pw->paned.sashThickness; int nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1; @@ -921,11 +920,11 @@ Tcl_Obj *thicknessObj; } SashElement; static Ttk_ElementOptionSpec SashElementOptions[] = { { "-sashthickness", TK_OPTION_INT, - Tk_Offset(SashElement,thicknessObj), "5" }, + offsetof(SashElement,thicknessObj), "5" }, { NULL, 0, 0, NULL } }; static void SashElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, Index: generic/ttk/ttkProgress.c ================================================================== --- generic/ttk/ttkProgress.c +++ generic/ttk/ttkProgress.c @@ -2,13 +2,11 @@ * Copyright (c) Joe English, Pat Thoyts, Michael Kirkham * * ttk::progressbar widget. */ -#include -#include - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" /*------------------------------------------------------------------------ * +++ Widget record: @@ -21,17 +19,23 @@ static const char *const ProgressbarModeStrings[] = { "determinate", "indeterminate", NULL }; typedef struct { - Tcl_Obj *orientObj; + Tcl_Obj *anchorObj; + Tcl_Obj *fontObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *justifyObj; Tcl_Obj *lengthObj; - Tcl_Obj *modeObj; - Tcl_Obj *variableObj; Tcl_Obj *maximumObj; - Tcl_Obj *valueObj; + Tcl_Obj *modeObj; + Tcl_Obj *orientObj; Tcl_Obj *phaseObj; + Tcl_Obj *textObj; + Tcl_Obj *valueObj; + Tcl_Obj *variableObj; + Tcl_Obj *wrapLengthObj; int mode; Ttk_TraceHandle *variableTrace; /* Trace handle for -variable option */ int period; /* Animation period */ int maxPhase; /* Max animation phase */ @@ -44,32 +48,50 @@ ProgressbarPart progress; } Progressbar; static Tk_OptionSpec ProgressbarOptionSpecs[] = { - {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", - "horizontal", Tk_Offset(Progressbar,progress.orientObj), -1, - 0, (ClientData)ttkOrientStrings, STYLE_CHANGED }, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", + "w", offsetof(Progressbar,progress.anchorObj), -1, + TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, + {TK_OPTION_FONT, "-font", "font", "Font", + DEFAULT_FONT, offsetof(Progressbar,progress.fontObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", + "black", offsetof(Progressbar,progress.foregroundObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "left", offsetof(Progressbar,progress.justifyObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_PIXELS, "-length", "length", "Length", - DEF_PROGRESSBAR_LENGTH, Tk_Offset(Progressbar,progress.lengthObj), -1, + DEF_PROGRESSBAR_LENGTH, offsetof(Progressbar,progress.lengthObj), -1, 0, 0, GEOMETRY_CHANGED }, - {TK_OPTION_STRING_TABLE, "-mode", "mode", "ProgressMode", "determinate", - Tk_Offset(Progressbar,progress.modeObj), - Tk_Offset(Progressbar,progress.mode), - 0, (ClientData)ProgressbarModeStrings, 0 }, {TK_OPTION_DOUBLE, "-maximum", "maximum", "Maximum", - "100", Tk_Offset(Progressbar,progress.maximumObj), -1, + "100", offsetof(Progressbar,progress.maximumObj), -1, + 0, 0, 0 }, + {TK_OPTION_STRING_TABLE, "-mode", "mode", "ProgressMode", "determinate", + offsetof(Progressbar,progress.modeObj), + offsetof(Progressbar,progress.mode), + 0, (ClientData)ProgressbarModeStrings, 0 }, + {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", + "horizontal", offsetof(Progressbar,progress.orientObj), -1, + 0, (ClientData)ttkOrientStrings, STYLE_CHANGED }, + {TK_OPTION_INT, "-phase", "phase", "Phase", + "0", offsetof(Progressbar,progress.phaseObj), -1, + 0, 0, 0 }, + {TK_OPTION_STRING, "-text", "text", "Text", "", + offsetof(Progressbar,progress.textObj), -1, + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_DOUBLE, "-value", "value", "Value", + "0.0", offsetof(Progressbar,progress.valueObj), -1, 0, 0, 0 }, {TK_OPTION_STRING, "-variable", "variable", "Variable", - NULL, Tk_Offset(Progressbar,progress.variableObj), -1, + NULL, offsetof(Progressbar,progress.variableObj), -1, TK_OPTION_NULL_OK, 0, 0 }, - {TK_OPTION_DOUBLE, "-value", "value", "Value", - "0.0", Tk_Offset(Progressbar,progress.valueObj), -1, - 0, 0, 0 }, - {TK_OPTION_INT, "-phase", "phase", "Phase", - "0", Tk_Offset(Progressbar,progress.phaseObj), -1, - 0, 0, 0 }, + {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", + "0", offsetof(Progressbar, progress.wrapLengthObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED}, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -135,11 +157,11 @@ static void CheckAnimation(Progressbar *pb) { if (AnimationEnabled(pb)) { if (pb->progress.timer == 0) { pb->progress.timer = Tcl_CreateTimerHandler( - pb->progress.period, AnimateProgressProc, (ClientData)pb); + pb->progress.period, AnimateProgressProc, pb); } } else { if (pb->progress.timer != 0) { Tcl_DeleteTimerHandler(pb->progress.timer); pb->progress.timer = 0; @@ -396,11 +418,11 @@ static int ProgressbarStepCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Progressbar *pb = recordPtr; double value = 0.0, stepAmount = 1.0; - Tcl_Obj *newValueObj; + Tcl_Obj *newValueObj; if (objc == 3) { if (Tcl_GetDoubleFromObj(interp, objv[2], &stepAmount) != TCL_OK) { return TCL_ERROR; } @@ -423,11 +445,11 @@ newValueObj = Tcl_NewDoubleObj(value); Tcl_IncrRefCount(newValueObj); TtkRedisplayWidget(&pb->core); - /* Update value by setting the linked -variable, if there is one: + /* Update value by setting the linked -variable, if there is one: */ if (pb->progress.variableTrace) { int result = Tcl_ObjSetVar2( interp, pb->progress.variableObj, 0, newValueObj, TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) @@ -444,11 +466,11 @@ return TCL_OK; } /* $sb start|stop ?args? -- - * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...] + * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...] * and pass to interpreter. */ static int ProgressbarStartStopCommand( Tcl_Interp *interp, const char *cmdName, int objc, Tcl_Obj *const objv[]) { @@ -522,11 +544,12 @@ TTK_NODE("Vertical.Progressbar.pbar", TTK_PACK_BOTTOM|TTK_FILL_X)) TTK_END_LAYOUT TTK_BEGIN_LAYOUT(HorizontalProgressbarLayout) TTK_GROUP("Horizontal.Progressbar.trough", TTK_FILL_BOTH, - TTK_NODE("Horizontal.Progressbar.pbar", TTK_PACK_LEFT|TTK_FILL_Y)) + TTK_NODE("Horizontal.Progressbar.pbar", TTK_PACK_LEFT|TTK_FILL_Y) + TTK_NODE("Horizontal.Progressbar.text", TTK_PACK_LEFT)) TTK_END_LAYOUT /* * Initialization: */ Index: generic/ttk/ttkScale.c ================================================================== --- generic/ttk/ttkScale.c +++ generic/ttk/ttkScale.c @@ -2,13 +2,11 @@ * Copyright (C) 2004 Pat Thoyts * * ttk::scale widget. */ -#include -#include -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #define DEF_SCALE_LENGTH "100" @@ -53,32 +51,32 @@ } Scale; static Tk_OptionSpec ScaleOptionSpecs[] = { {TK_OPTION_STRING, "-command", "command", "Command", "", - Tk_Offset(Scale,scale.commandObj), -1, + offsetof(Scale,scale.commandObj), -1, TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", "", - Tk_Offset(Scale,scale.variableObj), -1, + offsetof(Scale,scale.variableObj), -1, 0,0,0}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal", - Tk_Offset(Scale,scale.orientObj), - Tk_Offset(Scale,scale.orient), 0, + offsetof(Scale,scale.orientObj), + offsetof(Scale,scale.orient), 0, (ClientData)ttkOrientStrings, STYLE_CHANGED }, {TK_OPTION_DOUBLE, "-from", "from", "From", "0", - Tk_Offset(Scale,scale.fromObj), -1, 0, 0, 0}, + offsetof(Scale,scale.fromObj), -1, 0, 0, 0}, {TK_OPTION_DOUBLE, "-to", "to", "To", "1.0", - Tk_Offset(Scale,scale.toObj), -1, 0, 0, 0}, + offsetof(Scale,scale.toObj), -1, 0, 0, 0}, {TK_OPTION_DOUBLE, "-value", "value", "Value", "0", - Tk_Offset(Scale,scale.valueObj), -1, 0, 0, 0}, + offsetof(Scale,scale.valueObj), -1, 0, 0, 0}, {TK_OPTION_PIXELS, "-length", "length", "Length", - DEF_SCALE_LENGTH, Tk_Offset(Scale,scale.lengthObj), -1, 0, 0, + DEF_SCALE_LENGTH, offsetof(Scale,scale.lengthObj), -1, 0, 0, GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-state", "state", "State", - "normal", Tk_Offset(Scale,scale.stateObj), -1, + "normal", offsetof(Scale,scale.stateObj), -1, 0,0,STATE_CHANGED}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -87,11 +85,11 @@ static double PointToValue(Scale *scalePtr, int x, int y); /* ScaleVariableChanged -- * Variable trace procedure for scale -variable; * Updates the scale's value. - * If the linked variable is not a valid double, + * If the linked variable is not a valid double, * sets the 'invalid' state. */ static void ScaleVariableChanged(void *recordPtr, const char *value) { Scale *scale = recordPtr; @@ -187,11 +185,11 @@ } /* ScaleGetLayout -- * getLayout hook. */ -static Ttk_Layout +static Ttk_Layout ScaleGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) { Scale *scalePtr = recordPtr; return TtkWidgetGetOrientedLayout( interp, theme, recordPtr, scalePtr->scale.orientObj); @@ -251,11 +249,11 @@ return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction; } /* $scale get ?x y? -- - * Returns the current value of the scale widget, or if $x and + * Returns the current value of the scale widget, or if $x and * $y are specified, the value represented by point @x,y. */ static int ScaleGetCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Index: generic/ttk/ttkScroll.c ================================================================== --- generic/ttk/ttkScroll.c +++ generic/ttk/ttkScroll.c @@ -178,10 +178,23 @@ void TtkScrollbarUpdateRequired(ScrollHandle h) { h->flags |= SCROLL_UPDATE_REQUIRED; } + +/* TtkUpdateScrollInfo -- + * Call the layoutProc to update the scroll info first, last, and total. + * Do it only if needed, that is when a redisplay is pending (which + * indicates scroll info are possibly out of date). + */ + +void TtkUpdateScrollInfo(ScrollHandle h) +{ + if (h->corePtr->flags & REDISPLAY_PENDING) { + h->corePtr->widgetSpec->layoutProc(h->corePtr); + } +} /* TtkScrollviewCommand -- * Widget [xy]view command implementation. * * $w [xy]view -- return current view region @@ -191,11 +204,14 @@ */ int TtkScrollviewCommand( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle h) { Scrollable *s = h->scrollPtr; - int newFirst = s->first; + int newFirst; + + TtkUpdateScrollInfo(h); + newFirst = s->first; if (objc == 2) { Tcl_Obj *result[2]; result[0] = Tcl_NewDoubleObj((double)s->first / s->total); result[1] = Tcl_NewDoubleObj((double)s->last / s->total); @@ -224,18 +240,22 @@ break; } } } - TtkScrollTo(h, newFirst); + TtkScrollTo(h, newFirst, 0); return TCL_OK; } -void TtkScrollTo(ScrollHandle h, int newFirst) +void TtkScrollTo(ScrollHandle h, int newFirst, int updateScrollInfo) { Scrollable *s = h->scrollPtr; + + if (updateScrollInfo) { + TtkUpdateScrollInfo(h); + } if (newFirst >= s->total) newFirst = s->total - 1; if (newFirst > s->first && s->last >= s->total) /* don't scroll past end */ newFirst = s->first; Index: generic/ttk/ttkScrollbar.c ================================================================== --- generic/ttk/ttkScrollbar.c +++ generic/ttk/ttkScrollbar.c @@ -2,12 +2,11 @@ * Copyright (c) 2003, Joe English * * ttk::scrollbar widget. */ -#include - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" /*------------------------------------------------------------------------ * +++ Scrollbar widget record. @@ -20,11 +19,11 @@ Tcl_Obj *orientObj; double first; /* top fraction */ double last; /* bottom fraction */ - Ttk_Box troughBox; /* trough parcel */ + Ttk_Box troughBox; /* trough parcel */ int minSize; /* minimum size of thumb */ } ScrollbarPart; typedef struct { @@ -33,15 +32,15 @@ } Scrollbar; static Tk_OptionSpec ScrollbarOptionSpecs[] = { {TK_OPTION_STRING, "-command", "command", "Command", "", - Tk_Offset(Scrollbar,scrollbar.commandObj), -1, 0,0,0}, + offsetof(Scrollbar,scrollbar.commandObj), -1, 0,0,0}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical", - Tk_Offset(Scrollbar,scrollbar.orientObj), - Tk_Offset(Scrollbar,scrollbar.orient), + offsetof(Scrollbar,scrollbar.orientObj), + offsetof(Scrollbar,scrollbar.orient), 0,(ClientData)ttkOrientStrings,STYLE_CHANGED }, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -48,11 +47,11 @@ /*------------------------------------------------------------------------ * +++ Widget hooks. */ -static void +static void ScrollbarInitialize(Tcl_Interp *interp, void *recordPtr) { Scrollbar *sb = recordPtr; sb->scrollbar.first = 0.0; sb->scrollbar.last = 1.0; @@ -239,11 +238,11 @@ return TCL_OK; } /* $sb fraction $x $y -- * Returns a real number between 0 and 1 indicating where the - * point given by x and y lies in the trough area of the scrollbar. + * point given by x and y lies in the trough area of the scrollbar. */ static int ScrollbarFractionCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Index: generic/ttk/ttkSeparator.c ================================================================== --- generic/ttk/ttkSeparator.c +++ generic/ttk/ttkSeparator.c @@ -2,12 +2,11 @@ * Copyright (c) 2004, Joe English * * ttk::separator and ttk::sizegrip widgets. */ -#include - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" /* +++ Separator widget record: */ @@ -23,12 +22,12 @@ SeparatorPart separator; } Separator; static Tk_OptionSpec SeparatorOptionSpecs[] = { {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal", - Tk_Offset(Separator,separator.orientObj), - Tk_Offset(Separator,separator.orient), + offsetof(Separator,separator.orientObj), + offsetof(Separator,separator.orient), 0,(ClientData)ttkOrientStrings,STYLE_CHANGED }, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; Index: generic/ttk/ttkSquare.c ================================================================== --- generic/ttk/ttkSquare.c +++ generic/ttk/ttkSquare.c @@ -1,11 +1,11 @@ /* square.c - Copyright (C) 2004 Pat Thoyts * * Minimal sample ttk widget. */ -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #if defined(TTK_SQUARE_WIDGET) || 1 @@ -49,33 +49,33 @@ */ static Tk_OptionSpec SquareOptionSpecs[] = { {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEFAULT_BORDERWIDTH, Tk_Offset(Square,square.borderWidthObj), -1, + DEFAULT_BORDERWIDTH, offsetof(Square,square.borderWidthObj), -1, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground", - DEFAULT_BACKGROUND, Tk_Offset(Square,square.foregroundObj), + DEFAULT_BACKGROUND, offsetof(Square,square.foregroundObj), -1, 0, 0, 0}, - + {TK_OPTION_PIXELS, "-width", "width", "Width", - "50", Tk_Offset(Square,square.widthObj), -1, 0, 0, + "50", offsetof(Square,square.widthObj), -1, 0, 0, GEOMETRY_CHANGED}, {TK_OPTION_PIXELS, "-height", "height", "Height", - "50", Tk_Offset(Square,square.heightObj), -1, 0, 0, + "50", offsetof(Square,square.heightObj), -1, 0, 0, GEOMETRY_CHANGED}, - + {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL, - Tk_Offset(Square,square.paddingObj), -1, + offsetof(Square,square.paddingObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, - + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - NULL, Tk_Offset(Square,square.reliefObj), -1, TK_OPTION_NULL_OK, 0, 0}, - + NULL, offsetof(Square,square.reliefObj), -1, TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - NULL, Tk_Offset(Square,square.anchorObj), -1, TK_OPTION_NULL_OK, 0, 0}, - + NULL, offsetof(Square,square.anchorObj), -1, TK_OPTION_NULL_OK, 0, 0}, + WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; /* @@ -136,11 +136,11 @@ { "state", TtkWidgetStateCommand,0 }, { 0,0,0 } }; /* - * The Widget specification structure holds all the implementation + * The Widget specification structure holds all the implementation * information about this widget and this is what must be registered * with Tk in the package initialization code (see bottom). */ static WidgetSpec SquareWidgetSpec = @@ -157,11 +157,11 @@ TtkWidgetSize, /* sizeProc */ SquareDoLayout, /* layoutProc */ TtkWidgetDisplay /* displayProc */ }; -/* ---------------------------------------------------------------------- +/* ---------------------------------------------------------------------- * Square element * * In this section we demonstrate what is required to create a new themed * element. */ @@ -174,22 +174,22 @@ Tcl_Obj *reliefObj; Tcl_Obj *widthObj; Tcl_Obj *heightObj; } SquareElement; -static Ttk_ElementOptionSpec SquareElementOptions[] = -{ - { "-background", TK_OPTION_BORDER, Tk_Offset(SquareElement,borderObj), - DEFAULT_BACKGROUND }, - { "-foreground", TK_OPTION_BORDER, Tk_Offset(SquareElement,foregroundObj), - DEFAULT_BACKGROUND }, - { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SquareElement,borderWidthObj), - DEFAULT_BORDERWIDTH }, - { "-relief", TK_OPTION_RELIEF, Tk_Offset(SquareElement,reliefObj), - "raised" }, - { "-width", TK_OPTION_PIXELS, Tk_Offset(SquareElement,widthObj), "20"}, - { "-height", TK_OPTION_PIXELS, Tk_Offset(SquareElement,heightObj), "20"}, +static Ttk_ElementOptionSpec SquareElementOptions[] = +{ + { "-background", TK_OPTION_BORDER, offsetof(SquareElement,borderObj), + DEFAULT_BACKGROUND }, + { "-foreground", TK_OPTION_BORDER, offsetof(SquareElement,foregroundObj), + DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, offsetof(SquareElement,borderWidthObj), + DEFAULT_BORDERWIDTH }, + { "-relief", TK_OPTION_RELIEF, offsetof(SquareElement,reliefObj), + "raised" }, + { "-width", TK_OPTION_PIXELS, offsetof(SquareElement,widthObj), "20"}, + { "-height", TK_OPTION_PIXELS, offsetof(SquareElement,heightObj), "20"}, { NULL, 0, 0, NULL } }; /* * The element geometry function is called when the layout code wishes to @@ -246,25 +246,25 @@ * Every widget class needs a layout style that specifies which elements * are part of the widget and how they should be placed. The element layout * engine is similar to the Tk pack geometry manager. Read the documentation * for the details. In this example we just need to have the square element * that has been defined for this widget placed on a background. We will - * also need some padding to keep it away from the edges. + * also need some padding to keep it away from the edges. */ TTK_BEGIN_LAYOUT(SquareLayout) TTK_NODE("Square.background", TTK_FILL_BOTH) TTK_GROUP("Square.padding", TTK_FILL_BOTH, TTK_NODE("Square.square", 0)) TTK_END_LAYOUT -/* ---------------------------------------------------------------------- +/* ---------------------------------------------------------------------- * * Widget initialization. * * This file defines a new element and a new widget. We need to register - * the element with the themes that will need it. In this case we will + * the element with the themes that will need it. In this case we will * register with the default theme that is the root of the theme inheritance * tree. This means all themes will find this element. * We then need to register the widget class style. This is the layout * specification. If a different theme requires an alternative layout, we * could register that here. For instance, in some themes the scrollbars have @@ -285,17 +285,17 @@ { Ttk_Theme theme = Ttk_GetDefaultTheme(interp); /* register the new elements for this theme engine */ Ttk_RegisterElement(interp, theme, "square", &SquareElementSpec, NULL); - + /* register the layout for this theme */ Ttk_RegisterLayout(theme, "TSquare", SquareLayout); - + /* register the widget */ RegisterWidget(interp, "ttk::square", &SquareWidgetSpec); return TCL_OK; } #endif /* TTK_SQUARE_WIDGET */ Index: generic/ttk/ttkState.c ================================================================== --- generic/ttk/ttkState.c +++ generic/ttk/ttkState.c @@ -3,13 +3,11 @@ * * Copyright (c) 2003 Joe English. Freely redistributable. * */ -#include - -#include +#include "tkInt.h" #include "ttkTheme.h" /* * Table of state names. Must be kept in sync with TTK_STATE_* * #defines in ttkTheme.h. Index: generic/ttk/ttkStubLib.c ================================================================== --- generic/ttk/ttkStubLib.c +++ generic/ttk/ttkStubLib.c @@ -65,10 +65,10 @@ Tcl_ResetResult(interp); Tcl_AppendResult(interp, "Error loading ", packageName, " package", " (requested version '", version, "', loaded version '", actualVersion, "'): ", - errMsg, + errMsg, NULL); return NULL; } Index: generic/ttk/ttkTagSet.c ================================================================== --- generic/ttk/ttkTagSet.c +++ generic/ttk/ttkTagSet.c @@ -2,14 +2,11 @@ * Tag tables. 3/4-baked, work in progress. * * Copyright (C) 2005, Joe English. Freely redistributable. */ -#include /* for memset() */ -#include -#include - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" /*------------------------------------------------------------------------ * +++ Internal data structures. @@ -186,11 +183,11 @@ for (i = 0; i < tagset->nTags; ++i) { if (tagset->tags[i] == tag) { return 0; } } - tagset->tags = ckrealloc(tagset->tags, + tagset->tags = ckrealloc(tagset->tags, (tagset->nTags+1)*sizeof(tagset->tags[0])); tagset->tags[tagset->nTags++] = tag; return 1; } Index: generic/ttk/ttkTheme.c ================================================================== --- generic/ttk/ttkTheme.c +++ generic/ttk/ttkTheme.c @@ -147,11 +147,11 @@ if (!optionSpec) return 0; /* Make sure widget option has a Tcl_Obj* entry: */ - if (optionSpec->objOffset < 0) { + if (optionSpec->objOffset == TCL_AUTO_LENGTH) { return 0; } /* Grrr. Ignore accidental mismatches caused by prefix-matching: */ @@ -976,33 +976,33 @@ static int InitializeElementRecord( Ttk_ElementClass *eclass, /* Element instance to initialize */ Ttk_Style style, /* Style table */ - char *widgetRecord, /* Source of widget option values */ + void *widgetRecord, /* Source of widget option values */ Tk_OptionTable optionTable, /* Option table describing widget record */ Tk_Window tkwin, /* Corresponding window */ Ttk_State state) /* Widget or element state */ { - char *elementRecord = eclass->elementRecord; + void *elementRecord = eclass->elementRecord; OptionMap optionMap = GetOptionMap(eclass,optionTable); int nResources = eclass->nResources; Ttk_ResourceCache cache = style->cache; Ttk_ElementOptionSpec *elementOption = eclass->specPtr->options; int i; for (i=0; ioffset); + ((char *)elementRecord + elementOption->offset); const char *optionName = elementOption->optionName; Tcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state); Tcl_Obj *widgetValue = 0; Tcl_Obj *elementDefault = eclass->defaultValues[i]; if (optionMap[i]) { widgetValue = *(Tcl_Obj **) - (widgetRecord + optionMap[i]->objOffset); + ((char *)widgetRecord + optionMap[i]->objOffset); } if (widgetValue) { *dest = widgetValue; } else if (dynamicSetting) { @@ -1070,11 +1070,11 @@ void Ttk_ElementSize( Ttk_ElementClass *eclass, /* Element to query */ Ttk_Style style, /* Style settings */ - char *recordPtr, /* The widget record. */ + void *recordPtr, /* The widget record. */ Tk_OptionTable optionTable, /* Description of widget record */ Tk_Window tkwin, /* The widget window. */ Ttk_State state, /* Current widget state */ int *widthPtr, /* Requested width */ int *heightPtr, /* Reqested height */ @@ -1100,11 +1100,11 @@ void Ttk_DrawElement( Ttk_ElementClass *eclass, /* Element instance */ Ttk_Style style, /* Style settings */ - char *recordPtr, /* The widget record. */ + void *recordPtr, /* The widget record. */ Tk_OptionTable optionTable, /* Description of option table */ Tk_Window tkwin, /* The widget window. */ Drawable d, /* Where to draw element. */ Ttk_Box b, /* Element area */ Ttk_State state) /* Widget or element state flags. */ @@ -1380,11 +1380,11 @@ */ static int StyleThemeCreateCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { StylePackageData *pkgPtr = clientData; - static const char *optStrings[] = + static const char *const optStrings[] = { "-parent", "-settings", NULL }; enum { OP_PARENT, OP_SETTINGS }; Ttk_Theme parentTheme = pkgPtr->defaultTheme, newTheme; Tcl_Obj *settingsScript = NULL; const char *themeName; Index: generic/ttk/ttkTheme.h ================================================================== --- generic/ttk/ttkTheme.h +++ generic/ttk/ttkTheme.h @@ -27,13 +27,17 @@ /*------------------------------------------------------------------------ * +++ Defaults for element option specifications. */ #define DEFAULT_FONT "TkDefaultFont" +#ifdef MAC_OSX_TK +#define DEFAULT_BACKGROUND "systemTextBackgroundColor" +#define DEFAULT_FOREGROUND "systemTextColor" +#else #define DEFAULT_BACKGROUND "#d9d9d9" #define DEFAULT_FOREGROUND "black" - +#endif /*------------------------------------------------------------------------ * +++ Widget states. * Keep in sync with stateNames[] in tkstate.c. */ @@ -231,16 +235,24 @@ typedef void (Ttk_ElementSizeProc)(void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding*); typedef void (Ttk_ElementDrawProc)(void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state); + +#ifndef TkSizeT +# if TCL_MAJOR_VERSION > 8 +# define TkSizeT size_t +# else +# define TkSizeT int +# endif +#endif typedef struct Ttk_ElementOptionSpec { const char *optionName; /* Command-line name of the widget option */ Tk_OptionType type; /* Accepted option types */ - int offset; /* Offset of Tcl_Obj* field in element record */ + TkSizeT offset; /* Offset of Tcl_Obj* field in element record */ const char *defaultValue; /* Default value to used if resource missing */ } Ttk_ElementOptionSpec; #define TK_OPTION_ANY TK_OPTION_STRING Index: generic/ttk/ttkThemeInt.h ================================================================== --- generic/ttk/ttkThemeInt.h +++ generic/ttk/ttkThemeInt.h @@ -13,15 +13,15 @@ MODULE_SCOPE Ttk_ElementClass *Ttk_GetElement(Ttk_Theme, const char *name); MODULE_SCOPE const char *Ttk_ElementClassName(Ttk_ElementClass *); MODULE_SCOPE void Ttk_ElementSize( - Ttk_ElementClass *, Ttk_Style, char *recordPtr, Tk_OptionTable, + Ttk_ElementClass *, Ttk_Style, void *recordPtr, Tk_OptionTable, Tk_Window tkwin, Ttk_State state, int *widthPtr, int *heightPtr, Ttk_Padding*); MODULE_SCOPE void Ttk_DrawElement( - Ttk_ElementClass *, Ttk_Style, char *recordPtr, Tk_OptionTable, + Ttk_ElementClass *, Ttk_Style, void *recordPtr, Tk_OptionTable, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state); MODULE_SCOPE Tcl_Obj *Ttk_QueryStyle( Ttk_Style, void *, Tk_OptionTable, const char *, Ttk_State state); Index: generic/ttk/ttkTrace.c ================================================================== --- generic/ttk/ttkTrace.c +++ generic/ttk/ttkTrace.c @@ -1,15 +1,15 @@ /* * Copyright 2003, Joe English * * Simplified interface to Tcl_TraceVariable. * - * PROBLEM: Can't distinguish "variable does not exist" (which is OK) + * PROBLEM: Can't distinguish "variable does not exist" (which is OK) * from other errors (which are not). */ -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" struct TtkTraceHandle_ { @@ -24,30 +24,19 @@ */ static char * VarTraceProc( ClientData clientData, /* Widget record pointer */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Name of variable. */ - const char *name2, /* Second part of variable name. */ + const char *name1, /* (unused) */ + const char *name2, /* (unused) */ int flags) /* Information about what happened. */ { Ttk_TraceHandle *tracePtr = clientData; const char *name, *value; Tcl_Obj *valuePtr; - if (flags & TCL_INTERP_DESTROYED) { - return NULL; - } - - /* - * See ticket [5d991b82]. - */ - - if (tracePtr->varnameObj == NULL) { - Tcl_UntraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - VarTraceProc, clientData); + if (Tcl_InterpDeleted(interp)) { return NULL; } name = Tcl_GetString(tracePtr->varnameObj); Index: generic/ttk/ttkTrack.c ================================================================== --- generic/ttk/ttkTrack.c +++ generic/ttk/ttkTrack.c @@ -21,11 +21,11 @@ * event. * * TODO: Handle "chords" properly (e.g., ) */ -#include +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" typedef struct { WidgetCore *corePtr; /* widget to track */ Index: generic/ttk/ttkTreeview.c ================================================================== --- generic/ttk/ttkTreeview.c +++ generic/ttk/ttkTreeview.c @@ -2,12 +2,10 @@ * Copyright (c) 2004, Joe English * * ttk::treeview widget implementation. */ -#include -#include #include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #define DEF_TREE_ROWS "10" @@ -61,23 +59,23 @@ #define ITEM_OPTION_TAGS_CHANGED 0x100 #define ITEM_OPTION_IMAGE_CHANGED 0x200 static Tk_OptionSpec ItemOptionSpecs[] = { {TK_OPTION_STRING, "-text", "text", "Text", - "", Tk_Offset(TreeItem,textObj), -1, + "", offsetof(TreeItem,textObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-image", "image", "Image", - NULL, Tk_Offset(TreeItem,imageObj), -1, + NULL, offsetof(TreeItem,imageObj), -1, TK_OPTION_NULL_OK,0,ITEM_OPTION_IMAGE_CHANGED }, {TK_OPTION_STRING, "-values", "values", "Values", - NULL, Tk_Offset(TreeItem,valuesObj), -1, + NULL, offsetof(TreeItem,valuesObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_BOOLEAN, "-open", "open", "Open", - "0", Tk_Offset(TreeItem,openObj), -1, + "0", offsetof(TreeItem,openObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-tags", "tags", "Tags", - NULL, Tk_Offset(TreeItem,tagsObj), -1, + NULL, offsetof(TreeItem,tagsObj), -1, TK_OPTION_NULL_OK,0,ITEM_OPTION_TAGS_CHANGED }, {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; @@ -189,26 +187,26 @@ Tcl_Obj *fontObj; } DisplayItem; static Tk_OptionSpec TagOptionSpecs[] = { {TK_OPTION_STRING, "-text", "text", "Text", - NULL, Tk_Offset(DisplayItem,textObj), -1, + NULL, offsetof(DisplayItem,textObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_STRING, "-image", "image", "Image", - NULL, Tk_Offset(DisplayItem,imageObj), -1, + NULL, offsetof(DisplayItem,imageObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - NULL, Tk_Offset(DisplayItem,anchorObj), -1, + NULL, offsetof(DisplayItem,anchorObj), -1, TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, /* <> */ {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", - NULL, Tk_Offset(DisplayItem,backgroundObj), -1, + NULL, offsetof(DisplayItem,backgroundObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", - NULL, Tk_Offset(DisplayItem,foregroundObj), -1, + NULL, offsetof(DisplayItem,foregroundObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_FONT, "-font", "font", "Font", - NULL, Tk_Offset(DisplayItem,fontObj), -1, + NULL, offsetof(DisplayItem,fontObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; @@ -273,42 +271,42 @@ /* Don't touch column->data, it's scratch storage */ } static Tk_OptionSpec ColumnOptionSpecs[] = { {TK_OPTION_INT, "-width", "width", "Width", - DEF_COLWIDTH, -1, Tk_Offset(TreeColumn,width), + DEF_COLWIDTH, -1, offsetof(TreeColumn,width), 0,0,GEOMETRY_CHANGED }, {TK_OPTION_INT, "-minwidth", "minWidth", "MinWidth", - DEF_MINWIDTH, -1, Tk_Offset(TreeColumn,minWidth), + DEF_MINWIDTH, -1, offsetof(TreeColumn,minWidth), 0,0,0 }, {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch", - "1", -1, Tk_Offset(TreeColumn,stretch), - 0,0,0 }, + "1", -1, offsetof(TreeColumn,stretch), + 0,0,GEOMETRY_CHANGED }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - "w", Tk_Offset(TreeColumn,anchorObj), -1, /* <> */ + "w", offsetof(TreeColumn,anchorObj), -1, /* <> */ 0,0,0 }, {TK_OPTION_STRING, "-id", "id", "ID", - NULL, Tk_Offset(TreeColumn,idObj), -1, + NULL, offsetof(TreeColumn,idObj), -1, TK_OPTION_NULL_OK,0,READONLY_OPTION }, {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; static Tk_OptionSpec HeadingOptionSpecs[] = { {TK_OPTION_STRING, "-text", "text", "Text", - "", Tk_Offset(TreeColumn,headingObj), -1, + "", offsetof(TreeColumn,headingObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-image", "image", "Image", - "", Tk_Offset(TreeColumn,headingImageObj), -1, + "", offsetof(TreeColumn,headingImageObj), -1, 0,0,0 }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - "center", Tk_Offset(TreeColumn,headingAnchorObj), -1, + "center", offsetof(TreeColumn,headingAnchorObj), -1, 0,0,0 }, {TK_OPTION_STRING, "-command", "", "", - "", Tk_Offset(TreeColumn,headingCommandObj), -1, + "", offsetof(TreeColumn,headingCommandObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_STRING, "state", "", "", - "", Tk_Offset(TreeColumn,headingStateObj), -1, + "", offsetof(TreeColumn,headingStateObj), -1, 0,0,STATE_CHANGED }, {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; /*------------------------------------------------------------------------ @@ -319,18 +317,18 @@ #define SHOW_TREE (0x1) /* Show tree column? */ #define SHOW_HEADINGS (0x2) /* Show heading row? */ #define DEFAULT_SHOW "tree headings" -static const char *showStrings[] = { +static const char *const showStrings[] = { "tree", "headings", NULL }; static int GetEnumSetFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, - const char *table[], + const char *const table[], unsigned *resultPtr) { unsigned result = 0; int i, objc; Tcl_Obj **objv; @@ -433,39 +431,39 @@ #define COLUMNS_CHANGED (USER_MASK) #define DCOLUMNS_CHANGED (USER_MASK<<1) #define SCROLLCMD_CHANGED (USER_MASK<<2) #define SHOW_CHANGED (USER_MASK<<3) -static const char *SelectModeStrings[] = { "none", "browse", "extended", NULL }; +static const char *const SelectModeStrings[] = { "none", "browse", "extended", NULL }; static Tk_OptionSpec TreeviewOptionSpecs[] = { {TK_OPTION_STRING, "-columns", "columns", "Columns", - "", Tk_Offset(Treeview,tree.columnsObj), -1, + "", offsetof(Treeview,tree.columnsObj), -1, 0,0,COLUMNS_CHANGED | GEOMETRY_CHANGED /*| READONLY_OPTION*/ }, {TK_OPTION_STRING, "-displaycolumns","displayColumns","DisplayColumns", - "#all", Tk_Offset(Treeview,tree.displayColumnsObj), -1, + "#all", offsetof(Treeview,tree.displayColumnsObj), -1, 0,0,DCOLUMNS_CHANGED | GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-show", "show", "Show", - DEFAULT_SHOW, Tk_Offset(Treeview,tree.showObj), -1, + DEFAULT_SHOW, offsetof(Treeview,tree.showObj), -1, 0,0,SHOW_CHANGED | GEOMETRY_CHANGED }, {TK_OPTION_STRING_TABLE, "-selectmode", "selectMode", "SelectMode", - "extended", Tk_Offset(Treeview,tree.selectModeObj), -1, + "extended", offsetof(Treeview,tree.selectModeObj), -1, 0,(ClientData)SelectModeStrings,0 }, {TK_OPTION_PIXELS, "-height", "height", "Height", - DEF_TREE_ROWS, Tk_Offset(Treeview,tree.heightObj), -1, + DEF_TREE_ROWS, offsetof(Treeview,tree.heightObj), -1, 0,0,GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-padding", "padding", "Pad", - NULL, Tk_Offset(Treeview,tree.paddingObj), -1, + NULL, offsetof(Treeview,tree.paddingObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - NULL, -1, Tk_Offset(Treeview, tree.xscroll.scrollCmd), + NULL, -1, offsetof(Treeview, tree.xscroll.scrollCmd), TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - NULL, -1, Tk_Offset(Treeview, tree.yscroll.scrollCmd), + NULL, -1, offsetof(Treeview, tree.yscroll.scrollCmd), TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -921,11 +919,11 @@ * +++ Event handlers. */ static TreeItem *IdentifyItem(Treeview *tv, int y); /*forward*/ -static const unsigned int TreeviewBindEventMask = +static const unsigned long TreeviewBindEventMask = KeyPressMask|KeyReleaseMask | ButtonPressMask|ButtonReleaseMask | PointerMotionMask|ButtonMotionMask | VirtualEventMask ; @@ -1064,11 +1062,11 @@ if (tv->tree.rowLayout) Ttk_FreeLayout(tv->tree.rowLayout); TreeviewFreeColumns(tv); if (tv->tree.displayColumns) - Tcl_Free((ClientData)tv->tree.displayColumns); + ckfree((ClientData)tv->tree.displayColumns); foreachHashEntry(&tv->tree.items, FreeItemCB); Tcl_DeleteHashTable(&tv->tree.items); TtkFreeScrollHandle(tv->tree.xscrollHandle); @@ -1129,11 +1127,11 @@ Tk_SavedOptions savedOptions; int mask; Ttk_ImageSpec *newImageSpec = NULL; Ttk_TagSet newTagSet = NULL; - if (Tk_SetOptions(interp, (ClientData)item, tv->tree.itemOptionTable, + if (Tk_SetOptions(interp, item, tv->tree.itemOptionTable, objc, objv, tv->core.tkwin, &savedOptions, &mask) != TCL_OK) { return TCL_ERROR; } @@ -1209,11 +1207,11 @@ int objc, Tcl_Obj *const objv[]) { Tk_SavedOptions savedOptions; int mask; - if (Tk_SetOptions(interp, (ClientData)column, + if (Tk_SetOptions(interp, column, tv->tree.columnOptionTable, objc, objv, tv->core.tkwin, &savedOptions,&mask) != TCL_OK) { return TCL_ERROR; } @@ -1232,15 +1230,14 @@ if (mask & GEOMETRY_CHANGED) { if (!Tk_IsMapped(tv->core.tkwin)) { TtkResizeWidget(&tv->core); } RecomputeSlack(tv); + ResizeColumns(tv, TreeWidth(tv)); } TtkRedisplayWidget(&tv->core); - /* ASSERT: SLACKINVARIANT */ - Tk_FreeSavedOptions(&savedOptions); return TCL_OK; error: Tk_RestoreSavedOptions(&savedOptions); @@ -1255,11 +1252,11 @@ int objc, Tcl_Obj *const objv[]) { Tk_SavedOptions savedOptions; int mask; - if (Tk_SetOptions(interp, (ClientData)column, + if (Tk_SetOptions(interp, column, tv->tree.headingOptionTable, objc, objv, tv->core.tkwin, &savedOptions,&mask) != TCL_OK) { return TCL_ERROR; } @@ -1501,11 +1498,11 @@ REGION_SEPARATOR, REGION_TREE, REGION_CELL } TreeRegion; -static const char *regionStrings[] = { +static const char *const regionStrings[] = { "nothing", "heading", "separator", "tree", "cell", 0 }; static TreeRegion IdentifyRegion(Treeview *tv, int x, int y) { @@ -1613,17 +1610,14 @@ static void TreeviewDoLayout(void *clientData) { Treeview *tv = clientData; int visibleRows; - /* ASSERT: SLACKINVARIANT */ - Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin)); tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, "treearea"); ResizeColumns(tv, tv->tree.treeArea.width); - /* ASSERT: SLACKINVARIANT */ TtkScrolled(tv->tree.xscrollHandle, tv->tree.xscroll.first, tv->tree.xscroll.first + tv->tree.treeArea.width, TreeWidth(tv)); @@ -2144,11 +2138,11 @@ Tcl_WrongNumArgs(interp, 2, objv, "itemid"); return TCL_ERROR; } entryPtr = Tcl_FindHashEntry(&tv->tree.items, Tcl_GetString(objv[2])); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(entryPtr != 0)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(entryPtr != 0)); return TCL_OK; } /* + $tv bbox $itemid ?$column? -- * Return bounding box [x y width height] of specified item. @@ -2231,11 +2225,13 @@ Ttk_Box itemBox; DisplayItem displayItem; Ttk_Element element; BoundingBox(tv, item, NULL, &itemBox); - PrepareItem(tv, item, &displayItem); /*@@@ FIX: -text, etc*/ + PrepareItem(tv, item, &displayItem); + if (item->textObj) { displayItem.textObj = item->textObj; } + if (item->imageObj) { displayItem.imageObj = item->imageObj; } Ttk_RebindSublayout(layout, &displayItem); Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox); element = Ttk_IdentifyElement(layout, x, y); if (element) { @@ -2264,11 +2260,11 @@ */ static int TreeviewIdentifyCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - static const char *submethodStrings[] = + static const char *const submethodStrings[] = { "region", "item", "column", "row", "element", NULL }; enum { I_REGION, I_ITEM, I_COLUMN, I_ROW, I_ELEMENT }; Treeview *tv = recordPtr; int submethod; @@ -2343,11 +2339,13 @@ if (!BoundingBox(tv, item, column, &bbox)) { return TCL_OK; } - PrepareItem(tv, item, &displayItem); /*@@@ FIX: fill in -text,etc */ + PrepareItem(tv, item, &displayItem); + if (item->textObj) { displayItem.textObj = item->textObj; } + if (item->imageObj) { displayItem.imageObj = item->imageObj; } Ttk_RebindSublayout(layout, &displayItem); Ttk_PlaceLayout(layout, ItemState(tv,item), bbox); element = Ttk_IdentifyElement(layout, x, y); if (element) { @@ -2678,11 +2676,11 @@ static int TreeviewDeleteCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Treeview *tv = recordPtr; TreeItem **items, *delq; - int i; + int i, selItemDeleted = 0; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "items"); return TCL_ERROR; } @@ -2705,10 +2703,13 @@ /* Remove items from hash table. */ delq = 0; for (i=0; items[i]; ++i) { + if (items[i]->state & TTK_STATE_SELECTED) { + selItemDeleted = 1; + } delq = DeleteItems(items[i], delq); } /* Free items: */ @@ -2721,10 +2722,13 @@ FreeItem(delq); delq = next; } ckfree(items); + if (selItemDeleted) { + TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect"); + } TtkRedisplayWidget(&tv->core); return TCL_OK; } /* + $tv move $item $parent $index @@ -2839,14 +2843,14 @@ /* Make sure item is visible: */ rowNumber = RowNumber(tv, item); if (rowNumber < tv->tree.yscroll.first) { - TtkScrollTo(tv->tree.yscrollHandle, rowNumber); + TtkScrollTo(tv->tree.yscrollHandle, rowNumber, 1); } else if (rowNumber >= tv->tree.yscroll.last) { TtkScrollTo(tv->tree.yscrollHandle, - tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last)); + tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last), 1); } return TCL_OK; } @@ -2879,13 +2883,32 @@ for (;i < tv->tree.nDisplayColumns; ++i) { TreeColumn *c = tv->tree.displayColumns[i]; int right = left + c->width; if (c == column) { - DragColumn(tv, i, newx - right); - /* ASSERT: SLACKINVARIANT */ - TtkRedisplayWidget(&tv->core); + /* The limit not to exceed at the right is given by the tree width + minus the sum of the min widths of the columns at the right of + the one being resized (and don't forget possible x scrolling!). + For stretchable columns, this min width really is the minWidth, + for non-stretchable columns, this is the column width. + */ + int newxRightLimit = tv->tree.treeArea.x - tv->tree.xscroll.first + + tv->tree.treeArea.width; + int j = i + 1; + while (j < tv->tree.nDisplayColumns) { + TreeColumn *cr = tv->tree.displayColumns[j]; + if (cr->stretch) { + newxRightLimit -= cr->minWidth; + } else { + newxRightLimit -= cr->width; + } + ++j; + } + if (newx <= newxRightLimit) { + DragColumn(tv, i, newx - right); + TtkRedisplayWidget(&tv->core); + } return TCL_OK; } left = right; } @@ -2892,10 +2915,24 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "column %s is not displayed", Tcl_GetString(objv[2]))); Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN_INVISIBLE", NULL); return TCL_ERROR; } + +static int TreeviewDropCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "drop"); + return TCL_ERROR; + } + ResizeColumns(tv, TreeWidth(tv)); + TtkRedisplayWidget(&tv->core); + return TCL_OK; +} /*------------------------------------------------------------------------ * +++ Widget commands -- focus and selection */ @@ -2930,11 +2967,11 @@ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { enum { SELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE }; - static const char *selopStrings[] = { + static const char *const selopStrings[] = { "set", "add", "remove", "toggle", NULL }; Treeview *tv = recordPtr; int selop, i; @@ -3110,11 +3147,11 @@ TreeItem *item = FindItem(interp, tv, objv[4]); if (!item) { return TCL_ERROR; } Tcl_SetObjResult(interp, - Tcl_NewBooleanObj(Ttk_TagSetContains(item->tagset, tag))); + Tcl_NewWideIntObj(Ttk_TagSetContains(item->tagset, tag))); return TCL_OK; } else { Tcl_WrongNumArgs(interp, 3, objv, "tagName ?item?"); return TCL_ERROR; } @@ -3242,10 +3279,11 @@ { "column", TreeviewColumnCommand,0 }, { "configure", TtkWidgetConfigureCommand,0 }, { "delete", TreeviewDeleteCommand,0 }, { "detach", TreeviewDetachCommand,0 }, { "drag", TreeviewDragCommand,0 }, + { "drop", TreeviewDropCommand,0 }, { "exists", TreeviewExistsCommand,0 }, { "focus", TreeviewFocusCommand,0 }, { "heading", TreeviewHeadingCommand,0 }, { "identify", TreeviewIdentifyCommand,0 }, { "index", TreeviewIndexCommand,0 }, @@ -3329,15 +3367,15 @@ Tcl_Obj *marginsObj; } TreeitemIndicator; static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = { { "-foreground", TK_OPTION_COLOR, - Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND }, + offsetof(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND }, { "-indicatorsize", TK_OPTION_PIXELS, - Tk_Offset(TreeitemIndicator,sizeObj), "12" }, + offsetof(TreeitemIndicator,sizeObj), "12" }, { "-indicatormargins", TK_OPTION_STRING, - Tk_Offset(TreeitemIndicator,marginsObj), "2 2 4 2" }, + offsetof(TreeitemIndicator,marginsObj), "2 2 4 2" }, { NULL, 0, 0, NULL } }; static void TreeitemIndicatorSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -3398,13 +3436,13 @@ Tcl_Obj *rowNumberObj; } RowElement; static Ttk_ElementOptionSpec RowElementOptions[] = { { "-background", TK_OPTION_COLOR, - Tk_Offset(RowElement,backgroundObj), DEFAULT_BACKGROUND }, + offsetof(RowElement,backgroundObj), DEFAULT_BACKGROUND }, { "-rownumber", TK_OPTION_INT, - Tk_Offset(RowElement,rowNumberObj), "0" }, + offsetof(RowElement,rowNumberObj), "0" }, { NULL, 0, 0, NULL } }; static void RowElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Index: generic/ttk/ttkWidget.c ================================================================== --- generic/ttk/ttkWidget.c +++ generic/ttk/ttkWidget.c @@ -2,11 +2,10 @@ * Copyright (c) 2003, Joe English * * Core widget utilities. */ -#include #include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #ifdef MAC_OSX_TK @@ -333,11 +332,11 @@ WidgetCore *corePtr = clientData; SizeChanged(corePtr); TtkRedisplayWidget(corePtr); } -static Tk_ClassProcs widgetClassProcs = { +static const Tk_ClassProcs widgetClassProcs = { sizeof(Tk_ClassProcs), /* size */ WidgetWorldChanged, /* worldChangedProc */ NULL, /* createProc */ NULL /* modalProc */ }; @@ -737,11 +736,11 @@ if (status != TCL_OK) return status; if (objc == 3) { Tcl_SetObjResult(interp, - Tcl_NewBooleanObj(Ttk_StateMatches(state,&spec))); + Tcl_NewWideIntObj(Ttk_StateMatches(state,&spec))); } else if (objc == 4) { if (Ttk_StateMatches(state,&spec)) { status = Tcl_EvalObjEx(interp, objv[3], 0); } } @@ -755,11 +754,11 @@ int TtkWidgetIdentifyCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { WidgetCore *corePtr = recordPtr; Ttk_Element element; - static const char *whatTable[] = { "element", NULL }; + static const char *const whatTable[] = { "element", NULL }; int x, y, what; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 2, objv, "?what? x y"); return TCL_ERROR; Index: generic/ttk/ttkWidget.h ================================================================== --- generic/ttk/ttkWidget.h +++ generic/ttk/ttkWidget.h @@ -109,20 +109,20 @@ Tcl_CreateObjCommand(interp, name, \ TtkWidgetConstructorObjCmd, (ClientData)specPtr,NULL) /* WIDGET_TAKEFOCUS_TRUE -- * WIDGET_TAKEFOCUS_FALSE -- - * Add one or the other of these to each OptionSpecs table - * to indicate whether the widget should take focus + * Add one or the other of these to each OptionSpecs table + * to indicate whether the widget should take focus * during keyboard traversal. */ #define WIDGET_TAKEFOCUS_TRUE \ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \ - "ttk::takefocus", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 } + "ttk::takefocus", offsetof(WidgetCore, takeFocusPtr), -1, 0,0,0 } #define WIDGET_TAKEFOCUS_FALSE \ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \ - "", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 } + "", offsetof(WidgetCore, takeFocusPtr), -1, 0,0,0 } /* WIDGET_INHERIT_OPTIONS(baseOptionSpecs) -- * Add this at the end of an OptionSpecs table to inherit * the options from 'baseOptionSpecs'. */ @@ -193,11 +193,12 @@ MODULE_SCOPE void TtkFreeScrollHandle(ScrollHandle); MODULE_SCOPE int TtkScrollviewCommand( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle); -MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst); +MODULE_SCOPE void TtkUpdateScrollInfo(ScrollHandle h); +MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst, int updateScrollInfo); MODULE_SCOPE void TtkScrolled(ScrollHandle, int first, int last, int total); MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle); /* * Tag sets (work in progress, half-baked) Index: library/bgerror.tcl ================================================================== --- library/bgerror.tcl +++ library/bgerror.tcl @@ -95,28 +95,33 @@ # to see a stack trace. # # Arguments: # err - The error message. # -proc ::tk::dialog::error::bgerror err { +proc ::tk::dialog::error::bgerror {err {flag 1}} { global errorInfo variable button set info $errorInfo set ret [catch {::tkerror $err} msg]; if {$ret != 1} {return -code $ret $msg} - # Ok the application's tkerror either failed or was not found - # we use the default dialog then : + # The application's tkerror either failed or was not found + # so we use the default dialog. But on Aqua we cannot display + # the dialog if the background error occurs in an idle task + # being processed inside of [NSView drawRect]. In that case + # we post the dialog as an after task instead. set windowingsystem [tk windowingsystem] if {$windowingsystem eq "aqua"} { - set ok [mc Ok] - } else { - set ok [mc OK] + if $flag { + after 500 [list bgerror "$err" 0] + return + } } + set ok [mc OK] # Truncate the message if it is too wide (>maxLine characters) or # too tall (>4 lines). Truncation occurs at the first point at # which one of those conditions is met. set displayedErr "" set lines 0 Index: library/button.tcl ================================================================== --- library/button.tcl +++ library/button.tcl @@ -746,15 +746,19 @@ variable ::tk::Priv if {[$w cget -state] ne "disabled"} { $w configure -state normal } - # Restore the original button "selected" color; assume that the user - # wasn't monkeying around with things too much. + # Restore the original button "selected" color; but only if the user + # has not changed it in the meantime. if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} { - $w configure -selectcolor $Priv($w,selectcolor) + if {[$w cget -selectcolor] eq $Priv($w,selectcolor) + || ([info exist Priv($w,aselectcolor)] && + [$w cget -selectcolor] eq $Priv($w,aselectcolor))} { + $w configure -selectcolor $Priv($w,selectcolor) + } } unset -nocomplain Priv($w,selectcolor) Priv($w,aselectcolor) # Restore the original button relief if it was changed by Tk. That is # signaled by the existence of Priv($w,prelief). Index: library/demos/combo.tcl ================================================================== --- library/demos/combo.tcl +++ library/demos/combo.tcl @@ -41,11 +41,12 @@ } set secondValue unchangable set ozCity Sydney ttk::labelframe $w.c1 -text "Fully Editable" -ttk::combobox $w.c1.c -textvariable firstValue +ttk::combobox $w.c1.c -textvariable firstValue -placeholder {Enter text here} +ttk::style configure TEntry -placeholderforeground gray50 ttk::labelframe $w.c2 -text Disabled ttk::combobox $w.c2.c -textvariable secondValue -state disabled ttk::labelframe $w.c3 -text "Defined List Only" ttk::combobox $w.c3.c -textvariable ozCity -state readonly \ -values $australianCities Index: library/demos/ctext.tcl ================================================================== --- library/demos/ctext.tcl +++ library/demos/ctext.tcl @@ -38,11 +38,11 @@ $c create rectangle 245 195 255 205 -outline black -fill red # First, create the text item and give it bindings so it can be edited. -$c addtag text withtag [$c create text 250 200 -text "This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been been defined to support editing (see above)." -width 440 -anchor n -font $textFont -justify left] +$c addtag text withtag [$c create text 250 200 -text "This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been defined to support editing (see above)." -width 440 -anchor n -font $textFont -justify left] $c bind text <1> "textB1Press $c %x %y" $c bind text "textB1Move $c %x %y" $c bind text "$c select adjust current @%x,%y" $c bind text "textB1Move $c %x %y" $c bind text "textInsert $c %A" Index: library/demos/entry1.tcl ================================================================== --- library/demos/entry1.tcl +++ library/demos/entry1.tcl @@ -23,11 +23,11 @@ set btns [addSeeDismiss $w.buttons $w] pack $btns -side bottom -fill x entry $w.e1 entry $w.e2 -entry $w.e3 +entry $w.e3 -placeholder {Enter text here} -placeholderforeground gray75 pack $w.e1 $w.e2 $w.e3 -side top -pady 5 -padx 10 -fill x $w.e1 insert 0 "Initial value" $w.e2 insert end "This entry contains a long value, much too long " $w.e2 insert end "to fit in the window at one time, so long in fact " Index: library/demos/entry2.tcl ================================================================== --- library/demos/entry2.tcl +++ library/demos/entry2.tcl @@ -42,5 +42,6 @@ $w.frame.e1 insert 0 "Initial value" $w.frame.e2 insert end "This entry contains a long value, much too long " $w.frame.e2 insert end "to fit in the window at one time, so long in fact " $w.frame.e2 insert end "that you'll have to scan or scroll to see the end." +$w.frame.e3 configure -placeholder {Enter text here} -placeholderforeground gray75 Index: library/demos/menu.tcl ================================================================== --- library/demos/menu.tcl +++ library/demos/menu.tcl @@ -129,19 +129,26 @@ $m entryconfigure 2 -columnbreak 1 set m $w.menu.more $w.menu add cascade -label "More" -menu $m -underline 0 menu $m -tearoff 0 -foreach i {{An entry} {Another entry} {Does nothing} {Does almost nothing} {Make life meaningful}} { +foreach i {{An entry} {Another entry} {Does nothing} {Does almost nothing} {Does almost nothing also} {Make life meaningful}} { $m add command -label $i -command [list puts "You invoked \"$i\""] } $m entryconfigure "Does almost nothing" -bitmap questhead -compound left \ -command [list \ tk_dialog $w.compound {Compound Menu Entry} \ "The menu entry you invoked displays both a bitmap and a\ text string. Other than this, it is just like any other\ menu entry." {} 0 OK ] + +$m entryconfigure "Does almost nothing also" -image lilearth -compound left \ + -command [list \ + tk_dialog $w.compound {Compound Menu Entry} \ + "The menu entry you invoked displays both a image and a\ + text string. Other than this, it is just like any other\ + menu entry." {} 0 OK ] set m $w.menu.colors $w.menu add cascade -label "Colors" -menu $m -underline 1 menu $m -tearoff 1 foreach i {red orange yellow green blue} { Index: library/demos/pendulum.tcl ================================================================== --- library/demos/pendulum.tcl +++ library/demos/pendulum.tcl @@ -124,20 +124,20 @@ showPendulum %W at %x %y set animationCallbacks(pendulum) [after 15 repeat [winfo toplevel %W]] } bind $w.c { %W coords plate 0 25 %w 25 - set home [expr %w/2] - %W coords pivot [expr $home-5] 20 [expr $home+5] 30 + set home [expr {%w/2}] + %W coords pivot [expr {$home-5}] 20 [expr {$home+5}] 30 } bind $w.k { - set psh [expr %h/2] - set psw [expr %w/2] - %W coords x_axis 2 $psh [expr %w-2] $psh - %W coords y_axis $psw [expr %h-2] $psw 2 - %W coords label_dtheta [expr $psw-4] 6 - %W coords label_theta [expr %w-6] [expr $psh+4] + set psh [expr {%h/2}] + set psw [expr {%w/2}] + %W coords x_axis 2 $psh [expr {%w-2}] $psh + %W coords y_axis $psw [expr {%h-2}] $psw 2 + %W coords label_dtheta [expr {$psw-4}] 6 + %W coords label_theta [expr {%w-6}] [expr {$psh+4}] } # This procedure is the "business" part of the simulation that does # simple numerical integration of the formula for a simple rotational # pendulum. Index: library/demos/puzzle.tcl ================================================================== --- library/demos/puzzle.tcl +++ library/demos/puzzle.tcl @@ -71,11 +71,11 @@ set order {3 1 6 2 5 7 15 13 4 11 8 9 14 10 12} for {set i 0} {$i < 15} {set i [expr {$i+1}]} { set num [lindex $order $i] set xpos($num) [expr {($i%4)*.25}] set ypos($num) [expr {($i/4)*.25}] - button $w.frame.$num -relief raised -text $num -highlightthickness 0 \ + button $w.frame.$num -relief raised -text $num -bd 0 -highlightthickness 0 \ -command "puzzleSwitch $w $num" place $w.frame.$num -relx $xpos($num) -rely $ypos($num) \ -relwidth .25 -relheight .25 } set xpos(space) .75 Index: library/demos/square ================================================================== --- library/demos/square +++ library/demos/square @@ -25,11 +25,11 @@ # The procedure below centers the square on a given position. proc center {x y} { set a [.s size] - .s position [expr $x-($a/2)] [expr $y-($a/2)] + .s position [expr {$x-($a/2)}] [expr {$y-($a/2)}] } # The procedures below provide a simple form of animation where # the box changes size in a pulsing pattern: larger, smaller, larger, # and so on. Index: library/demos/toolbar.tcl ================================================================== --- library/demos/toolbar.tcl +++ library/demos/toolbar.tcl @@ -29,11 +29,11 @@ set t [frame $w.toolbar] ;# Must be a frame! ttk::separator $w.sep ttk::frame $t.tearoff -cursor fleur ttk::separator $t.tearoff.to -orient vertical ttk::separator $t.tearoff.to2 -orient vertical -pack $t.tearoff.to -fill y -expand 1 -padx 2 -side left +pack $t.tearoff.to -fill y -expand 1 -padx 4 -side left pack $t.tearoff.to2 -fill y -expand 1 -side left ttk::frame $t.contents grid $t.tearoff $t.contents -sticky nsew grid columnconfigure $t $t.contents -weight 1 grid columnconfigure $t.contents 1000 -weight 1 @@ -77,11 +77,11 @@ ## Some content for the rest of the toplevel text $w.txt -width 40 -height 10 interp alias {} doInsert {} $w.txt insert end ;# Make bindings easy to write ## Arrange contents -grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -sticky ns +grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -pady 4 -sticky ns grid $t -sticky ew grid $w.sep -sticky ew grid $w.msg -sticky ew grid $w.txt -sticky nsew grid rowconfigure $w $w.txt -weight 1 Index: library/demos/tree.tcl ================================================================== --- library/demos/tree.tcl +++ library/demos/tree.tcl @@ -37,10 +37,11 @@ return } set path [$tree set $node fullpath] $tree delete [$tree children $node] foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] { + set f [file normalize $f] set type [file type $f] set id [$tree insert $node end -text [file tail $f] \ -values [list $f $type]] if {$type eq "directory"} { @@ -73,11 +74,11 @@ -yscroll "$w.vsb set" -xscroll "$w.hsb set" ttk::scrollbar $w.vsb -orient vertical -command "$w.tree yview" ttk::scrollbar $w.hsb -orient horizontal -command "$w.tree xview" $w.tree heading \#0 -text "Directory Structure" $w.tree heading size -text "File Size" -$w.tree column size -stretch 0 -width 70 +$w.tree column size -width 70 populateRoots $w.tree bind $w.tree <> {populateTree %W [%W focus]} ## Arrange the tree and its scrollbars in the toplevel lower [ttk::frame $w.dummy] Index: library/demos/ttkpane.tcl ================================================================== --- library/demos/ttkpane.tcl +++ library/demos/ttkpane.tcl @@ -102,11 +102,11 @@ pack $w.sb -side right -fill y -in $w.outer.inRight.bot pack $w.outer.inRight.bot.f -fill both -expand 1 pack $w.outer -fill both -expand 1 } else { text $w.txt -wrap word -yscroll "$w.sb set" -width 30 -borderwidth 0 - scrollbar $w.sb -orient vertical -command "$w.txt yview" + ttk::scrollbar $w.sb -orient vertical -command "$w.txt yview" pack $w.sb -side right -fill y -in $w.outer.inRight.bot pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot pack $w.outer -fill both -expand 1 -padx 10 -pady {6 10} } Index: library/demos/twind.tcl ================================================================== --- library/demos/twind.tcl +++ library/demos/twind.tcl @@ -6,10 +6,18 @@ if {![info exists widgetDemo]} { error "This script should be run from the \"widget\" demo." } package require Tk + +# Make an Aqua button's fill color match its parent's background +proc blend {bt} { + if {[tk windowingsystem] eq "aqua"} { + $bt configure -highlightbackground [[winfo parent $bt] cget -background] + } + return $bt +} set w .twind catch {destroy $w} toplevel $w wm title $w "Text Demonstration - Embedded Windows and Other Features" @@ -51,38 +59,42 @@ $t insert end "A text widget can contain other widgets embedded " $t insert end "it. These are called \"embedded windows\", " $t insert end "and they can consist of arbitrary widgets. " $t insert end "For example, here are two embedded button " $t insert end "widgets. You can click on the first button to " -$t window create end -window $t.on +$t window create end -window [blend $t.on] $t insert end " horizontal scrolling, which also turns off " $t insert end "word wrapping. Or, you can click on the second " $t insert end "button to\n" -$t window create end -window $t.off +$t window create end -window [blend $t.off] $t insert end " horizontal scrolling and turn back on word wrapping.\n\n" $t insert end "Or, here is another example. If you " $t window create end -create { button %W.click -text "Click Here" -command "textWindPlot %W" \ - -cursor top_left_arrow} + -cursor top_left_arrow + blend %W.click +} $t insert end " a canvas displaying an x-y plot will appear right here." $t mark set plot insert $t mark gravity plot left $t insert end " You can drag the data points around with the mouse, " $t insert end "or you can click here to " $t window create end -create { button %W.delete -text "Delete" -command "textWindDel %W" \ - -cursor top_left_arrow + -cursor top_left_arrow + blend %W.delete } $t insert end " the plot again.\n\n" $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 + -cursor top_left_arrow + blend %W.peer} -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 " @@ -90,11 +102,12 @@ $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 + -cursor top_left_arrow + blend %W.split} -padx 3 $t insert end " \n\n" $t insert end "Users of previous versions of Tk will also be interested " $t insert end "to note that now cursor movement is now by visual line by " $t insert end "default, and that all scrolling of this widget is by pixel.\n\n" @@ -126,15 +139,15 @@ foreach color {AntiqueWhite3 Bisque1 Bisque2 Bisque3 Bisque4 SlateBlue3 RoyalBlue1 SteelBlue2 DeepSkyBlue3 LightBlue1 DarkSlateGray1 Aquamarine2 DarkSeaGreen2 SeaGreen1 Yellow1 IndianRed1 IndianRed2 Tan1 Tan4} { button $t.color$i -text $color -cursor top_left_arrow -command \ - "$t configure -bg $color" - $t window create end -window $t.color$i -padx 3 -pady 2 + "changeBg $t $color" + $t window create end -window [blend $t.color$i] -padx 3 -pady 2 incr i } -$t tag add buttons $t.default end +$t tag add buttons [blend $t.default] end button $t.bigB -text "Big borders" -command "textWindBigB $t" \ -cursor top_left_arrow button $t.smallB -text "Small borders" -command "textWindSmallB $t" \ -cursor top_left_arrow @@ -151,16 +164,16 @@ set text_normal(highlight) [$t cget -highlightthickness] set text_normal(pad) [$t cget -padx] $t insert end "\nYou can also change the usual border width and " $t insert end "highlightthickness and padding.\n" -$t window create end -window $t.bigB -$t window create end -window $t.smallB -$t window create end -window $t.bigH -$t window create end -window $t.smallH -$t window create end -window $t.bigP -$t window create end -window $t.smallP +$t window create end -window [blend $t.bigB] +$t window create end -window [blend $t.smallB] +$t window create end -window [blend $t.bigH] +$t window create end -window [blend $t.smallH] +$t window create end -window [blend $t.bigP] +$t window create end -window [blend $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]] @@ -186,11 +199,10 @@ } proc textWindSmallP w { $w configure -padx $::text_normal(pad) -pady $::text_normal(pad) } - proc textWindOn w { catch {destroy $w.scroll2} set t $w.f.text ttk::scrollbar $w.scroll2 -orient horizontal -command "$t xview" @@ -287,13 +299,25 @@ $t delete plot } $t insert plot " " } } + +proc changeBg {t c} { + $t configure -background $c + if {[tk windowingsystem] eq "aqua"} { + foreach b [$t window names] { + if {[winfo class $b] eq "Button"} { + $b configure -highlightbackground $c + } + } + } +} proc embDefBg t { - $t configure -background [lindex [$t configure -background] 3] + set bg [lindex [$t configure -background] 3] + changeBg $t $bg } proc textMakePeer {parent} { set n 1 while {[winfo exists .peer$n]} { incr n } Index: library/demos/unicodeout.tcl ================================================================== --- library/demos/unicodeout.tcl +++ library/demos/unicodeout.tcl @@ -20,12 +20,12 @@ -text "This is a sample of Tk's support for languages that use\ non-Western character sets. However, what you will actually see\ below depends largely on what character sets you have installed,\ and what you see for characters that are not present varies greatly\ between platforms as well. The strings are written in Tcl using\ - UNICODE characters using the \\uXXXX escape so as to do so in a\ - portable fashion." + UNICODE characters using the \\uXXXX (or \\UXXXXXX) escape so as to\ + do so in a portable fashion." pack $w.msg -side top ## See Code / Dismiss buttons set btns [addSeeDismiss $w.buttons $w] pack $btns -side bottom -fill x @@ -129,9 +129,11 @@ "\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, " \ "\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA" addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00" addSample $w Russian \ "\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A" +addSample $w Emoji \ + "\U1F600\U1F4A9\U1F44D\U1F1F3\U1F1F1" ## We're done processing, so change things back to normal running... destroy $w.wait $w conf -cursor $oldCursor Index: library/entry.tcl ================================================================== --- library/entry.tcl +++ library/entry.tcl @@ -72,10 +72,15 @@ %W icursor end } # Standard Motif bindings: +bind Entry { + if {[tk windowingsystem] eq "aqua"} { + ::tk::RegisterServiceWidget %W + } +} bind Entry <1> { tk::EntryButton1 %W %x %W selection clear } bind Entry { @@ -650,5 +655,14 @@ return [string repeat [string index [$w cget -show] 0] \ [string length $entryString]] } return $entryString } + + + + + + + + + Index: library/images/logo.eps ================================================================== --- library/images/logo.eps +++ library/images/logo.eps @@ -26,11 +26,11 @@ %AI5_OpenViewLayers: 7 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.0 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) -%%Version: 1.0 +%%Version: 1.0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 21 dict dup begin put /packedarray where not @@ -75,11 +75,11 @@ 5 -1 roll pop setcmykcolor } def } if - + /gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { @@ -176,11 +176,11 @@ } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog) -%%Version: 1.1 +%%Version: 1.1 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin put @@ -1060,11 +1060,11 @@ { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def - + /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } @@ -1087,11 +1087,11 @@ { currentdict end end begin - + /clipForward? false ddef } if } ifelse } bind def /Pb Index: library/images/pwrdLogo.eps ================================================================== --- library/images/pwrdLogo.eps +++ library/images/pwrdLogo.eps @@ -26,11 +26,11 @@ %AI5_OpenViewLayers: 7 %%EndComments %%BeginProlog %%BeginResource: procset Adobe_level2_AI5 1.0 0 %%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation) -%%Version: 1.0 +%%Version: 1.0 %%CreationDate: (04/10/93) () %%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved) userdict /Adobe_level2_AI5 21 dict dup begin put /packedarray where not @@ -75,11 +75,11 @@ 5 -1 roll pop setcmykcolor } def } if - + /gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put userdict /level2? systemdict /languagelevel known dup { @@ -176,11 +176,11 @@ } if end defaultpacking setpacking %%EndResource %%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0 %%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog) -%%Version: 1.1 +%%Version: 1.1 %%CreationDate: (3/7/1994) () %%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved) currentpacking true setpacking userdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin put @@ -1060,11 +1060,11 @@ { (%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard } { /clipForward? true def - + /Tx /pop load def /Tj /pop load def currentdict end clipRenderOff begin begin } ifelse } @@ -1087,11 +1087,11 @@ { currentdict end end begin - + /clipForward? false ddef } if } ifelse } bind def /Pb Index: library/menu.tcl ================================================================== --- library/menu.tcl +++ library/menu.tcl @@ -231,10 +231,11 @@ } if {[$w cget -state] eq "active" && [tk windowingsystem] ne "aqua"} { $w configure -state normal } } + # ::tk::MbPost -- # Given a menubutton, this procedure does all the work of posting # its associated menu and unposting any other menu that is currently # posted. @@ -280,105 +281,21 @@ set Priv(postedMb) $w set Priv(focus) [focus] $menu activate none GenerateMenuSelect $menu - - # If this looks like an option menubutton then post the menu so - # that the current entry is on top of the mouse. Otherwise post - # the menu just below the menubutton, as for a pull-down. - update idletasks - if {[catch { - switch [$w cget -direction] { - above { - set x [winfo rootx $w] - set y [expr {[winfo rooty $w] - [winfo reqheight $menu]}] - # if we go offscreen to the top, show as 'below' - if {$y < [winfo vrooty $w]} { - set y [expr {[winfo vrooty $w] + [winfo rooty $w] + [winfo reqheight $w]}] - } - PostOverPoint $menu $x $y - } - below { - set x [winfo rootx $w] - set y [expr {[winfo rooty $w] + [winfo height $w]}] - # if we go offscreen to the bottom, show as 'above' - set mh [winfo reqheight $menu] - if {($y + $mh) > ([winfo vrooty $w] + [winfo vrootheight $w])} { - set y [expr {[winfo vrooty $w] + [winfo vrootheight $w] + [winfo rooty $w] - $mh}] - } - PostOverPoint $menu $x $y - } - left { - set x [expr {[winfo rootx $w] - [winfo reqwidth $menu]}] - set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}] - set entry [MenuFindName $menu [$w cget -text]] - if {$entry eq ""} { - set entry 0 - } - if {[$w cget -indicatoron]} { - if {$entry == [$menu index last]} { - incr y [expr {-([$menu yposition $entry] \ - + [winfo reqheight $menu])/2}] - } else { - incr y [expr {-([$menu yposition $entry] \ - + [$menu yposition [expr {$entry+1}]])/2}] - } - } - PostOverPoint $menu $x $y - if {$entry ne "" \ - && [$menu entrycget $entry -state] ne "disabled"} { - $menu activate $entry - GenerateMenuSelect $menu - } - } - right { - set x [expr {[winfo rootx $w] + [winfo width $w]}] - set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}] - set entry [MenuFindName $menu [$w cget -text]] - if {$entry eq ""} { - set entry 0 - } - if {[$w cget -indicatoron]} { - if {$entry == [$menu index last]} { - incr y [expr {-([$menu yposition $entry] \ - + [winfo reqheight $menu])/2}] - } else { - incr y [expr {-([$menu yposition $entry] \ - + [$menu yposition [expr {$entry+1}]])/2}] - } - } - PostOverPoint $menu $x $y - if {$entry ne "" \ - && [$menu entrycget $entry -state] ne "disabled"} { - $menu activate $entry - GenerateMenuSelect $menu - } - } - default { - if {[$w cget -indicatoron]} { - if {$y eq ""} { - set x [expr {[winfo rootx $w] + [winfo width $w]/2}] - set y [expr {[winfo rooty $w] + [winfo height $w]/2}] - } - PostOverPoint $menu $x $y [MenuFindName $menu [$w cget -text]] - } else { - PostOverPoint $menu [winfo rootx $w] [expr {[winfo rooty $w]+[winfo height $w]}] - } - } - } - } msg opt]} { + + if {[catch {PostMenubuttonMenu $w $menu} msg opt]} { # Error posting menu (e.g. bogus -postcommand). Unpost it and # reflect the error. - MenuUnpost {} return -options $opt $msg } set Priv(tearoff) $tearoff - if {$tearoff != 0} { + if {$tearoff != 0 && [tk windowingsystem] ne "aqua"} { focus $menu if {[winfo viewable $w]} { SaveGrabInfo $w grab -global $w } @@ -574,15 +491,17 @@ && $index ne $activeindex} { set mode [option get $menu clickToFocus ClickToFocus] if {[string is false $mode]} { set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}] if {[$menu type $index] eq "cascade"} { + # Catch these postcascade commands since the menu could be + # destroyed before they run. set Priv(menuActivatedTimer) \ - [after $delay [list $menu postcascade active]] + [after $delay "catch {$menu postcascade active}"] } else { set Priv(menuDeactivatedTimer) \ - [after $delay [list $menu postcascade none]] + [after $delay "catch {$menu postcascade none}"] } } } } } @@ -1205,36 +1124,140 @@ } } } return "" } + +# ::tk::PostMenubuttonMenu -- +# +# Given a menubutton and a menu, this procedure posts the menu at the +# appropriate location. If the menubutton looks like an option +# menubutton, meaning that the indicator is on and the direction is +# neither above nor below, then the menu is posted so that the current +# entry is vertically aligned with the menubutton. On the Mac this +# will expose a small amount of the blue indicator on the right hand +# side. On other platforms the entry is centered over the button. + +if {[tk windowingsystem] eq "aqua"} { + proc ::tk::PostMenubuttonMenu {button menu} { + set entry "" + if {[$button cget -indicatoron]} { + set entry [MenuFindName $menu [$button cget -text]] + if {$entry eq ""} { + set entry 0 + } + } + set x [winfo rootx $button] + set y [expr {2 + [winfo rooty $button]}] + switch [$button cget -direction] { + above { + set entry "" + incr y [expr {4 - [winfo reqheight $menu]}] + } + below { + set entry "" + incr y [expr {2 + [winfo height $button]}] + } + left { + incr x [expr {-[winfo reqwidth $menu]}] + } + right { + incr x [winfo width $button] + } + default { + incr x [expr {[winfo width $button] - [winfo reqwidth $menu] - 5}] + } + } + PostOverPoint $menu $x $y $entry + } +} else { + proc ::tk::PostMenubuttonMenu {button menu} { + set entry "" + if {[$button cget -indicatoron]} { + set entry [MenuFindName $menu [$button cget -text]] + if {$entry eq ""} { + set entry 0 + } + } + set x [winfo rootx $button] + set y [winfo rooty $button] + switch [$button cget -direction] { + above { + incr y [expr {-[winfo reqheight $menu]}] + # if we go offscreen to the top, show as 'below' + if {$y < [winfo vrooty $button]} { + set y [expr {[winfo vrooty $button] + [winfo rooty $button]\ + + [winfo reqheight $button]}] + } + set entry {} + } + below { + incr y [winfo height $button] + # if we go offscreen to the bottom, show as 'above' + set mh [winfo reqheight $menu] + if {($y + $mh) > ([winfo vrooty $button] + [winfo vrootheight $button])} { + set y [expr {[winfo vrooty $button] + [winfo vrootheight $button] \ + + [winfo rooty $button] - $mh}] + } + set entry {} + } + left { + # It is not clear why this is needed. + if {[tk windowingsystem] eq "win32"} { + incr x [expr {-4 - [winfo reqwidth $button] / 2}] + } + incr x [expr {- [winfo reqwidth $menu]}] + } + right { + incr x [expr {[winfo width $button]}] + } + default { + if {[$button cget -indicatoron]} { + incr x [expr {([winfo width $button] - \ + [winfo reqwidth $menu])/ 2}] + } else { + incr y [winfo height $button] + } + } + } + PostOverPoint $menu $x $y $entry + } +} # ::tk::PostOverPoint -- -# This procedure posts a given menu such that a given entry in the -# menu is centered over a given point in the root window. It also -# activates the given entry. +# +# This procedure posts a menu on the screen so that a given entry in +# the menu is positioned with its upper left corner at a given point +# in the root window. The procedure also activates that entry. If no +# entry is specified the upper left corner of the entire menu is +# placed at the point. # # Arguments: # menu - Menu to post. # x, y - Root coordinates of point. # entry - Index of entry within menu to center over (x,y). # If omitted or specified as {}, then the menu's # upper-left corner goes at (x,y). -proc ::tk::PostOverPoint {menu x y {entry {}}} { - if {$entry ne ""} { - if {$entry == [$menu index last]} { - incr y [expr {-([$menu yposition $entry] \ - + [winfo reqheight $menu])/2}] +if {[tk windowingsystem] ne "win32"} { + proc ::tk::PostOverPoint {menu x y {entry {}}} { + if {$entry ne ""} { + $menu post $x $y $entry + if {[$menu entrycget $entry -state] ne "disabled"} { + $menu activate $entry + GenerateMenuSelect $menu + } } else { - incr y [expr {-([$menu yposition $entry] \ - + [$menu yposition [expr {$entry+1}]])/2}] + $menu post $x $y } - incr x [expr {-[winfo reqwidth $menu]/2}] + return } - - if {[tk windowingsystem] eq "win32"} { +} else { + proc ::tk::PostOverPoint {menu x y {entry {}}} { + if {$entry ne ""} { + incr y [expr {-[$menu yposition $entry]}] + } # osVersion is not available in safe interps set ver 5 if {[info exists ::tcl_platform(osVersion)]} { scan $::tcl_platform(osVersion) %d ver } @@ -1246,11 +1269,11 @@ # entry. To be safe we subtract an extra 10. # NOTE: this issue appears to have been resolved in the Window # manager provided with Vista and Windows 7. if {$ver < 6} { set yoffset [expr {[winfo screenheight $menu] \ - - $y - [winfo reqheight $menu] - 10}] + - $y - [winfo reqheight $menu] - 10}] if {$yoffset < [winfo vrooty $menu]} { # The bottom of the menu is offscreen, so adjust upwards incr y [expr {$yoffset - [winfo vrooty $menu]}] } # If we're off the top of the screen (either because we were @@ -1258,15 +1281,15 @@ # then make the menu popup on the top edge. if {$y < [winfo vrooty $menu]} { set y [winfo vrooty $menu] } } - } - $menu post $x $y - if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} { - $menu activate $entry - GenerateMenuSelect $menu + $menu post $x $y + if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} { + $menu activate $entry + GenerateMenuSelect $menu + } } } # ::tk::SaveGrabInfo -- # Sets the variables tk::Priv(oldGrab) and tk::Priv(grabStatus) to record Index: library/msgs/cs.msg ================================================================== --- library/msgs/cs.msg +++ library/msgs/cs.msg @@ -1,77 +1,77 @@ namespace eval ::tk { - ::msgcat::mcset cs "&Abort" "&P\u0159eru\u0161it" + ::msgcat::mcset cs "&Abort" "&Přerušit" ::msgcat::mcset cs "&About..." "&O programu..." - ::msgcat::mcset cs "All Files" "V\u0161echny soubory" + ::msgcat::mcset cs "All Files" "Všechny soubory" ::msgcat::mcset cs "Application Error" "Chyba programu" ::msgcat::mcset cs "Bold Italic" - ::msgcat::mcset cs "&Blue" "&Modr\341" - ::msgcat::mcset cs "Cancel" "Zru\u0161it" - ::msgcat::mcset cs "&Cancel" "&Zru\u0161it" - ::msgcat::mcset cs "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nemohu zm\u011bnit atku\341ln\355 adres\341\u0159 na \"%1\$s\".\nP\u0159\355stup odm\355tnut." - ::msgcat::mcset cs "Choose Directory" "V\375b\u011br adres\341\u0159e" + ::msgcat::mcset cs "&Blue" "&Modá" + ::msgcat::mcset cs "Cancel" "Zrušit" + ::msgcat::mcset cs "&Cancel" "&Zrušit" + ::msgcat::mcset cs "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nemohu změnit atkálí adreář na \"%1\$s\".\nPístup odítnut." + ::msgcat::mcset cs "Choose Directory" "ýběr adreáře" ::msgcat::mcset cs "Cl&ear" "Sma&zat" ::msgcat::mcset cs "&Clear Console" "&Smazat konzolu" ::msgcat::mcset cs "Color" "Barva" ::msgcat::mcset cs "Console" "Konzole" - ::msgcat::mcset cs "&Copy" "&Kop\355rovat" - ::msgcat::mcset cs "Cu&t" "V&y\u0159\355znout" + ::msgcat::mcset cs "&Copy" "&Koírovat" + ::msgcat::mcset cs "Cu&t" "V&yíznout" ::msgcat::mcset cs "&Delete" "&Smazat" ::msgcat::mcset cs "Details >>" "Detaily >>" - ::msgcat::mcset cs "Directory \"%1\$s\" does not exist." "Adres\341\u0159 \"%1\$s\" neexistuje." - ::msgcat::mcset cs "&Directory:" "&Adres\341\u0159:" - ::msgcat::mcset cs "&Edit" "&\332pravy" + ::msgcat::mcset cs "Directory \"%1\$s\" does not exist." "Adreář \"%1\$s\" neexistuje." + ::msgcat::mcset cs "&Directory:" "&Adreář:" + ::msgcat::mcset cs "&Edit" "Úpravy" ::msgcat::mcset cs "Error: %1\$s" "Chyba: %1\$s" ::msgcat::mcset cs "E&xit" "&Konec" ::msgcat::mcset cs "&File" "&Soubor" - ::msgcat::mcset cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Soubor \"%1\$s\" ji\u017e existuje.\nChcete jej p\u0159epsat?" - ::msgcat::mcset cs "File \"%1\$s\" already exists.\n\n" "Soubor \"%1\$s\" ji\u017e existuje.\n\n" + ::msgcat::mcset cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Soubor \"%1\$s\" již existuje.\nChcete jej přepsat?" + ::msgcat::mcset cs "File \"%1\$s\" already exists.\n\n" "Soubor \"%1\$s\" již existuje.\n\n" ::msgcat::mcset cs "File \"%1\$s\" does not exist." "Soubor \"%1\$s\" neexistuje." - ::msgcat::mcset cs "File &name:" "&Jm\351no souboru:" - ::msgcat::mcset cs "File &names:" "&Jm\351na soubor\u016f:" - ::msgcat::mcset cs "Files of &type:" "&Typy soubor\u016f:" + ::msgcat::mcset cs "File &name:" "&Jéno souboru:" + ::msgcat::mcset cs "File &names:" "&Jéna souborů:" + ::msgcat::mcset cs "Files of &type:" "&Typy souborů:" ::msgcat::mcset cs "Fi&les:" "Sou&bory:" ::msgcat::mcset cs "&Filter" "&Filtr" ::msgcat::mcset cs "Fil&ter:" "Fil&tr:" ::msgcat::mcset cs "Font st&yle:" - ::msgcat::mcset cs "&Green" "Ze&len\341" - ::msgcat::mcset cs "&Help" "&N\341pov\u011bda" + ::msgcat::mcset cs "&Green" "Ze&leá" + ::msgcat::mcset cs "&Help" "&ápověda" ::msgcat::mcset cs "Hi" "Ahoj" ::msgcat::mcset cs "&Hide Console" "&Schovat Konzolu" ::msgcat::mcset cs "&Ignore" "&Ignorovat" - ::msgcat::mcset cs "Invalid file name \"%1\$s\"." "\u0160patn\351 jm\351no souboru \"%1\$s\"." + ::msgcat::mcset cs "Invalid file name \"%1\$s\"." "Špaté jéno souboru \"%1\$s\"." ::msgcat::mcset cs "Log Files" "Log soubory" ::msgcat::mcset cs "&No" "&Ne" ::msgcat::mcset cs "&OK" ::msgcat::mcset cs "OK" ::msgcat::mcset cs "Ok" - ::msgcat::mcset cs "Open" "Otev\u0159\355t" - ::msgcat::mcset cs "&Open" "&Otev\u0159\355t" - ::msgcat::mcset cs "Open Multiple Files" "Otev\u0159\355t v\355ce soubor\u016f" - ::msgcat::mcset cs "P&aste" "&Vlo\u017eit" - ::msgcat::mcset cs "&Quit" "&Ukon\u010dit" - ::msgcat::mcset cs "&Red" "\u010ce&rven\341" - ::msgcat::mcset cs "Replace existing file?" "Nahradit st\341vaj\355c\355 soubor?" + ::msgcat::mcset cs "Open" "Otevít" + ::msgcat::mcset cs "&Open" "&Otevít" + ::msgcat::mcset cs "Open Multiple Files" "Otevít íce souborů" + ::msgcat::mcset cs "P&aste" "&Vložit" + ::msgcat::mcset cs "&Quit" "&Ukončit" + ::msgcat::mcset cs "&Red" "Če&rveá" + ::msgcat::mcset cs "Replace existing file?" "Nahradit sávaíí soubor?" ::msgcat::mcset cs "&Retry" "Z&novu" - ::msgcat::mcset cs "&Save" "&Ulo\u017eit" - ::msgcat::mcset cs "Save As" "Ulo\u017eit jako" - ::msgcat::mcset cs "Save To Log" "Ulo\u017eit do logu" + ::msgcat::mcset cs "&Save" "&Uložit" + ::msgcat::mcset cs "Save As" "Uložit jako" + ::msgcat::mcset cs "Save To Log" "Uložit do logu" ::msgcat::mcset cs "Select Log File" "Vybrat log soubor" - ::msgcat::mcset cs "Select a file to source" "Vybrat soubor k nahr\341n\355" - ::msgcat::mcset cs "&Selection:" "&V\375b\u011br:" - ::msgcat::mcset cs "Skip Messages" "P\u0159esko\u010dit zpr\341vy" + ::msgcat::mcset cs "Select a file to source" "Vybrat soubor k naháí" + ::msgcat::mcset cs "&Selection:" "&ýběr:" + ::msgcat::mcset cs "Skip Messages" "Přeskočit zpávy" ::msgcat::mcset cs "&Source..." "&Zdroj..." ::msgcat::mcset cs "Tcl Scripts" "Tcl skripty" ::msgcat::mcset cs "Tcl for Windows" "Tcl pro Windows" - ::msgcat::mcset cs "Text Files" "Textov\351 soubory" - ::msgcat::mcset cs "abort" "p\u0159eru\u0161it" - ::msgcat::mcset cs "blue" "modr\341" - ::msgcat::mcset cs "cancel" "zru\u0161it" - ::msgcat::mcset cs "extension" "p\u0159\355pona" - ::msgcat::mcset cs "extensions" "p\u0159\355pony" - ::msgcat::mcset cs "green" "zelen\341" + ::msgcat::mcset cs "Text Files" "Textoé soubory" + ::msgcat::mcset cs "abort" "přerušit" + ::msgcat::mcset cs "blue" "modá" + ::msgcat::mcset cs "cancel" "zrušit" + ::msgcat::mcset cs "extension" "pípona" + ::msgcat::mcset cs "extensions" "pípony" + ::msgcat::mcset cs "green" "zeleá" ::msgcat::mcset cs "ignore" "ignorovat" ::msgcat::mcset cs "ok" - ::msgcat::mcset cs "red" "\u010derven\341" + ::msgcat::mcset cs "red" "červeá" ::msgcat::mcset cs "retry" "znovu" ::msgcat::mcset cs "yes" "ano" } Index: library/msgs/de.msg ================================================================== --- library/msgs/de.msg +++ library/msgs/de.msg @@ -1,34 +1,34 @@ namespace eval ::tk { ::msgcat::mcset de "&Abort" "&Abbruch" - ::msgcat::mcset de "&About..." "&\u00dcber..." + ::msgcat::mcset de "&About..." "&Über..." ::msgcat::mcset de "All Files" "Alle Dateien" ::msgcat::mcset de "Application Error" "Applikationsfehler" ::msgcat::mcset de "&Apply" "&Anwenden" ::msgcat::mcset de "Bold" "Fett" ::msgcat::mcset de "Bold Italic" "Fett kursiv" ::msgcat::mcset de "&Blue" "&Blau" ::msgcat::mcset de "Cancel" "Abbruch" ::msgcat::mcset de "&Cancel" "&Abbruch" ::msgcat::mcset de "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kann nicht in das Verzeichnis \"%1\$s\" wechseln.\nKeine Rechte vorhanden." - ::msgcat::mcset de "Choose Directory" "W\u00e4hle Verzeichnis" - ::msgcat::mcset de "Cl&ear" "&R\u00fccksetzen" - ::msgcat::mcset de "&Clear Console" "&Konsole l\u00f6schen" + ::msgcat::mcset de "Choose Directory" "Wähle Verzeichnis" + ::msgcat::mcset de "Cl&ear" "&Rücksetzen" + ::msgcat::mcset de "&Clear Console" "&Konsole löschen" ::msgcat::mcset de "Color" "Farbe" ::msgcat::mcset de "Console" "Konsole" ::msgcat::mcset de "&Copy" "&Kopieren" ::msgcat::mcset de "Cu&t" "Aus&schneiden" - ::msgcat::mcset de "&Delete" "&L\u00f6schen" + ::msgcat::mcset de "&Delete" "&Löschen" ::msgcat::mcset de "Details >>" ::msgcat::mcset de "Directory \"%1\$s\" does not exist." "Das Verzeichnis \"%1\$s\" existiert nicht." ::msgcat::mcset de "&Directory:" "&Verzeichnis:" ::msgcat::mcset de "&Edit" "&Bearbeiten" ::msgcat::mcset de "Effects" "Effekte" ::msgcat::mcset de "Error: %1\$s" "Fehler: %1\$s" ::msgcat::mcset de "E&xit" "&Ende" ::msgcat::mcset de "&File" "&Datei" - ::msgcat::mcset de "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei \u00fcberschreiben ?" + ::msgcat::mcset de "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei überschreiben ?" ::msgcat::mcset de "File \"%1\$s\" already exists.\n\n" "Die Datei \"%1\$s\" ist bereits vorhanden.\n\n" ::msgcat::mcset de "File \"%1\$s\" does not exist." "Die Datei \"%1\$s\" existiert nicht." ::msgcat::mcset de "File &name:" "Datei&name:" ::msgcat::mcset de "File &names:" "Datei&namen:" ::msgcat::mcset de "Files of &type:" "Dateien des &Typs:" @@ -36,56 +36,56 @@ ::msgcat::mcset de "&Filter" ::msgcat::mcset de "Fil&ter:" ::msgcat::mcset de "Font" "Schriftart" ::msgcat::mcset de "&Font:" "Schriftart:" ::msgcat::mcset de "Font st&yle:" "Schriftschnitt:" - ::msgcat::mcset de "&Green" "&Gr\u00fcn" + ::msgcat::mcset de "&Green" "&Grün" ::msgcat::mcset de "&Help" "&Hilfe" ::msgcat::mcset de "Hi" "Hallo" ::msgcat::mcset de "&Hide Console" "&Konsole unsichtbar machen" ::msgcat::mcset de "&Ignore" "&Ignorieren" - ::msgcat::mcset de "Invalid file name \"%1\$s\"." "Ung\u00fcltiger Dateiname \"%1\$s\"." + ::msgcat::mcset de "Invalid file name \"%1\$s\"." "Ungültiger Dateiname \"%1\$s\"." ::msgcat::mcset de "Italic" "Kursiv" ::msgcat::mcset de "Log Files" "Protokolldatei" ::msgcat::mcset de "&No" "&Nein" ::msgcat::mcset de "&OK" ::msgcat::mcset de "OK" ::msgcat::mcset de "Ok" - ::msgcat::mcset de "Open" "\u00d6ffnen" - ::msgcat::mcset de "&Open" "\u00d6&ffnen" + ::msgcat::mcset de "Open" "Öffnen" + ::msgcat::mcset de "&Open" "Ö&ffnen" ::msgcat::mcset de "Open Multiple Files" "Mehrere Dateien \u00F6ffnen" - ::msgcat::mcset de "P&aste" "E&inf\u00fcgen" + ::msgcat::mcset de "P&aste" "E&infügen" ::msgcat::mcset de "&Quit" "&Beenden" ::msgcat::mcset de "&Red" "&Rot" ::msgcat::mcset de "Regular" "Standard" ::msgcat::mcset de "Replace existing file?" "Existierende Datei ersetzen?" ::msgcat::mcset de "&Retry" "&Wiederholen" ::msgcat::mcset de "Sample" "Beispiel" ::msgcat::mcset de "&Save" "&Speichern" ::msgcat::mcset de "Save As" "Speichern unter" ::msgcat::mcset de "Save To Log" "In Protokoll speichern" - ::msgcat::mcset de "Select Log File" "Protokolldatei ausw\u00e4hlen" - ::msgcat::mcset de "Select a file to source" "Auszuf\u00fchrende Datei ausw\u00e4hlen" + ::msgcat::mcset de "Select Log File" "Protokolldatei auswählen" + ::msgcat::mcset de "Select a file to source" "Auszuführende Datei auswählen" ::msgcat::mcset de "&Selection:" "Auswah&l:" ::msgcat::mcset de "&Size:" "Schriftgrad:" ::msgcat::mcset de "Show &Hidden Directories" "Zeige versteckte Dateien" ::msgcat::mcset de "Show &Hidden Files and Directories" "Zeige versteckte Dateien und Verzeichnisse" - ::msgcat::mcset de "Skip Messages" "Weitere Nachrichten \u00fcberspringen" - ::msgcat::mcset de "&Source..." "&Ausf\u00fchren..." + ::msgcat::mcset de "Skip Messages" "Weitere Nachrichten überspringen" + ::msgcat::mcset de "&Source..." "&Ausführen..." ::msgcat::mcset de "Stri&keout" "&Durchgestrichen" ::msgcat::mcset de "Tcl Scripts" "Tcl-Skripte" - ::msgcat::mcset de "Tcl for Windows" "Tcl f\u00fcr Windows" + ::msgcat::mcset de "Tcl for Windows" "Tcl für Windows" ::msgcat::mcset de "Text Files" "Textdateien" ::msgcat::mcset de "&Underline" "&Unterstrichen" ::msgcat::mcset de "&Yes" "&Ja" ::msgcat::mcset de "abort" "abbrechen" ::msgcat::mcset de "blue" "blau" ::msgcat::mcset de "cancel" "abbrechen" ::msgcat::mcset de "extension" "Erweiterung" ::msgcat::mcset de "extensions" "Erweiterungen" - ::msgcat::mcset de "green" "gr\u00fcn" + ::msgcat::mcset de "green" "grün" ::msgcat::mcset de "ignore" "ignorieren" ::msgcat::mcset de "ok" ::msgcat::mcset de "red" "rot" ::msgcat::mcset de "retry" "wiederholen" ::msgcat::mcset de "yes" "ja" } Index: library/msgs/el.msg ================================================================== --- library/msgs/el.msg +++ library/msgs/el.msg @@ -1,86 +1,86 @@ ## Messages for the Greek (Hellenic - "el") language. ## Please report any changes/suggestions to: ## petasis@iit.demokritos.gr namespace eval ::tk { - ::msgcat::mcset el "&Abort" "\u03a4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2" - ::msgcat::mcset el "About..." "\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac..." - ::msgcat::mcset el "All Files" "\u038c\u03bb\u03b1 \u03c4\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03b1" - ::msgcat::mcset el "Application Error" "\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2" - ::msgcat::mcset el "&Blue" "\u039c\u03c0\u03bb\u03b5" - ::msgcat::mcset el "&Cancel" "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7" + ::msgcat::mcset el "&Abort" "Τερματισμός" + ::msgcat::mcset el "About..." "Σχετικά..." + ::msgcat::mcset el "All Files" "Όλα τα Αρχεία" + ::msgcat::mcset el "Application Error" "Λάθος Εφαρμογής" + ::msgcat::mcset el "&Blue" "Μπλε" + ::msgcat::mcset el "&Cancel" "Ακύρωση" ::msgcat::mcset el \ "Cannot change to the directory \"%1\$s\".\nPermission denied." \ -"\u0394\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03ba\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5 \u03c3\u03b5 \"%1\$s\".\n\u0397 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9." - ::msgcat::mcset el "Choose Directory" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u039a\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5" - ::msgcat::mcset el "Clear" "\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2" - ::msgcat::mcset el "Color" "\u03a7\u03c1\u03ce\u03bc\u03b1" - ::msgcat::mcset el "Console" "\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1" - ::msgcat::mcset el "Copy" "\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae" - ::msgcat::mcset el "Cut" "\u0391\u03c0\u03bf\u03ba\u03bf\u03c0\u03ae" - ::msgcat::mcset el "Delete" "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae" - ::msgcat::mcset el "Details >>" "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 >>" +"Δεν είναι δυνατή η αλλαγή καταλόγου σε \"%1\$s\".\nΗ πρόσβαση δεν επιτρέπεται." + ::msgcat::mcset el "Choose Directory" "Επιλογή Καταλόγου" + ::msgcat::mcset el "Clear" "Καθαρισμός" + ::msgcat::mcset el "Color" "Χρώμα" + ::msgcat::mcset el "Console" "Κονσόλα" + ::msgcat::mcset el "Copy" "Αντιγραφή" + ::msgcat::mcset el "Cut" "Αποκοπή" + ::msgcat::mcset el "Delete" "Διαγραφή" + ::msgcat::mcset el "Details >>" "Λεπτομέρειες >>" ::msgcat::mcset el "Directory \"%1\$s\" does not exist." \ - "\u039f \u03ba\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2 \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9." - ::msgcat::mcset el "&Directory:" "&\u039a\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2:" - ::msgcat::mcset el "Error: %1\$s" "\u039b\u03ac\u03b8\u03bf\u03c2: %1\$s" - ::msgcat::mcset el "Exit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2" + "Ο κατάλογος \"%1\$s\" δεν υπάρχει." + ::msgcat::mcset el "&Directory:" "&Κατάλογος:" + ::msgcat::mcset el "Error: %1\$s" "Λάθος: %1\$s" + ::msgcat::mcset el "Exit" "Έξοδος" ::msgcat::mcset el \ "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \ - "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03ba\u03b1\u03bb\u03c5\u03c6\u03b8\u03b5\u03af;" + "Το αρχείο \"%1\$s\" ήδη υπάρχει.\nΘέλετε να επικαλυφθεί;" ::msgcat::mcset el "File \"%1\$s\" already exists.\n\n" \ - "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\n" + "Το αρχείο \"%1\$s\" ήδη υπάρχει.\n\n" ::msgcat::mcset el "File \"%1\$s\" does not exist." \ - "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9." - ::msgcat::mcset el "File &name:" "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5:" - ::msgcat::mcset el "File &names:" "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd:" - ::msgcat::mcset el "Files of &type:" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03c4\u03bf\u03c5 &\u03c4\u03cd\u03c0\u03bf\u03c5:" - ::msgcat::mcset el "Fi&les:" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1:" - ::msgcat::mcset el "&Filter" "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf" - ::msgcat::mcset el "Fil&ter:" "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf:" - ::msgcat::mcset el "&Green" "\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf" - ::msgcat::mcset el "Hi" "\u0393\u03b5\u03b9\u03b1" - ::msgcat::mcset el "Hide Console" "\u0391\u03c0\u03cc\u03ba\u03c1\u03c5\u03c8\u03b7 \u03ba\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1\u03c2" - ::msgcat::mcset el "&Ignore" "\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7" + "Το αρχείο \"%1\$s\" δεν υπάρχει." + ::msgcat::mcset el "File &name:" "Ό&νομα αρχείου:" + ::msgcat::mcset el "File &names:" "Ό&νομα αρχείων:" + ::msgcat::mcset el "Files of &type:" "Αρχεία του &τύπου:" + ::msgcat::mcset el "Fi&les:" "Αρχεία:" + ::msgcat::mcset el "&Filter" "Φίλτρο" + ::msgcat::mcset el "Fil&ter:" "Φίλτρο:" + ::msgcat::mcset el "&Green" "Πράσινο" + ::msgcat::mcset el "Hi" "Γεια" + ::msgcat::mcset el "Hide Console" "Απόκρυψη κονσόλας" + ::msgcat::mcset el "&Ignore" "Αγνόηση" ::msgcat::mcset el "Invalid file name \"%1\$s\"." \ - "\u0386\u03ba\u03c5\u03c1\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \"%1\$s\"." - ::msgcat::mcset el "Log Files" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2" - ::msgcat::mcset el "&No" "\u038c\u03c7\u03b9" - ::msgcat::mcset el "&OK" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9" - ::msgcat::mcset el "OK" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9" - ::msgcat::mcset el "Ok" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9" - ::msgcat::mcset el "Open" "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1" - ::msgcat::mcset el "&Open" "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1" + "Άκυρο όνομα αρχείου \"%1\$s\"." + ::msgcat::mcset el "Log Files" "Αρχεία Καταγραφής" + ::msgcat::mcset el "&No" "Όχι" + ::msgcat::mcset el "&OK" "Εντάξει" + ::msgcat::mcset el "OK" "Εντάξει" + ::msgcat::mcset el "Ok" "Εντάξει" + ::msgcat::mcset el "Open" "Άνοιγμα" + ::msgcat::mcset el "&Open" "Άνοιγμα" ::msgcat::mcset el "Open Multiple Files" \ - "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd" - ::msgcat::mcset el "P&aste" "\u0395\u03c0\u03b9\u03ba\u03cc\u03bb\u03bb\u03b7\u03c3\u03b7" - ::msgcat::mcset el "Quit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2" - ::msgcat::mcset el "&Red" "\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf" + "Άνοιγμα πολλαπλών αρχείων" + ::msgcat::mcset el "P&aste" "Επικόλληση" + ::msgcat::mcset el "Quit" "Έξοδος" + ::msgcat::mcset el "&Red" "Κόκκινο" ::msgcat::mcset el "Replace existing file?" \ - "\u0395\u03c0\u03b9\u03ba\u03ac\u03bb\u03c5\u03c8\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd\u03c4\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5;" - ::msgcat::mcset el "&Retry" "\u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac" - ::msgcat::mcset el "&Save" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7" - ::msgcat::mcset el "Save As" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03b1\u03bd" - ::msgcat::mcset el "Save To Log" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2" - ::msgcat::mcset el "Select Log File" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2" + "Επικάλυψη υπάρχοντος αρχείου;" + ::msgcat::mcset el "&Retry" "Προσπάθησε ξανά" + ::msgcat::mcset el "&Save" "Αποθήκευση" + ::msgcat::mcset el "Save As" "Αποθήκευση σαν" + ::msgcat::mcset el "Save To Log" "Αποθήκευση στο αρχείο καταγραφής" + ::msgcat::mcset el "Select Log File" "Επιλογή αρχείου καταγραφής" ::msgcat::mcset el "Select a file to source" \ - "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b3\u03b9\u03b1 \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7" - ::msgcat::mcset el "&Selection:" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae:" - ::msgcat::mcset el "Skip Messages" "\u0391\u03c0\u03bf\u03c6\u03c5\u03b3\u03ae\u03bc\u03b7\u03bd\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd" - ::msgcat::mcset el "&Source..." "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7..." + "Επιλέξτε αρχείο για εκτέλεση" + ::msgcat::mcset el "&Selection:" "Επιλογή:" + ::msgcat::mcset el "Skip Messages" "Αποφυγήμηνυμάτων" + ::msgcat::mcset el "&Source..." "Εκτέλεση..." ::msgcat::mcset el "Tcl Scripts" "Tcl Scripts" - ::msgcat::mcset el "Tcl for Windows" "Tcl \u03b3\u03b9\u03b1 Windows" - ::msgcat::mcset el "Text Files" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b5\u03b9\u03bc\u03ad\u03bd\u03bf\u03c5" - ::msgcat::mcset el "&Yes" "\u039d\u03b1\u03b9" - ::msgcat::mcset el "abort" "\u03c4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2" - ::msgcat::mcset el "blue" "\u03bc\u03c0\u03bb\u03b5" - ::msgcat::mcset el "cancel" "\u03b1\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7" - ::msgcat::mcset el "extension" "\u03b5\u03c0\u03ad\u03ba\u03c4\u03b1\u03c3\u03b7" - ::msgcat::mcset el "extensions" "\u03b5\u03c0\u03b5\u03ba\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2" - ::msgcat::mcset el "green" "\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf" - ::msgcat::mcset el "ignore" "\u03b1\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7" - ::msgcat::mcset el "ok" "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9" - ::msgcat::mcset el "red" "\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf" - ::msgcat::mcset el "retry" "\u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac" - ::msgcat::mcset el "yes" "\u03bd\u03b1\u03b9" + ::msgcat::mcset el "Tcl for Windows" "Tcl για Windows" + ::msgcat::mcset el "Text Files" "Αρχεία Κειμένου" + ::msgcat::mcset el "&Yes" "Ναι" + ::msgcat::mcset el "abort" "τερματισμός" + ::msgcat::mcset el "blue" "μπλε" + ::msgcat::mcset el "cancel" "ακύρωση" + ::msgcat::mcset el "extension" "επέκταση" + ::msgcat::mcset el "extensions" "επεκτάσεις" + ::msgcat::mcset el "green" "πράσινο" + ::msgcat::mcset el "ignore" "αγνόηση" + ::msgcat::mcset el "ok" "εντάξει" + ::msgcat::mcset el "red" "κόκκινο" + ::msgcat::mcset el "retry" "προσπάθησε ξανά" + ::msgcat::mcset el "yes" "ναι" } Index: library/msgs/eo.msg ================================================================== --- library/msgs/eo.msg +++ library/msgs/eo.msg @@ -1,30 +1,30 @@ namespace eval ::tk { - ::msgcat::mcset eo "&Abort" "&\u0108esigo" + ::msgcat::mcset eo "&Abort" "&Ĉesigo" ::msgcat::mcset eo "&About..." "Pri..." - ::msgcat::mcset eo "All Files" "\u0108ioj dosieroj" + ::msgcat::mcset eo "All Files" "Ĉioj dosieroj" ::msgcat::mcset eo "Application Error" "Aplikoerraro" ::msgcat::mcset eo "&Blue" "&Blua" ::msgcat::mcset eo "Cancel" "Rezignu" ::msgcat::mcset eo "&Cancel" "&Rezignu" - ::msgcat::mcset eo "Cannot change to the directory \"%1\$s\".\nPermission denied." "Neeble \u0109angi al dosierulon \"%1\$s\".\nVi ne rajtas tion." + ::msgcat::mcset eo "Cannot change to the directory \"%1\$s\".\nPermission denied." "Neeble ĉangi al dosierulon \"%1\$s\".\nVi ne rajtas tion." ::msgcat::mcset eo "Choose Directory" "Elektu Dosierujo" ::msgcat::mcset eo "Cl&ear" "&Klaru" ::msgcat::mcset eo "&Clear Console" "&Klaru konzolon" ::msgcat::mcset eo "Color" "Farbo" ::msgcat::mcset eo "Console" "Konzolo" ::msgcat::mcset eo "&Copy" "&Kopiu" - ::msgcat::mcset eo "Cu&t" "&Enpo\u015digu" + ::msgcat::mcset eo "Cu&t" "&Enpoŝigu" ::msgcat::mcset eo "&Delete" "&Forprenu" ::msgcat::mcset eo "Details >>" "Detaloj >>" ::msgcat::mcset eo "Directory \"%1\$s\" does not exist." "La dosierujo \"%1\$s\" ne ekzistas." ::msgcat::mcset eo "&Directory:" "&Dosierujo:" ::msgcat::mcset eo "&Edit" "&Redaktu" ::msgcat::mcset eo "Error: %1\$s" "Eraro: %1\$s" ::msgcat::mcset eo "E&xit" "&Eliru" ::msgcat::mcset eo "&File" "&Dosiero" - ::msgcat::mcset eo "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "La dosiero \"%1\$s\" jam ekzistas.\n\u0108u vi volas anstata\u00fbigi la dosieron?" + ::msgcat::mcset eo "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "La dosiero \"%1\$s\" jam ekzistas.\nĈu vi volas anstataûigi la dosieron?" ::msgcat::mcset eo "File \"%1\$s\" already exists.\n\n" "La dosiero \"%1\$s\" jam egzistas. \n\n" ::msgcat::mcset eo "File \"%1\$s\" does not exist." "La dosierp \"%1\$s\" ne estas." ::msgcat::mcset eo "File &name:" "Dosiero&nomo:" ::msgcat::mcset eo "File &names:" "Dosiero&nomoj:" ::msgcat::mcset eo "Files of &type:" "Dosieroj de &Typo:" @@ -32,11 +32,11 @@ ::msgcat::mcset eo "&Filter" "&Filtrilo" ::msgcat::mcset eo "Fil&ter:" "&Filtrilo:" ::msgcat::mcset eo "&Green" "&Verda" ::msgcat::mcset eo "&Help" "&Helpu" ::msgcat::mcset eo "Hi" "Saluton" - ::msgcat::mcset eo "&Hide Console" "&Ka\u015du konzolon" + ::msgcat::mcset eo "&Hide Console" "&Kaŝu konzolon" ::msgcat::mcset eo "&Ignore" "&Ignoru" ::msgcat::mcset eo "Invalid file name \"%1\$s\"." "Malvalida dosieronomo \"%1\$s\"." ::msgcat::mcset eo "Log Files" "Protokolo" ::msgcat::mcset eo "&No" "&Ne" ::msgcat::mcset eo "&OK" @@ -43,33 +43,33 @@ ::msgcat::mcset eo "OK" ::msgcat::mcset eo "Ok" ::msgcat::mcset eo "Open" "Malfermu" ::msgcat::mcset eo "&Open" "&Malfermu" ::msgcat::mcset eo "Open Multiple Files" "Melfermu multan dosierojn" - ::msgcat::mcset eo "P&aste" "&Elpo\u015digi" + ::msgcat::mcset eo "P&aste" "&Elpoŝigi" ::msgcat::mcset eo "&Quit" "&Finigu" ::msgcat::mcset eo "&Red" "&Rosa" - ::msgcat::mcset eo "Replace existing file?" "\u0108u anstata\u00fbu ekzistantan dosieron?" + ::msgcat::mcset eo "Replace existing file?" "Ĉu anstataûu ekzistantan dosieron?" ::msgcat::mcset eo "&Retry" "&Ripetu" ::msgcat::mcset eo "&Save" "&Savu" ::msgcat::mcset eo "Save As" "Savu kiel" ::msgcat::mcset eo "Save To Log" "Savu en protokolon" ::msgcat::mcset eo "Select Log File" "Elektu prokolodosieron" ::msgcat::mcset eo "Select a file to source" "Elektu dosieron por interpreti" ::msgcat::mcset eo "&Selection:" "&Elekto:" - ::msgcat::mcset eo "Skip Messages" "transsaltu pluajn mesa\u011dojn" + ::msgcat::mcset eo "Skip Messages" "transsaltu pluajn mesaĝojn" ::msgcat::mcset eo "&Source..." "&Fontoprogramo..." ::msgcat::mcset eo "Tcl Scripts" "Tcl-skriptoj" ::msgcat::mcset eo "Tcl for Windows" "Tcl por vindoso" ::msgcat::mcset eo "Text Files" "Tekstodosierojn" ::msgcat::mcset eo "&Yes" "&Jes" - ::msgcat::mcset eo "abort" "\u0109esigo" + ::msgcat::mcset eo "abort" "ĉesigo" ::msgcat::mcset eo "blue" "blua" ::msgcat::mcset eo "cancel" "rezignu" ::msgcat::mcset eo "extension" "ekspansio" ::msgcat::mcset eo "extensions" "ekspansioj" ::msgcat::mcset eo "green" "verda" ::msgcat::mcset eo "ignore" "ignorieren" - ::msgcat::mcset eo "red" "ru\u011da" + ::msgcat::mcset eo "red" "ruĝa" ::msgcat::mcset eo "retry" "ripetu" ::msgcat::mcset eo "yes" "jes" } Index: library/msgs/es.msg ================================================================== --- library/msgs/es.msg +++ library/msgs/es.msg @@ -1,10 +1,10 @@ namespace eval ::tk { ::msgcat::mcset es "&Abort" "&Abortar" ::msgcat::mcset es "&About..." "&Acerca de ..." ::msgcat::mcset es "All Files" "Todos los archivos" - ::msgcat::mcset es "Application Error" "Error de la aplicaci\u00f3n" + ::msgcat::mcset es "Application Error" "Error de la aplicación" ::msgcat::mcset es "&Blue" "&Azul" ::msgcat::mcset es "Cancel" "Cancelar" ::msgcat::mcset es "&Cancel" "&Cancelar" ::msgcat::mcset es "Cannot change to the directory \"%1\$s\".\nPermission denied." "No es posible acceder al directorio \"%1\$s\".\nPermiso denegado." ::msgcat::mcset es "Choose Directory" "Elegir directorio" @@ -20,11 +20,11 @@ ::msgcat::mcset es "&Directory:" "&Directorio:" ::msgcat::mcset es "&Edit" "&Editar" ::msgcat::mcset es "Error: %1\$s" ::msgcat::mcset es "E&xit" "Salir" ::msgcat::mcset es "&File" "&Archivo" - ::msgcat::mcset es "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "El archivo \"%1\$s\" ya existe.\n\u00bfDesea sobreescribirlo?" + ::msgcat::mcset es "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "El archivo \"%1\$s\" ya existe.\n¿Desea sobreescribirlo?" ::msgcat::mcset es "File \"%1\$s\" already exists.\n\n" "El archivo \"%1\$s\" ya existe.\n\n" ::msgcat::mcset es "File \"%1\$s\" does not exist." "El archivo \"%1\$s\" no existe." ::msgcat::mcset es "File &name:" "&Nombre de archivo:" ::msgcat::mcset es "File &names:" "&Nombres de archivo:" ::msgcat::mcset es "Files of &type:" "Archivos de &tipo:" @@ -34,43 +34,43 @@ ::msgcat::mcset es "&Green" "&Verde" ::msgcat::mcset es "&Help" "&Ayuda" ::msgcat::mcset es "Hi" "Hola" ::msgcat::mcset es "&Hide Console" "&Esconder la consola" ::msgcat::mcset es "&Ignore" "&Ignorar" - ::msgcat::mcset es "Invalid file name \"%1\$s\"." "Nombre de archivo inv\u00e1lido \"%1\$s\"." + ::msgcat::mcset es "Invalid file name \"%1\$s\"." "Nombre de archivo inválido \"%1\$s\"." ::msgcat::mcset es "Log Files" "Ficheros de traza" ::msgcat::mcset es "&No" ::msgcat::mcset es "&OK" ::msgcat::mcset es "OK" ::msgcat::mcset es "Ok" ::msgcat::mcset es "Open" "Abrir" ::msgcat::mcset es "&Open" "&Abrir" - ::msgcat::mcset es "Open Multiple Files" "Abrir m\u00faltiples archivos" + ::msgcat::mcset es "Open Multiple Files" "Abrir múltiples archivos" ::msgcat::mcset es "P&aste" "Peg&ar" ::msgcat::mcset es "&Quit" "&Abandonar" ::msgcat::mcset es "&Red" "&Rojo" - ::msgcat::mcset es "Replace existing file?" "\u00bfReemplazar el archivo existente?" + ::msgcat::mcset es "Replace existing file?" "¿Reemplazar el archivo existente?" ::msgcat::mcset es "&Retry" "&Reintentar" ::msgcat::mcset es "&Save" "&Guardar" ::msgcat::mcset es "Save As" "Guardar como" ::msgcat::mcset es "Save To Log" "Guardar al archivo de traza" ::msgcat::mcset es "Select Log File" "Elegir un archivo de traza" ::msgcat::mcset es "Select a file to source" "Seleccionar un archivo a evaluar" - ::msgcat::mcset es "&Selection:" "&Selecci\u00f3n:" + ::msgcat::mcset es "&Selection:" "&Selección:" ::msgcat::mcset es "Skip Messages" "Omitir los mensajes" ::msgcat::mcset es "&Source..." "E&valuar..." ::msgcat::mcset es "Tcl Scripts" "Scripts Tcl" ::msgcat::mcset es "Tcl for Windows" "Tcl para Windows" ::msgcat::mcset es "Text Files" "Archivos de texto" - ::msgcat::mcset es "&Yes" "&S\u00ed" + ::msgcat::mcset es "&Yes" "&Sí" ::msgcat::mcset es "abort" "abortar" ::msgcat::mcset es "blue" "azul" ::msgcat::mcset es "cancel" "cancelar" - ::msgcat::mcset es "extension" "extensi\u00f3n" + ::msgcat::mcset es "extension" "extensión" ::msgcat::mcset es "extensions" "extensiones" ::msgcat::mcset es "green" "verde" ::msgcat::mcset es "ignore" "ignorar" ::msgcat::mcset es "ok" ::msgcat::mcset es "red" "rojo" ::msgcat::mcset es "retry" "reintentar" - ::msgcat::mcset es "yes" "s\u00ed" + ::msgcat::mcset es "yes" "sí" } Index: library/msgs/fr.msg ================================================================== --- library/msgs/fr.msg +++ library/msgs/fr.msg @@ -1,28 +1,28 @@ namespace eval ::tk { ::msgcat::mcset fr "&Abort" "&Annuler" - ::msgcat::mcset fr "About..." "\u00c0 propos..." + ::msgcat::mcset fr "About..." "À propos..." ::msgcat::mcset fr "All Files" "Tous les fichiers" ::msgcat::mcset fr "Application Error" "Erreur d'application" ::msgcat::mcset fr "&Blue" "&Bleu" ::msgcat::mcset fr "Cancel" "Annuler" ::msgcat::mcset fr "&Cancel" "&Annuler" - ::msgcat::mcset fr "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossible d'acc\u00e9der au r\u00e9pertoire \"%1\$s\".\nPermission refus\u00e9e." - ::msgcat::mcset fr "Choose Directory" "Choisir r\u00e9pertoire" + ::msgcat::mcset fr "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossible d'accéder au répertoire \"%1\$s\".\nPermission refusée." + ::msgcat::mcset fr "Choose Directory" "Choisir répertoire" ::msgcat::mcset fr "Cl&ear" "Effacer" ::msgcat::mcset fr "Color" "Couleur" ::msgcat::mcset fr "Console" ::msgcat::mcset fr "Copy" "Copier" ::msgcat::mcset fr "Cu&t" "Couper" ::msgcat::mcset fr "Delete" "Effacer" - ::msgcat::mcset fr "Details >>" "D\u00e9tails >>" - ::msgcat::mcset fr "Directory \"%1\$s\" does not exist." "Le r\u00e9pertoire \"%1\$s\" n'existe pas." - ::msgcat::mcset fr "&Directory:" "&R\u00e9pertoire:" + ::msgcat::mcset fr "Details >>" "Détails >>" + ::msgcat::mcset fr "Directory \"%1\$s\" does not exist." "Le répertoire \"%1\$s\" n'existe pas." + ::msgcat::mcset fr "&Directory:" "&Répertoire:" ::msgcat::mcset fr "Error: %1\$s" "Erreur: %1\$s" ::msgcat::mcset fr "E&xit" "Quitter" - ::msgcat::mcset fr "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\nVoulez-vous l'\u00e9craser?" - ::msgcat::mcset fr "File \"%1\$s\" already exists.\n\n" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\n\n" + ::msgcat::mcset fr "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Le fichier \"%1\$s\" existe déjà.\nVoulez-vous l'écraser?" + ::msgcat::mcset fr "File \"%1\$s\" already exists.\n\n" "Le fichier \"%1\$s\" existe déjà.\n\n" ::msgcat::mcset fr "File \"%1\$s\" does not exist." "Le fichier \"%1\$s\" n'existe pas." ::msgcat::mcset fr "File &name:" "&Nom de fichier:" ::msgcat::mcset fr "File &names:" "&Noms de fichiers:" ::msgcat::mcset fr "Files of &type:" "&Type de fichiers:" ::msgcat::mcset fr "Fi&les:" "Fich&iers:" @@ -43,19 +43,19 @@ ::msgcat::mcset fr "Open Multiple Files" "Ouvrir plusieurs fichiers" ::msgcat::mcset fr "P&aste" "Coller" ::msgcat::mcset fr "&Quit" "&Quitter" ::msgcat::mcset fr "&Red" "&Rouge" ::msgcat::mcset fr "Replace existing file?" "Remplacer le fichier existant?" - ::msgcat::mcset fr "&Retry" "&R\u00e9-essayer" + ::msgcat::mcset fr "&Retry" "&Ré-essayer" ::msgcat::mcset fr "&Save" "&Sauvegarder" ::msgcat::mcset fr "Save As" "Sauvegarder sous" ::msgcat::mcset fr "Save To Log" "Sauvegarde au fichier de trace" ::msgcat::mcset fr "Select Log File" "Choisir un fichier de trace" - ::msgcat::mcset fr "Select a file to source" "Choisir un fichier \u00e0 \u00e9valuer" - ::msgcat::mcset fr "&Selection:" "&S\u00e9lection:" + ::msgcat::mcset fr "Select a file to source" "Choisir un fichier à évaluer" + ::msgcat::mcset fr "&Selection:" "&Sélection:" ::msgcat::mcset fr "Skip Messages" "Omettre les messages" - ::msgcat::mcset fr "&Source..." "\u00c9valuer..." + ::msgcat::mcset fr "&Source..." "Évaluer..." ::msgcat::mcset fr "Tcl Scripts" "Scripts Tcl" ::msgcat::mcset fr "Tcl for Windows" "Tcl pour Windows" ::msgcat::mcset fr "Text Files" "Fichiers texte" ::msgcat::mcset fr "&Yes" "&Oui" ::msgcat::mcset fr "abort" "abandonner" @@ -65,8 +65,8 @@ ::msgcat::mcset fr "extensions" ::msgcat::mcset fr "green" "vert" ::msgcat::mcset fr "ignore" "ignorer" ::msgcat::mcset fr "ok" ::msgcat::mcset fr "red" "rouge" - ::msgcat::mcset fr "retry" "r\u00e9essayer" + ::msgcat::mcset fr "retry" "réessayer" ::msgcat::mcset fr "yes" "oui" } Index: library/msgs/hu.msg ================================================================== --- library/msgs/hu.msg +++ library/msgs/hu.msg @@ -1,78 +1,78 @@ namespace eval ::tk { - ::msgcat::mcset hu "&Abort" "&Megszak\u00edt\u00e1s" - ::msgcat::mcset hu "&About..." "N\u00e9vjegy..." - ::msgcat::mcset hu "All Files" "Minden f\u00e1jl" - ::msgcat::mcset hu "Application Error" "Alkalmaz\u00e1s hiba" - ::msgcat::mcset hu "&Blue" "&K\u00e9k" - ::msgcat::mcset hu "Cancel" "M\u00e9gsem" - ::msgcat::mcset hu "&Cancel" "M\u00e9g&sem" - ::msgcat::mcset hu "Cannot change to the directory \"%1\$s\".\nPermission denied." "A k\u00f6nyvt\u00e1rv\u00e1lt\u00e1s nem siker\u00fclt: \"%1\$s\".\nHozz\u00e1f\u00e9r\u00e9s megtagadva." - ::msgcat::mcset hu "Choose Directory" "K\u00f6nyvt\u00e1r kiv\u00e1laszt\u00e1sa" - ::msgcat::mcset hu "Cl&ear" "T\u00f6rl\u00e9s" - ::msgcat::mcset hu "&Clear Console" "&T\u00f6rl\u00e9s Konzol" - ::msgcat::mcset hu "Color" "Sz\u00edn" + ::msgcat::mcset hu "&Abort" "&Megszakítás" + ::msgcat::mcset hu "&About..." "Névjegy..." + ::msgcat::mcset hu "All Files" "Minden fájl" + ::msgcat::mcset hu "Application Error" "Alkalmazás hiba" + ::msgcat::mcset hu "&Blue" "&Kék" + ::msgcat::mcset hu "Cancel" "Mégsem" + ::msgcat::mcset hu "&Cancel" "Még&sem" + ::msgcat::mcset hu "Cannot change to the directory \"%1\$s\".\nPermission denied." "A könyvtárváltás nem sikerült: \"%1\$s\".\nHozzáférés megtagadva." + ::msgcat::mcset hu "Choose Directory" "Könyvtár kiválasztása" + ::msgcat::mcset hu "Cl&ear" "Törlés" + ::msgcat::mcset hu "&Clear Console" "&Törlés Konzol" + ::msgcat::mcset hu "Color" "Szín" ::msgcat::mcset hu "Console" "Konzol" - ::msgcat::mcset hu "&Copy" "&M\u00e1sol\u00e1s" - ::msgcat::mcset hu "Cu&t" "&Kiv\u00e1g\u00e1s" - ::msgcat::mcset hu "&Delete" "&T\u00f6rl\u00e9s" - ::msgcat::mcset hu "Details >>" "R\u00e9szletek >>" - ::msgcat::mcset hu "Directory \"%1\$s\" does not exist." "\"%1\$s\" k\u00f6nyvt\u00e1r nem l\u00e9tezik." - ::msgcat::mcset hu "&Directory:" "&K\u00f6nyvt\u00e1r:" + ::msgcat::mcset hu "&Copy" "&Másolás" + ::msgcat::mcset hu "Cu&t" "&Kivágás" + ::msgcat::mcset hu "&Delete" "&Törlés" + ::msgcat::mcset hu "Details >>" "Részletek >>" + ::msgcat::mcset hu "Directory \"%1\$s\" does not exist." "\"%1\$s\" könyvtár nem létezik." + ::msgcat::mcset hu "&Directory:" "&Könyvtár:" #::msgcat::mcset hu "&Edit" ::msgcat::mcset hu "Error: %1\$s" "Hiba: %1\$s" - ::msgcat::mcset hu "E&xit" "Kil\u00e9p\u00e9s" - ::msgcat::mcset hu "&File" "&F\u00e1jl" - ::msgcat::mcset hu "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "\"%1\$s\" f\u00e1jl m\u00e1r l\u00e9tezik.\nFel\u00fcl\u00edrjam?" - ::msgcat::mcset hu "File \"%1\$s\" already exists.\n\n" "\"%1\$s\" f\u00e1jl m\u00e1r l\u00e9tezik.\n\n" - ::msgcat::mcset hu "File \"%1\$s\" does not exist." "\"%1\$s\" f\u00e1jl nem l\u00e9tezik." - ::msgcat::mcset hu "File &name:" "F\u00e1jl &neve:" - ::msgcat::mcset hu "File &names:" "F\u00e1jlok &nevei:" - ::msgcat::mcset hu "Files of &type:" "F\u00e1jlok &t\u00edpusa:" - ::msgcat::mcset hu "Fi&les:" "F\u00e1j&lok:" - ::msgcat::mcset hu "&Filter" "&Sz\u0171r\u0151" - ::msgcat::mcset hu "Fil&ter:" "S&z\u0171r\u0151:" - ::msgcat::mcset hu "&Green" "&Z\u00f6ld" + ::msgcat::mcset hu "E&xit" "Kilépés" + ::msgcat::mcset hu "&File" "&Fájl" + ::msgcat::mcset hu "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "\"%1\$s\" fájl már létezik.\nFelülírjam?" + ::msgcat::mcset hu "File \"%1\$s\" already exists.\n\n" "\"%1\$s\" fájl már létezik.\n\n" + ::msgcat::mcset hu "File \"%1\$s\" does not exist." "\"%1\$s\" fájl nem létezik." + ::msgcat::mcset hu "File &name:" "Fájl &neve:" + ::msgcat::mcset hu "File &names:" "Fájlok &nevei:" + ::msgcat::mcset hu "Files of &type:" "Fájlok &típusa:" + ::msgcat::mcset hu "Fi&les:" "Fáj&lok:" + ::msgcat::mcset hu "&Filter" "&Szűrő" + ::msgcat::mcset hu "Fil&ter:" "S&zűrő:" + ::msgcat::mcset hu "&Green" "&Zöld" #::msgcat::mcset hu "&Help" - ::msgcat::mcset hu "Hi" "\u00dcdv" - ::msgcat::mcset hu "&Hide Console" "Konzol &elrejt\u00e9se" - ::msgcat::mcset hu "&Ignore" "K&ihagy\u00e1s" - ::msgcat::mcset hu "Invalid file name \"%1\$s\"." "\u00c9rv\u00e9nytelen f\u00e1jln\u00e9v: \"%1\$s\"." - ::msgcat::mcset hu "Log Files" "Log f\u00e1jlok" + ::msgcat::mcset hu "Hi" "Üdv" + ::msgcat::mcset hu "&Hide Console" "Konzol &elrejtése" + ::msgcat::mcset hu "&Ignore" "K&ihagyás" + ::msgcat::mcset hu "Invalid file name \"%1\$s\"." "Érvénytelen fájlnév: \"%1\$s\"." + ::msgcat::mcset hu "Log Files" "Log fájlok" ::msgcat::mcset hu "&No" "&Nem" ::msgcat::mcset hu "&OK" ::msgcat::mcset hu "OK" ::msgcat::mcset hu "Ok" - ::msgcat::mcset hu "Open" "Megnyit\u00e1s" - ::msgcat::mcset hu "&Open" "&Megnyit\u00e1s" - ::msgcat::mcset hu "Open Multiple Files" "T\u00f6bb f\u00e1jl megnyit\u00e1sa" - ::msgcat::mcset hu "P&aste" "&Beilleszt\u00e9s" - ::msgcat::mcset hu "&Quit" "&Kil\u00e9p\u00e9s" - ::msgcat::mcset hu "&Red" "&V\u00f6r\u00f6s" - ::msgcat::mcset hu "Replace existing file?" "Megl\u00e9v\u0151 f\u00e1jl cser\u00e9je?" - ::msgcat::mcset hu "&Retry" "\u00daj&ra" - ::msgcat::mcset hu "&Save" "&Ment\u00e9s" - ::msgcat::mcset hu "Save As" "Ment\u00e9s m\u00e1sk\u00e9nt" - ::msgcat::mcset hu "Save To Log" "Ment\u00e9s log f\u00e1jlba" - ::msgcat::mcset hu "Select Log File" "Log f\u00e1jl kiv\u00e1laszt\u00e1sa" - ::msgcat::mcset hu "Select a file to source" "Forr\u00e1sf\u00e1jl kiv\u00e1laszt\u00e1sa" - ::msgcat::mcset hu "&Selection:" "&Kijel\u00f6l\u00e9s:" - ::msgcat::mcset hu "Show &Hidden Directories" "&Rejtett k\u00f6nyvt\u00e1rak megjelen\u00edt\u00e9se" - ::msgcat::mcset hu "Show &Hidden Files and Directories" "&Rejtett f\u00e1jlok \u00e9s k\u00f6nyvt\u00e1rak megjelen\u00edt\u00e9se" - ::msgcat::mcset hu "Skip Messages" "\u00dczenetek kihagy\u00e1sa" - ::msgcat::mcset hu "&Source..." "&Forr\u00e1s..." + ::msgcat::mcset hu "Open" "Megnyitás" + ::msgcat::mcset hu "&Open" "&Megnyitás" + ::msgcat::mcset hu "Open Multiple Files" "Több fájl megnyitása" + ::msgcat::mcset hu "P&aste" "&Beillesztés" + ::msgcat::mcset hu "&Quit" "&Kilépés" + ::msgcat::mcset hu "&Red" "&Vörös" + ::msgcat::mcset hu "Replace existing file?" "Meglévő fájl cseréje?" + ::msgcat::mcset hu "&Retry" "Új&ra" + ::msgcat::mcset hu "&Save" "&Mentés" + ::msgcat::mcset hu "Save As" "Mentés másként" + ::msgcat::mcset hu "Save To Log" "Mentés log fájlba" + ::msgcat::mcset hu "Select Log File" "Log fájl kiválasztása" + ::msgcat::mcset hu "Select a file to source" "Forrásfájl kiválasztása" + ::msgcat::mcset hu "&Selection:" "&Kijelölés:" + ::msgcat::mcset hu "Show &Hidden Directories" "&Rejtett könyvtárak megjelenítése" + ::msgcat::mcset hu "Show &Hidden Files and Directories" "&Rejtett fájlok és könyvtárak megjelenítése" + ::msgcat::mcset hu "Skip Messages" "Üzenetek kihagyása" + ::msgcat::mcset hu "&Source..." "&Forrás..." ::msgcat::mcset hu "Tcl Scripts" "Tcl scriptek" ::msgcat::mcset hu "Tcl for Windows" "Tcl Windows-hoz" - ::msgcat::mcset hu "Text Files" "Sz\u00f6vegf\u00e1jlok" + ::msgcat::mcset hu "Text Files" "Szövegfájlok" ::msgcat::mcset hu "&Yes" "&Igen" - ::msgcat::mcset hu "abort" "megszak\u00edt\u00e1s" - ::msgcat::mcset hu "blue" "k\u00e9k" - ::msgcat::mcset hu "cancel" "m\u00e9gsem" - ::msgcat::mcset hu "extension" "kiterjeszt\u00e9s" - ::msgcat::mcset hu "extensions" "kiterjeszt\u00e9sek" - ::msgcat::mcset hu "green" "z\u00f6ld" + ::msgcat::mcset hu "abort" "megszakítás" + ::msgcat::mcset hu "blue" "kék" + ::msgcat::mcset hu "cancel" "mégsem" + ::msgcat::mcset hu "extension" "kiterjesztés" + ::msgcat::mcset hu "extensions" "kiterjesztések" + ::msgcat::mcset hu "green" "zöld" ::msgcat::mcset hu "ignore" "ignorer" ::msgcat::mcset hu "ok" - ::msgcat::mcset hu "red" "v\u00f6r\u00f6s" - ::msgcat::mcset hu "retry" "\u00fajra" + ::msgcat::mcset hu "red" "vörös" + ::msgcat::mcset hu "retry" "újra" ::msgcat::mcset hu "yes" "igen" } Index: library/msgs/it.msg ================================================================== --- library/msgs/it.msg +++ library/msgs/it.msg @@ -18,12 +18,12 @@ ::msgcat::mcset it "Details >>" "Dettagli >>" ::msgcat::mcset it "Directory \"%1\$s\" does not exist." "La directory \"%1\$s\" non esiste." ::msgcat::mcset it "&Directory:" ::msgcat::mcset it "Error: %1\$s" "Errore: %1\$s" ::msgcat::mcset it "E&xit" "Esci" - ::msgcat::mcset it "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Il file \"%1\$s\" esiste gi\u00e0.\nVuoi sovrascriverlo?" - ::msgcat::mcset it "File \"%1\$s\" already exists.\n\n" "Il file \"%1\$s\" esiste gi\u00e0.\n\n" + ::msgcat::mcset it "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Il file \"%1\$s\" esiste già.\nVuoi sovrascriverlo?" + ::msgcat::mcset it "File \"%1\$s\" already exists.\n\n" "Il file \"%1\$s\" esiste già.\n\n" ::msgcat::mcset it "File \"%1\$s\" does not exist." "Il file \"%1\$s\" non esiste." ::msgcat::mcset it "File &name:" "&Nome del file:" ::msgcat::mcset it "File &names:" "&Nomi dei file:" ::msgcat::mcset it "Files of &type:" "File di &tipo:" ::msgcat::mcset it "Fi&les:" "Fi&le:" @@ -56,11 +56,11 @@ ::msgcat::mcset it "Skip Messages" "Salta i messaggi" ::msgcat::mcset it "Source..." "Esegui..." ::msgcat::mcset it "Tcl Scripts" "Script Tcl" ::msgcat::mcset it "Tcl for Windows" "Tcl per Windows" ::msgcat::mcset it "Text Files" "File di testo" - ::msgcat::mcset it "&Yes" "&S\u00ec" + ::msgcat::mcset it "&Yes" "&Sì" ::msgcat::mcset it "abort" "interrompi" ::msgcat::mcset it "blue" "blu" ::msgcat::mcset it "cancel" "annulla" ::msgcat::mcset it "extension" "estensione" ::msgcat::mcset it "extensions" "estensioni" @@ -67,7 +67,7 @@ ::msgcat::mcset it "green" "verde" ::msgcat::mcset it "ignore" "ignora" ::msgcat::mcset it "ok" ::msgcat::mcset it "red" "rosso" ::msgcat::mcset it "retry" "riprova" - ::msgcat::mcset it "yes" "s\u00ec" + ::msgcat::mcset it "yes" "sì" } Index: library/msgs/nl.msg ================================================================== --- library/msgs/nl.msg +++ library/msgs/nl.msg @@ -13,20 +13,20 @@ ::msgcat::mcset nl "Choose Directory" "Kies map" ::msgcat::mcset nl "Cl&ear" "Wissen" ::msgcat::mcset nl "&Clear Console" "&Wis Console" ::msgcat::mcset nl "Color" "Kleur" ::msgcat::mcset nl "Console" - ::msgcat::mcset nl "&Copy" "Kopi\u00ebren" + ::msgcat::mcset nl "&Copy" "Kopiëren" ::msgcat::mcset nl "Cu&t" "Knippen" ::msgcat::mcset nl "&Delete" "Wissen" ::msgcat::mcset nl "Details >>" ::msgcat::mcset nl "Directory \"%1\$s\" does not exist." "Map \"%1\$s\" bestaat niet." ::msgcat::mcset nl "&Directory:" "&Map:" ::msgcat::mcset nl "&Edit" "Bewerken" ::msgcat::mcset nl "Effects" "Effecten" ::msgcat::mcset nl "Error: %1\$s" "Fout: %1\$s" - ::msgcat::mcset nl "E&xit" "Be\u00ebindigen" + ::msgcat::mcset nl "E&xit" "Beëindigen" ::msgcat::mcset nl "&File" "Bestand" ::msgcat::mcset nl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Bestand \"%1\$s\" bestaat al.\nWilt u het overschrijven?" ::msgcat::mcset nl "File \"%1\$s\" already exists.\n\n" "Bestand \"%1\$s\" bestaat al.\n\n" ::msgcat::mcset nl "File \"%1\$s\" does not exist." "Bestand \"%1\$s\" bestaat niet." ::msgcat::mcset nl "File &name:" "Bestands&naam:" @@ -38,11 +38,11 @@ ::msgcat::mcset nl "Font" ::msgcat::mcset nl "&Font:" ::msgcat::mcset nl "Font st&yle:" "Font stijl:" ::msgcat::mcset nl "&Green" "&Groen" ::msgcat::mcset nl "&Help" - ::msgcat::mcset nl "Hi" "H\u00e9" + ::msgcat::mcset nl "Hi" "Hé" ::msgcat::mcset nl "&Hide Console" "Verberg Console" ::msgcat::mcset nl "&Ignore" "&Negeren" ::msgcat::mcset nl "Invalid file name \"%1\$s\"." "Ongeldige bestandsnaam \"%1\$s\"." ::msgcat::mcset nl "Italic" "Cursief" ::msgcat::mcset nl "Log Files" "Log Bestanden" Index: library/msgs/pl.msg ================================================================== --- library/msgs/pl.msg +++ library/msgs/pl.msg @@ -1,38 +1,38 @@ namespace eval ::tk { ::msgcat::mcset pl "&Abort" "&Przerwij" ::msgcat::mcset pl "&About..." "O programie..." ::msgcat::mcset pl "All Files" "Wszystkie pliki" - ::msgcat::mcset pl "Application Error" "B\u0142\u0105d w programie" + ::msgcat::mcset pl "Application Error" "Błąd w programie" ::msgcat::mcset pl "&Apply" "Zastosuj" ::msgcat::mcset pl "Bold" "Pogrubienie" ::msgcat::mcset pl "Bold Italic" "Pogrubiona kursywa" ::msgcat::mcset pl "&Blue" "&Niebieski" ::msgcat::mcset pl "Cancel" "Anuluj" ::msgcat::mcset pl "&Cancel" "&Anuluj" - ::msgcat::mcset pl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nie mo\u017cna otworzy\u0107 katalogu \"%1\$s\".\nOdmowa dost\u0119pu." + ::msgcat::mcset pl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nie można otworzyć katalogu \"%1\$s\".\nOdmowa dostępu." ::msgcat::mcset pl "Choose Directory" "Wybierz katalog" - ::msgcat::mcset pl "Cl&ear" "&Wyczy\u015b\u0107" - ::msgcat::mcset pl "&Clear Console" "&Wyczy\u015b\u0107 konsol\u0119" + ::msgcat::mcset pl "Cl&ear" "&Wyczyść" + ::msgcat::mcset pl "&Clear Console" "&Wyczyść konsolę" ::msgcat::mcset pl "Color" "Kolor" ::msgcat::mcset pl "Console" "Konsola" ::msgcat::mcset pl "&Copy" "&Kopiuj" ::msgcat::mcset pl "Cu&t" "&Wytnij" - ::msgcat::mcset pl "&Delete" "&Usu\u0144" - ::msgcat::mcset pl "Details >>" "Szczeg\u00f3\u0142y >>" + ::msgcat::mcset pl "&Delete" "&Usuń" + ::msgcat::mcset pl "Details >>" "Szczegóły >>" ::msgcat::mcset pl "Directory \"%1\$s\" does not exist." "Katalog \"%1\$s\" nie istnieje." ::msgcat::mcset pl "&Directory:" "&Katalog:" ::msgcat::mcset pl "&Edit" "&Edytuj" ::msgcat::mcset pl "Effects" "Efekty" - ::msgcat::mcset pl "Error: %1\$s" "B\u0142\u0105d: %1\$s" - ::msgcat::mcset pl "E&xit" "&Wyjd\u017a" + ::msgcat::mcset pl "Error: %1\$s" "Błąd: %1\$s" + ::msgcat::mcset pl "E&xit" "&Wyjdź" ::msgcat::mcset pl "&File" "&Plik" - ::msgcat::mcset pl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Plik \"%1\$s\" ju\u017c istnieje.\nCzy chcesz go nadpisa\u0107?" - ::msgcat::mcset pl "File \"%1\$s\" already exists.\n\n" "Plik \"%1\$s\" ju\u017c istnieje.\n\n" + ::msgcat::mcset pl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Plik \"%1\$s\" już istnieje.\nCzy chcesz go nadpisać?" + ::msgcat::mcset pl "File \"%1\$s\" already exists.\n\n" "Plik \"%1\$s\" już istnieje.\n\n" ::msgcat::mcset pl "File \"%1\$s\" does not exist." "Plik \"%1\$s\" nie istnieje." ::msgcat::mcset pl "File &name:" "Nazwa &pliku:" - ::msgcat::mcset pl "File &names:" "Nazwy &plik\u00f3w:" + ::msgcat::mcset pl "File &names:" "Nazwy &plików:" ::msgcat::mcset pl "Files of &type:" "Pliki &typu:" ::msgcat::mcset pl "Fi&les:" "Pli&ki:" ::msgcat::mcset pl "&Filter" "&Filtr" ::msgcat::mcset pl "Fil&ter:" "&Filtr:" ::msgcat::mcset pl "Font" "Czcionka" @@ -39,45 +39,45 @@ ::msgcat::mcset pl "&Font:" "Czcio&nka:" ::msgcat::mcset pl "Font st&yle:" "&Styl czcionki:" ::msgcat::mcset pl "&Green" "&Zielony" ::msgcat::mcset pl "&Help" "&Pomoc" ::msgcat::mcset pl "Hi" "Witaj" - ::msgcat::mcset pl "&Hide Console" "&Ukryj konsol\u0119" + ::msgcat::mcset pl "&Hide Console" "&Ukryj konsolę" ::msgcat::mcset pl "&Ignore" "&Ignoruj" - ::msgcat::mcset pl "Invalid file name \"%1\$s\"." "Niew\u0142a\u015bciwa nazwa pliku \"%1\$s\"." + ::msgcat::mcset pl "Invalid file name \"%1\$s\"." "Niewłaściwa nazwa pliku \"%1\$s\"." ::msgcat::mcset pl "Italic" "Kursywa" ::msgcat::mcset pl "Log Files" "Pliki dziennika" ::msgcat::mcset pl "&No" "&Nie" ::msgcat::mcset pl "&OK" ::msgcat::mcset pl "OK" ::msgcat::mcset pl "Ok" - ::msgcat::mcset pl "Open" "Otw\u00f3rz" - ::msgcat::mcset pl "&Open" "&Otw\u00f3rz" - ::msgcat::mcset pl "Open Multiple Files" "Otw\u00f3rz wiele plik\u00f3w" + ::msgcat::mcset pl "Open" "Otwórz" + ::msgcat::mcset pl "&Open" "&Otwórz" + ::msgcat::mcset pl "Open Multiple Files" "Otwórz wiele plików" ::msgcat::mcset pl "P&aste" "&Wklej" - ::msgcat::mcset pl "&Quit" "&Zako\u0144cz" + ::msgcat::mcset pl "&Quit" "&Zakończ" ::msgcat::mcset pl "&Red" "&Czerwony" ::msgcat::mcset pl "Regular" "Regularne" - ::msgcat::mcset pl "Replace existing file?" "Czy zast\u0105pi\u0107 istniej\u0105cy plik?" - ::msgcat::mcset pl "&Retry" "&Pon\u00f3w" - ::msgcat::mcset pl "Sample" "Przyk\u0142ad" + ::msgcat::mcset pl "Replace existing file?" "Czy zastąpić istniejący plik?" + ::msgcat::mcset pl "&Retry" "&Ponów" + ::msgcat::mcset pl "Sample" "Przykład" ::msgcat::mcset pl "&Save" "&Zapisz" ::msgcat::mcset pl "Save As" "Zapisz jako" ::msgcat::mcset pl "Save To Log" "Wpisz do dziennika" ::msgcat::mcset pl "Select Log File" "Wybierz plik dziennika" ::msgcat::mcset pl "Select a file to source" "Wybierz plik do wykonania" - ::msgcat::mcset pl "&Selection:" "&Wyb\u00f3r:" + ::msgcat::mcset pl "&Selection:" "&Wybór:" ::msgcat::mcset pl "&Size:" "&Rozmiar:" - ::msgcat::mcset pl "Show &Hidden Directories" "Poka\u017c &ukryte katalogi" - ::msgcat::mcset pl "Show &Hidden Files and Directories" "Poka\u017c &ukryte pliki i katalogi" - ::msgcat::mcset pl "Skip Messages" "Pomi\u0144 pozosta\u0142e komunikaty" - ::msgcat::mcset pl "&Source..." "&Kod \u017ar\u00f3d\u0142owy..." - ::msgcat::mcset pl "Stri&keout" "&Przekre\u015blenie" + ::msgcat::mcset pl "Show &Hidden Directories" "Pokaż &ukryte katalogi" + ::msgcat::mcset pl "Show &Hidden Files and Directories" "Pokaż &ukryte pliki i katalogi" + ::msgcat::mcset pl "Skip Messages" "Pomiń pozostałe komunikaty" + ::msgcat::mcset pl "&Source..." "&Kod źródłowy..." + ::msgcat::mcset pl "Stri&keout" "&Przekreślenie" ::msgcat::mcset pl "Tcl Scripts" "Skrypty Tcl" ::msgcat::mcset pl "Tcl for Windows" "Tcl dla Windows" ::msgcat::mcset pl "Text Files" "Pliki tekstowe" - ::msgcat::mcset pl "&Underline" "Po&dkre\u015blenie" + ::msgcat::mcset pl "&Underline" "Po&dkreślenie" ::msgcat::mcset pl "&Yes" "&Tak" ::msgcat::mcset pl "abort" "przerwij" ::msgcat::mcset pl "blue" "niebieski" ::msgcat::mcset pl "cancel" "anuluj" ::msgcat::mcset pl "extension" "rozszerzenie" @@ -84,8 +84,8 @@ ::msgcat::mcset pl "extensions" "rozszerzenia" ::msgcat::mcset pl "green" "zielony" ::msgcat::mcset pl "ignore" "ignoruj" ::msgcat::mcset pl "ok" ::msgcat::mcset pl "red" "czerwony" - ::msgcat::mcset pl "retry" "pon\u00f3w" + ::msgcat::mcset pl "retry" "ponów" ::msgcat::mcset pl "yes" "tak" } Index: library/msgs/pt.msg ================================================================== --- library/msgs/pt.msg +++ library/msgs/pt.msg @@ -1,31 +1,31 @@ namespace eval ::tk { ::msgcat::mcset pt "&Abort" "&Abortar" ::msgcat::mcset pt "About..." "Sobre ..." ::msgcat::mcset pt "All Files" "Todos os arquivos" - ::msgcat::mcset pt "Application Error" "Erro de aplica\u00e7\u00e3o" + ::msgcat::mcset pt "Application Error" "Erro de aplicação" ::msgcat::mcset pt "&Blue" "&Azul" ::msgcat::mcset pt "Cancel" "Cancelar" ::msgcat::mcset pt "&Cancel" "&Cancelar" - ::msgcat::mcset pt "Cannot change to the directory \"%1\$s\".\nPermission denied." "N\u00e3o foi poss\u00edvel mudar para o diret\u00f3rio \"%1\$s\".\nPermiss\u00e3o negada." - ::msgcat::mcset pt "Choose Directory" "Escolha um diret\u00f3rio" + ::msgcat::mcset pt "Cannot change to the directory \"%1\$s\".\nPermission denied." "Não foi possível mudar para o diretório \"%1\$s\".\nPermissão negada." + ::msgcat::mcset pt "Choose Directory" "Escolha um diretório" ::msgcat::mcset pt "Cl&ear" "Apagar" ::msgcat::mcset pt "&Clear Console" "Apagar Console" ::msgcat::mcset pt "Color" "Cor" ::msgcat::mcset pt "Console" ::msgcat::mcset pt "&Copy" "Copiar" ::msgcat::mcset pt "Cu&t" "Recortar" ::msgcat::mcset pt "&Delete" "Excluir" ::msgcat::mcset pt "Details >>" "Detalhes >>" - ::msgcat::mcset pt "Directory \"%1\$s\" does not exist." "O diret\u00f3rio \"%1\$s\" n\u00e3o existe." - ::msgcat::mcset pt "&Directory:" "&Diret\u00f3rio:" + ::msgcat::mcset pt "Directory \"%1\$s\" does not exist." "O diretório \"%1\$s\" não existe." + ::msgcat::mcset pt "&Directory:" "&Diretório:" ::msgcat::mcset pt "Error: %1\$s" "Erro: %1\$s" ::msgcat::mcset pt "E&xit" "Sair" ::msgcat::mcset pt "&File" "Arquivo" - ::msgcat::mcset pt "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "O arquivo \"%1\$s\" j\u00e1 existe.\nDeseja sobrescreve-lo?" - ::msgcat::mcset pt "File \"%1\$s\" already exists.\n\n" "O arquivo \"%1\$s\" j\u00e1 existe.\n\n" - ::msgcat::mcset pt "File \"%1\$s\" does not exist." "Arquivo \"%1\$s\" n\u00e3o existe." + ::msgcat::mcset pt "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "O arquivo \"%1\$s\" já existe.\nDeseja sobrescreve-lo?" + ::msgcat::mcset pt "File \"%1\$s\" already exists.\n\n" "O arquivo \"%1\$s\" já existe.\n\n" + ::msgcat::mcset pt "File \"%1\$s\" does not exist." "Arquivo \"%1\$s\" não existe." ::msgcat::mcset pt "File &name:" "&Nome do arquivo:" ::msgcat::mcset pt "File &names:" "&Nomes dos arquivos:" ::msgcat::mcset pt "Files of &type:" "Arquivos do &tipo:" ::msgcat::mcset pt "Fi&les:" "&Arquivos:" ::msgcat::mcset pt "&Filter" "&Filtro" @@ -32,19 +32,19 @@ ::msgcat::mcset pt "Fil&ter:" "Fil&tro:" ::msgcat::mcset pt "&Green" "&Verde" ::msgcat::mcset pt "Hi" "Oi" ::msgcat::mcset pt "&Hide Console" "Ocultar console" ::msgcat::mcset pt "&Ignore" "&Ignorar" - ::msgcat::mcset pt "Invalid file name \"%1\$s\"." "O nome do arquivo \u00e9 inv\u00e1lido \"%1\$s\"." + ::msgcat::mcset pt "Invalid file name \"%1\$s\"." "O nome do arquivo é inválido \"%1\$s\"." ::msgcat::mcset pt "Log Files" "Arquivos de log" - ::msgcat::mcset pt "&No" "&N\u00e3o" + ::msgcat::mcset pt "&No" "&Não" ::msgcat::mcset pt "&OK" ::msgcat::mcset pt "OK" ::msgcat::mcset pt "Ok" ::msgcat::mcset pt "Open" "Abrir" ::msgcat::mcset pt "&Open" "&Abrir" - ::msgcat::mcset pt "Open Multiple Files" "Abrir m\u00faltiplos arquivos" + ::msgcat::mcset pt "Open Multiple Files" "Abrir múltiplos arquivos" ::msgcat::mcset pt "P&aste" "Col&ar" ::msgcat::mcset pt "Quit" "Encerrar" ::msgcat::mcset pt "&Red" "&Vermelho" ::msgcat::mcset pt "Replace existing file?" "Substituir arquivo existente?" ::msgcat::mcset pt "&Retry" "Tenta&r novamente" @@ -51,24 +51,24 @@ ::msgcat::mcset pt "&Save" "&Salvar" ::msgcat::mcset pt "Save As" "Salvar como" ::msgcat::mcset pt "Save To Log" "Salvar arquivo de log" ::msgcat::mcset pt "Select Log File" "Selecionar arquivo de log" ::msgcat::mcset pt "Select a file to source" "Selecione um arquivo como fonte" - ::msgcat::mcset pt "&Selection:" "&Sele\u00e7\u00e3o:" + ::msgcat::mcset pt "&Selection:" "&Seleção:" ::msgcat::mcset pt "Skip Messages" "Omitir as mensagens" ::msgcat::mcset pt "&Source..." "&Fonte..." ::msgcat::mcset pt "Tcl Scripts" "Scripts Tcl" ::msgcat::mcset pt "Tcl for Windows" "Tcl para Windows" ::msgcat::mcset pt "Text Files" "Arquivos de texto" ::msgcat::mcset pt "&Yes" "&Sim" ::msgcat::mcset pt "abort" "abortar" ::msgcat::mcset pt "blue" "azul" ::msgcat::mcset pt "cancel" "cancelar" - ::msgcat::mcset pt "extension" "extens\u00e3o" - ::msgcat::mcset pt "extensions" "extens\u00f5es" + ::msgcat::mcset pt "extension" "extensão" + ::msgcat::mcset pt "extensions" "extensões" ::msgcat::mcset pt "green" "verde" ::msgcat::mcset pt "ignore" "ignorar" ::msgcat::mcset pt "ok" ::msgcat::mcset pt "red" "vermelho" ::msgcat::mcset pt "retry" "tentar novamente" ::msgcat::mcset pt "yes" "sim" } Index: library/msgs/ru.msg ================================================================== --- library/msgs/ru.msg +++ library/msgs/ru.msg @@ -1,75 +1,75 @@ namespace eval ::tk { - ::msgcat::mcset ru "&Abort" "&\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c" - ::msgcat::mcset ru "&About..." "\u041f\u0440\u043e..." - ::msgcat::mcset ru "All Files" "\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b" - ::msgcat::mcset ru "Application Error" "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435" - ::msgcat::mcset ru "&Blue" " &\u0413\u043e\u043b\u0443\u0431\u043e\u0439" - ::msgcat::mcset ru "Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430" - ::msgcat::mcset ru "&Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430" + ::msgcat::mcset ru "&Abort" "&Отменить" + ::msgcat::mcset ru "&About..." "Про..." + ::msgcat::mcset ru "All Files" "Все файлы" + ::msgcat::mcset ru "Application Error" "Ошибка в программе" + ::msgcat::mcset ru "&Blue" " &Голубой" + ::msgcat::mcset ru "Cancel" "От&мена" + ::msgcat::mcset ru "&Cancel" "От&мена" ::msgcat::mcset ru "Cannot change to the directory \"%1\$s\".\nPermission denied." \ - "\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \"%1\$s\".\n\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430" - ::msgcat::mcset ru "Choose Directory" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433" - ::msgcat::mcset ru "Cl&ear" "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c" - ::msgcat::mcset ru "Color" "\u0426\u0432\u0435\u0442" - ::msgcat::mcset ru "Console" "\u041a\u043e\u043d\u0441\u043e\u043b\u044c" - ::msgcat::mcset ru "&Copy" "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c" - ::msgcat::mcset ru "Cu&t" "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c" - ::msgcat::mcset ru "&Delete" "\u0423\u0434\u0430\u043b\u0438\u0442\u044c" - ::msgcat::mcset ru "Details >>" "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 >>" - ::msgcat::mcset ru "Directory \"%1\$s\" does not exist." "\u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \"%1\$s\" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442." - ::msgcat::mcset ru "&Directory:" "&\u041a\u0430\u0442\u0430\u043b\u043e\u0433:" - ::msgcat::mcset ru "Error: %1\$s" "\u041e\u0448\u0438\u0431\u043a\u0430: %1\$s" - ::msgcat::mcset ru "E&xit" "\u0412\u044b\u0445\u043e\u0434" + "Не могу перейти в каталог \"%1\$s\".\nНедостаточно прав доступа" + ::msgcat::mcset ru "Choose Directory" "Выберите каталог" + ::msgcat::mcset ru "Cl&ear" "Очистить" + ::msgcat::mcset ru "Color" "Цвет" + ::msgcat::mcset ru "Console" "Консоль" + ::msgcat::mcset ru "&Copy" "Копировать" + ::msgcat::mcset ru "Cu&t" "Вырезать" + ::msgcat::mcset ru "&Delete" "Удалить" + ::msgcat::mcset ru "Details >>" "Подробнее >>" + ::msgcat::mcset ru "Directory \"%1\$s\" does not exist." "Каталога \"%1\$s\" не существует." + ::msgcat::mcset ru "&Directory:" "&Каталог:" + ::msgcat::mcset ru "Error: %1\$s" "Ошибка: %1\$s" + ::msgcat::mcset ru "E&xit" "Выход" ::msgcat::mcset ru "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \ - "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e?" - ::msgcat::mcset ru "File \"%1\$s\" already exists.\n\n" "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\n" - ::msgcat::mcset ru "File \"%1\$s\" does not exist." "\u0424\u0430\u0439\u043b \"%1\$s\" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d." - ::msgcat::mcset ru "File &name:" "&\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430:" - ::msgcat::mcset ru "File &names:" "&\u0418\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432:" - ::msgcat::mcset ru "Files of &type:" "&\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432:" - ::msgcat::mcset ru "Fi&les:" "\u0424\u0430\u0439&\u043b\u044b:" - ::msgcat::mcset ru "&Filter" "&\u0424\u0438\u043b\u044c\u0442\u0440" - ::msgcat::mcset ru "Fil&ter:" "\u0424\u0438\u043b\u044c&\u0442\u0440:" - ::msgcat::mcset ru "&Green" " &\u0417\u0435\u043b\u0435\u043d\u044b\u0439" - ::msgcat::mcset ru "Hi" "\u041f\u0440\u0438\u0432\u0435\u0442" - ::msgcat::mcset ru "&Hide Console" "\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c" - ::msgcat::mcset ru "&Ignore" "&\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c" - ::msgcat::mcset ru "Invalid file name \"%1\$s\"." "\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \"%1\$s\"." - ::msgcat::mcset ru "Log Files" "\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430" - ::msgcat::mcset ru "&No" "&\u041d\u0435\u0442" - ::msgcat::mcset ru "&OK" "&\u041e\u041a" - ::msgcat::mcset ru "OK" "\u041e\u041a" - ::msgcat::mcset ru "Ok" "\u0414\u0430" - ::msgcat::mcset ru "Open" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c" - ::msgcat::mcset ru "&Open" "&\u041e\u0442\u043a\u0440\u044b\u0442\u044c" - ::msgcat::mcset ru "Open Multiple Files" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432" - ::msgcat::mcset ru "P&aste" "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c" - ::msgcat::mcset ru "&Quit" "\u0412\u044b\u0445\u043e\u0434" - ::msgcat::mcset ru "&Red" " &\u041a\u0440\u0430\u0441\u043d\u044b\u0439" - ::msgcat::mcset ru "Replace existing file?" "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b?" - ::msgcat::mcset ru "&Retry" "&\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c" - ::msgcat::mcset ru "&Save" "&\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c" - ::msgcat::mcset ru "Save As" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a" - ::msgcat::mcset ru "Save To Log" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b" - ::msgcat::mcset ru "Select Log File" "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b" - ::msgcat::mcset ru "Select a file to source" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438" + "Файл \"%1\$s\" уже существует.\nЗаменить его?" + ::msgcat::mcset ru "File \"%1\$s\" already exists.\n\n" "Файл \"%1\$s\" уже существует.\n\n" + ::msgcat::mcset ru "File \"%1\$s\" does not exist." "Файл \"%1\$s\" не найден." + ::msgcat::mcset ru "File &name:" "&Имя файла:" + ::msgcat::mcset ru "File &names:" "&Имена файлов:" + ::msgcat::mcset ru "Files of &type:" "&Тип файлов:" + ::msgcat::mcset ru "Fi&les:" "Фай&лы:" + ::msgcat::mcset ru "&Filter" "&Фильтр" + ::msgcat::mcset ru "Fil&ter:" "Филь&тр:" + ::msgcat::mcset ru "&Green" " &Зеленый" + ::msgcat::mcset ru "Hi" "Привет" + ::msgcat::mcset ru "&Hide Console" "Спрятать консоль" + ::msgcat::mcset ru "&Ignore" "&Игнорировать" + ::msgcat::mcset ru "Invalid file name \"%1\$s\"." "Неверное имя файла \"%1\$s\"." + ::msgcat::mcset ru "Log Files" "Файлы журнала" + ::msgcat::mcset ru "&No" "&Нет" + ::msgcat::mcset ru "&OK" "&ОК" + ::msgcat::mcset ru "OK" "ОК" + ::msgcat::mcset ru "Ok" "Да" + ::msgcat::mcset ru "Open" "Открыть" + ::msgcat::mcset ru "&Open" "&Открыть" + ::msgcat::mcset ru "Open Multiple Files" "Открыть несколько файлов" + ::msgcat::mcset ru "P&aste" "Вставить" + ::msgcat::mcset ru "&Quit" "Выход" + ::msgcat::mcset ru "&Red" " &Красный" + ::msgcat::mcset ru "Replace existing file?" "Заменить существующий файл?" + ::msgcat::mcset ru "&Retry" "&Повторить" + ::msgcat::mcset ru "&Save" "&Сохранить" + ::msgcat::mcset ru "Save As" "Сохранить как" + ::msgcat::mcset ru "Save To Log" "Сохранить в журнал" + ::msgcat::mcset ru "Select Log File" "Выбрать журнал" + ::msgcat::mcset ru "Select a file to source" "Выберите файл для интерпретации" ::msgcat::mcset ru "&Selection:" - ::msgcat::mcset ru "Skip Messages" "\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f" - ::msgcat::mcset ru "&Source..." "\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b..." - ::msgcat::mcset ru "Tcl Scripts" "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 TCL" - ::msgcat::mcset ru "Tcl for Windows" "TCL \u0434\u043b\u044f Windows" - ::msgcat::mcset ru "Text Files" "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b" - ::msgcat::mcset ru "&Yes" "&\u0414\u0430" - ::msgcat::mcset ru "abort" "\u043e\u0442\u043c\u0435\u043d\u0430" - ::msgcat::mcset ru "blue" " \u0433\u043e\u043b\u0443\u0431\u043e\u0439" - ::msgcat::mcset ru "cancel" "\u043e\u0442\u043c\u0435\u043d\u0430" - ::msgcat::mcset ru "extension" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435" - ::msgcat::mcset ru "extensions" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f" - ::msgcat::mcset ru "green" " \u0437\u0435\u043b\u0435\u043d\u044b\u0439" - ::msgcat::mcset ru "ignore" "\u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c" - ::msgcat::mcset ru "ok" "\u043e\u043a" - ::msgcat::mcset ru "red" " \u043a\u0440\u0430\u0441\u043d\u044b\u0439" - ::msgcat::mcset ru "retry" "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c" - ::msgcat::mcset ru "yes" "\u0434\u0430" + ::msgcat::mcset ru "Skip Messages" "Пропустить сообщения" + ::msgcat::mcset ru "&Source..." "Интерпретировать файл..." + ::msgcat::mcset ru "Tcl Scripts" "Программа на языке TCL" + ::msgcat::mcset ru "Tcl for Windows" "TCL для Windows" + ::msgcat::mcset ru "Text Files" "Текстовые файлы" + ::msgcat::mcset ru "&Yes" "&Да" + ::msgcat::mcset ru "abort" "отмена" + ::msgcat::mcset ru "blue" " голубой" + ::msgcat::mcset ru "cancel" "отмена" + ::msgcat::mcset ru "extension" "расширение" + ::msgcat::mcset ru "extensions" "расширения" + ::msgcat::mcset ru "green" " зеленый" + ::msgcat::mcset ru "ignore" "пропустить" + ::msgcat::mcset ru "ok" "ок" + ::msgcat::mcset ru "red" " красный" + ::msgcat::mcset ru "retry" "повторить" + ::msgcat::mcset ru "yes" "да" } Index: library/msgs/sv.msg ================================================================== --- library/msgs/sv.msg +++ library/msgs/sv.msg @@ -1,18 +1,18 @@ namespace eval ::tk { ::msgcat::mcset sv "&Abort" "&Avsluta" ::msgcat::mcset sv "&About..." "&Om..." ::msgcat::mcset sv "All Files" "Samtliga filer" ::msgcat::mcset sv "Application Error" "Programfel" - ::msgcat::mcset sv "&Blue" "&Bl\u00e5" + ::msgcat::mcset sv "&Blue" "&Blå" ::msgcat::mcset sv "Cancel" "Avbryt" ::msgcat::mcset sv "&Cancel" "&Avbryt" - ::msgcat::mcset sv "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ej n\u00e5 mappen \"%1\$s\".\nSaknar r\u00e4ttigheter." - ::msgcat::mcset sv "Choose Directory" "V\u00e4lj mapp" + ::msgcat::mcset sv "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ej nå mappen \"%1\$s\".\nSaknar rättigheter." + ::msgcat::mcset sv "Choose Directory" "Välj mapp" ::msgcat::mcset sv "Cl&ear" "&Radera" ::msgcat::mcset sv "&Clear Console" "&Radera konsollen" - ::msgcat::mcset sv "Color" "F\u00e4rg" + ::msgcat::mcset sv "Color" "Färg" ::msgcat::mcset sv "Console" "Konsoll" ::msgcat::mcset sv "&Copy" "&Kopiera" ::msgcat::mcset sv "Cu&t" "Klipp u&t" ::msgcat::mcset sv "&Delete" "&Radera" ::msgcat::mcset sv "Details >>" "Detaljer >>" @@ -20,57 +20,57 @@ ::msgcat::mcset sv "&Directory:" "&Mapp:" ::msgcat::mcset sv "&Edit" "R&edigera" ::msgcat::mcset sv "Error: %1\$s" "Fel: %1\$s" ::msgcat::mcset sv "E&xit" "&Avsluta" ::msgcat::mcset sv "&File" "&Fil" - ::msgcat::mcset sv "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Filen \"%1\$s\" finns redan.\nVill du skriva \u00f6ver den?" + ::msgcat::mcset sv "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Filen \"%1\$s\" finns redan.\nVill du skriva över den?" ::msgcat::mcset sv "File \"%1\$s\" already exists.\n\n" "Filen \"%1\$s\" finns redan.\n\n" ::msgcat::mcset sv "File \"%1\$s\" does not exist." "Filen \"%1\$s\" finns ej." ::msgcat::mcset sv "File &name:" "Fil&namn:" ::msgcat::mcset sv "File &names:" "Fil&namn:" ::msgcat::mcset sv "Files of &type:" "Filer av &typ:" ::msgcat::mcset sv "Fi&les:" "Fi&ler:" ::msgcat::mcset sv "&Filter" ::msgcat::mcset sv "Fil&ter:" - ::msgcat::mcset sv "&Green" "&Gr\u00f6n" - ::msgcat::mcset sv "&Help" "&Hj\u00e4lp" + ::msgcat::mcset sv "&Green" "&Grön" + ::msgcat::mcset sv "&Help" "&Hjälp" ::msgcat::mcset sv "Hi" "Hej" - ::msgcat::mcset sv "&Hide Console" "&G\u00f6m konsollen" + ::msgcat::mcset sv "&Hide Console" "&Göm konsollen" ::msgcat::mcset sv "&Ignore" "&Ignorera" ::msgcat::mcset sv "Invalid file name \"%1\$s\"." "Ogiltigt filnamn \"%1\$s\"." ::msgcat::mcset sv "Log Files" "Loggfiler" ::msgcat::mcset sv "&No" "&Nej" ::msgcat::mcset sv "&OK" ::msgcat::mcset sv "OK" ::msgcat::mcset sv "Ok" - ::msgcat::mcset sv "Open" "\u00d6ppna" - ::msgcat::mcset sv "&Open" "&\u00d6ppna" - ::msgcat::mcset sv "Open Multiple Files" "\u00d6ppna flera filer" + ::msgcat::mcset sv "Open" "Öppna" + ::msgcat::mcset sv "&Open" "&Öppna" + ::msgcat::mcset sv "Open Multiple Files" "Öppna flera filer" ::msgcat::mcset sv "P&aste" "&Klistra in" ::msgcat::mcset sv "&Quit" "&Avsluta" - ::msgcat::mcset sv "&Red" "&R\u00f6d" - ::msgcat::mcset sv "Replace existing file?" "Ers\u00e4tt existerande fil?" - ::msgcat::mcset sv "&Retry" "&F\u00f6rs\u00f6k igen" + ::msgcat::mcset sv "&Red" "&Röd" + ::msgcat::mcset sv "Replace existing file?" "Ersätt existerande fil?" + ::msgcat::mcset sv "&Retry" "&Försök igen" ::msgcat::mcset sv "&Save" "&Spara" ::msgcat::mcset sv "Save As" "Spara som" ::msgcat::mcset sv "Save To Log" "Spara till logg" - ::msgcat::mcset sv "Select Log File" "V\u00e4lj loggfil" - ::msgcat::mcset sv "Select a file to source" "V\u00e4lj k\u00e4llfil" + ::msgcat::mcset sv "Select Log File" "Välj loggfil" + ::msgcat::mcset sv "Select a file to source" "Välj källfil" ::msgcat::mcset sv "&Selection:" "&Val:" - ::msgcat::mcset sv "Skip Messages" "Hoppa \u00f6ver meddelanden" - ::msgcat::mcset sv "&Source..." "&K\u00e4lla..." + ::msgcat::mcset sv "Skip Messages" "Hoppa över meddelanden" + ::msgcat::mcset sv "&Source..." "&Källa..." ::msgcat::mcset sv "Tcl Scripts" "Tcl skript" - ::msgcat::mcset sv "Tcl for Windows" "Tcl f\u00f6r Windows" + ::msgcat::mcset sv "Tcl for Windows" "Tcl för Windows" ::msgcat::mcset sv "Text Files" "Textfiler" ::msgcat::mcset sv "&Yes" "&Ja" ::msgcat::mcset sv "abort" "avbryt" - ::msgcat::mcset sv "blue" "bl\u00e5" + ::msgcat::mcset sv "blue" "blå" ::msgcat::mcset sv "cancel" "avbryt" ::msgcat::mcset sv "extension" "utvidgning" ::msgcat::mcset sv "extensions" "utvidgningar" - ::msgcat::mcset sv "green" "gr\u00f6n" + ::msgcat::mcset sv "green" "grön" ::msgcat::mcset sv "ignore" "ignorera" ::msgcat::mcset sv "ok" - ::msgcat::mcset sv "red" "r\u00f6d" - ::msgcat::mcset sv "retry" "f\u00f6rs\u00f6k igen" + ::msgcat::mcset sv "red" "röd" + ::msgcat::mcset sv "retry" "försök igen" ::msgcat::mcset sv "yes" "ja" } Index: library/tclIndex ================================================================== --- library/tclIndex +++ library/tclIndex @@ -245,9 +245,8 @@ set auto_index(::tk::ListBoxKeyAccel_Set) [list source [file join $dir xmfbox.tcl]] set auto_index(::tk::ListBoxKeyAccel_Unset) [list source [file join $dir xmfbox.tcl]] set auto_index(::tk::ListBoxKeyAccel_Key) [list source [file join $dir xmfbox.tcl]] set auto_index(::tk::ListBoxKeyAccel_Goto) [list source [file join $dir xmfbox.tcl]] set auto_index(::tk::ListBoxKeyAccel_Reset) [list source [file join $dir xmfbox.tcl]] -set auto_index(tk_getFileType) [list source [file join $dir xmfbox.tcl]] set auto_index(::tk::unsupported::ExposePrivateCommand) [list source [file join $dir unsupported.tcl]] set auto_index(::tk::unsupported::ExposePrivateVariable) [list source [file join $dir unsupported.tcl]] set auto_index(::tk::fontchooser) [list source [file join $dir fontchooser.tcl]] Index: library/text.tcl ================================================================== --- library/text.tcl +++ library/text.tcl @@ -35,12 +35,20 @@ #------------------------------------------------------------------------- #------------------------------------------------------------------------- # The code below creates the default class bindings for text widgets. #------------------------------------------------------------------------- + + # Standard Motif bindings: + +bind Text { + if {[tk windowingsystem] eq "aqua"} { + ::tk::RegisterServiceWidget %W + } +} bind Text <1> { tk::TextButton1 %W %x %y %W tag remove sel 0.0 end } @@ -81,10 +89,11 @@ tk::CancelRepeat } bind Text { tk::CancelRepeat } + bind Text { %W mark set insert @%x,%y # An operation that moves the insert mark without making it # one end of the selection must insert an autoseparator if {[%W cget -autoseparators]} { @@ -1203,5 +1212,95 @@ } if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} { $w scan dragto $x $y } } + +# ::tk::TextUndoRedoProcessMarks -- +# +# This proc is executed after an undo or redo action. +# It processes the list of undo/redo marks temporarily set in the +# text widget to positions delimiting where changes happened, and +# returns a flat list of ranges. The temporary marks are removed +# from the text widget. +# +# Arguments: +# w - The text widget + +proc ::tk::TextUndoRedoProcessMarks {w} { + set indices {} + set undoMarks {} + + # only consider the temporary marks set by an undo/redo action + foreach mark [$w mark names] { + if {[string range $mark 0 11] eq "tk::undoMark"} { + lappend undoMarks $mark + } + } + + # transform marks into indices + # the number of undo/redo marks is always even, each right mark + # completes a left mark to give a range + # this is true because: + # - undo/redo only deals with insertions and deletions of text + # - insertions may move marks but not delete them + # - when deleting text, marks located inside the deleted range + # are not erased but moved to the start of the deletion range + # . this is done in TkBTreeDeleteIndexRange ("This segment + # refuses to die...") + # . because MarkDeleteProc does nothing else than returning + # a value indicating that marks are not deleted by this + # deleteProc + # . mark deletion rather happen through [.text mark unset xxx] + # which was not used _up to this point of the code_ (it + # is a bit later just before exiting the present proc) + set nUndoMarks [llength $undoMarks] + set n [expr {$nUndoMarks / 2}] + set undoMarks [lsort -dictionary $undoMarks] + set Lmarks [lrange $undoMarks 0 [expr {$n - 1}]] + set Rmarks [lrange $undoMarks $n [llength $undoMarks]] + foreach Lmark $Lmarks Rmark $Rmarks { + lappend indices [$w index $Lmark] [$w index $Rmark] + $w mark unset $Lmark $Rmark + } + + # process ranges to: + # - remove those already fully included in another range + # - merge overlapping ranges + set ind [lsort -dictionary -stride 2 $indices] + set indices {} + + for {set i 0} {$i < $nUndoMarks} {incr i 2} { + set il1 [lindex $ind $i] + set ir1 [lindex $ind [expr {$i + 1}]] + lappend indices $il1 $ir1 + + for {set j [expr {$i + 2}]} {$j < $nUndoMarks} {incr j 2} { + set il2 [lindex $ind $j] + set ir2 [lindex $ind [expr {$j + 1}]] + + if {[$w compare $il2 > $ir1]} { + # second range starts after the end of first range + # -> further second ranges do not need to be considered + # because ranges were sorted by increasing first index + set j $nUndoMarks + } else { + if {[$w compare $ir2 > $ir1]} { + # second range overlaps first range + # -> merge them into a single range + set indices [lreplace $indices end-1 end] + lappend indices $il1 $ir2 + } else { + # second range is fully included in first range + # -> ignore it + } + # in both cases above, the second range shall be + # trimmed out from the list of ranges + set ind [lreplace $ind $j [expr {$j + 1}]] + incr j -2 + incr nUndoMarks -2 + } + } + } + + return $indices +} Index: library/tk.tcl ================================================================== --- library/tk.tcl +++ library/tk.tcl @@ -9,11 +9,11 @@ # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # Verify that we have Tk binary and script components from the same release -package require -exact Tk 8.6.9 +package require -exact Tk 8.7a2 # Create a ::tk namespace namespace eval ::tk { # Set up the msgcat commands namespace eval msgcat { @@ -674,17 +674,24 @@ } } return $maxlen } -# For now, turn off the custom mdef proc for the mac: +# For now, turn off the custom mdef proc for the Mac: if {[tk windowingsystem] eq "aqua"} { namespace eval ::tk::mac { set useCustomMDEF 0 } } + +#register to send data to macOS Services +if {[tk windowingsystem] eq "aqua"} { +proc ::tk::RegisterServiceWidget {w} { + ::tk::mac::registerServiceWidget $w + } +} # Run the Ttk themed widget set initialization if {$::ttk::library ne ""} { uplevel \#0 [list source $::ttk::library/ttk.tcl] } Index: library/ttk/altTheme.tcl ================================================================== --- library/ttk/altTheme.tcl +++ library/ttk/altTheme.tcl @@ -94,14 +94,12 @@ # Treeview: ttk::style configure Heading -font TkHeadingFont -relief raised ttk::style configure Treeview -background $colors(-window) ttk::style map Treeview \ -background [list disabled $colors(-frame)\ - {!disabled !selected} $colors(-window) \ selected $colors(-selectbg)] \ -foreground [list disabled $colors(-disabledfg) \ - {!disabled !selected} black \ selected $colors(-selectfg)] ttk::style configure TScale \ -groovewidth 4 -troughrelief sunken \ -sliderwidth raised -borderwidth 2 Index: library/ttk/aquaTheme.tcl ================================================================== --- library/ttk/aquaTheme.tcl +++ library/ttk/aquaTheme.tcl @@ -5,51 +5,106 @@ namespace eval ttk::theme::aqua { ttk::style theme settings aqua { ttk::style configure . \ -font TkDefaultFont \ - -background systemWindowBody \ - -foreground systemModelessDialogActiveText \ + -background systemWindowBackgroundColor \ + -foreground systemLabelColor \ -selectbackground systemHighlight \ - -selectforeground systemModelessDialogActiveText \ + -selectforeground systemLabelColor \ -selectborderwidth 0 \ -insertwidth 1 ttk::style map . \ - -foreground {disabled systemModelessDialogInactiveText - background systemModelessDialogInactiveText} \ - -selectbackground {background systemHighlightSecondary - !focus systemHighlightSecondary} \ - -selectforeground {background systemModelessDialogInactiveText - !focus systemDialogActiveText} + -foreground { + disabled systemDisabledControlTextColor + background systemLabelColor} \ + -selectbackground { + background systemSelectedTextBackgroundColor + !focus systemSelectedTextBackgroundColor} \ + -selectforeground { + background systemSelectedTextColor + !focus systemSelectedTextColor} + + # Button + ttk::style configure TButton -anchor center -width -6\ + -foreground systemControlTextColor + ttk::style configure TMenubutton -anchor center -padding {2 0 0 2} + ttk::style configure Toolbutton -anchor center + + # Entry + ttk::style configure TEntry \ + -foreground systemTextColor \ + -background systemTextBackgroundColor \ # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in # disabled buttons even if it did work... ttk::style configure . -stipple {} - ttk::style configure TButton -anchor center -width -6 - ttk::style configure Toolbutton -padding 4 - + # Notebook ttk::style configure TNotebook -tabmargins {10 0} -tabposition n ttk::style configure TNotebook -padding {18 8 18 17} ttk::style configure TNotebook.Tab -padding {12 3 12 2} + ttk::style configure TNotebook.Tab -foreground systemControlTextColor + ttk::style map TNotebook.Tab \ + -foreground { + background systemControlTextColor + disabled systemDisabledControlTextColor + selected systemSelectedTabTextColor} # Combobox: - ttk::style configure TCombobox -postoffset {5 -2 -10 0} + ttk::style configure TCombobox \ + -foreground systemTextColor \ + -background systemTransparent \ + -selectforeground systemSelectedTextColor \ + -selectbackground systemSelectedTextBackgroundColor + ttk::style map TCombobox \ + -foreground { + disabled systemDisabledControlTextColor + } \ + -selectforeground { + !active systemTextColor + } \ + -selectbackground { + !active systemTextBackgroundColor + !focus systemTextBackgroundColor + focus systemSelectedTextBackgroundColor + } + + # Spinbox + ttk::style configure TSpinbox \ + -foreground systemTextColor \ + -background systemTextBackgroundColor \ + -selectforeground systemSelectedTextColor \ + -selectbackground systemSelectedTextBackgroundColor + ttk::style map TSpinbox \ + -foreground { + disabled systemDisabledControlTextColor + } \ + -selectforeground { + !active systemTextColor + } \ + -selectbackground { + !active systemTextBackgroundColor + !focus systemTextBackgroundColor + focus systemSelectedTextBackgroundColor + } # Treeview: - ttk::style configure Heading -font TkHeadingFont - ttk::style configure Treeview -rowheight 18 -background White + ttk::style configure Heading \ + -font TkHeadingFont \ + -foreground systemTextColor \ + -background systemWindowBackgroundColor + ttk::style configure Treeview -rowheight 18 \ + -background systemTextBackgroundColor \ + -foreground systemTextColor \ + -fieldbackground systemTextBackgroundColor ttk::style map Treeview \ - -background [list disabled systemDialogBackgroundInactive \ - {!disabled !selected} systemWindowBody \ - {selected background} systemHighlightSecondary \ - selected systemHighlight] \ - -foreground [list disabled systemModelessDialogInactiveText \ - {!disabled !selected} black \ - selected systemModelessDialogActiveText] + -background { + selected systemSelectedTextBackgroundColor + } # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 # For Aqua, labelframe labels should appear outside the border, Index: library/ttk/button.tcl ================================================================== --- library/ttk/button.tcl +++ library/ttk/button.tcl @@ -6,11 +6,11 @@ # This doesn't seem to be conventional, but it's a nice way # to provide extra feedback while the grab is active. # (If the button is released off the widget, the grab deactivates and # we get a event then, which turns off the "active" state) # -# Normally, and events are +# Normally, and events are # delivered to the widget which received the initial # event. However, Tk [grab]s (#1223103) and menu interactions # (#1222605) can interfere with this. To guard against spurious # events, the binding only sets # the pressed state if the button is currently active. Index: library/ttk/clamTheme.tcl ================================================================== --- library/ttk/clamTheme.tcl +++ library/ttk/clamTheme.tcl @@ -3,11 +3,11 @@ # # Inspired by the XFCE family of Gnome themes. # namespace eval ttk::theme::clam { - variable colors + variable colors array set colors { -disabledfg "#999999" -frame "#dcdad5" -window "#ffffff" -dark "#cfcdc8" @@ -130,14 +130,12 @@ ttk::style configure Heading \ -font TkHeadingFont -relief raised -padding {3} ttk::style configure Treeview -background $colors(-window) ttk::style map Treeview \ -background [list disabled $colors(-frame)\ - {!disabled !selected} $colors(-window) \ selected $colors(-selectbg)] \ -foreground [list disabled $colors(-disabledfg) \ - {!disabled !selected} black \ selected $colors(-selectfg)] ttk::style configure TLabelframe \ -labeloutside true -labelmargins {0 0 0 4} \ -borderwidth 2 -relief raised Index: library/ttk/classicTheme.tcl ================================================================== --- library/ttk/classicTheme.tcl +++ library/ttk/classicTheme.tcl @@ -97,14 +97,12 @@ # Treeview: ttk::style configure Heading -font TkHeadingFont -relief raised ttk::style configure Treeview -background $colors(-window) ttk::style map Treeview \ -background [list disabled $colors(-frame)\ - {!disabled !selected} $colors(-window) \ selected $colors(-selectbg)] \ -foreground [list disabled $colors(-disabledfg) \ - {!disabled !selected} black \ selected $colors(-selectfg)] # # Toolbar buttons: # Index: library/ttk/combobox.tcl ================================================================== --- library/ttk/combobox.tcl +++ library/ttk/combobox.tcl @@ -249,34 +249,20 @@ proc ttk::combobox::UnmapPopdown {w} { [winfo parent $w] state !pressed ttk::releaseGrab $w } -### -# - -namespace eval ::ttk::combobox { - # @@@ Until we have a proper native scrollbar on Aqua, use - # @@@ the regular Tk one. Use ttk::scrollbar on other platforms. - variable scrollbar ttk::scrollbar - if {[tk windowingsystem] eq "aqua"} { - set scrollbar ::scrollbar - } -} - ## PopdownWindow -- # Returns the popdown widget associated with a combobox, # creating it if necessary. # proc ttk::combobox::PopdownWindow {cb} { - variable scrollbar - if {![winfo exists $cb.popdown]} { set poplevel [PopdownToplevel $cb.popdown] set popdown [ttk::frame $poplevel.f -style ComboboxPopdownFrame] - $scrollbar $popdown.sb \ + ttk::scrollbar $popdown.sb \ -orient vertical -command [list $popdown.l yview] listbox $popdown.l \ -listvariable ttk::combobox::Values($cb) \ -yscrollcommand [list $popdown.sb set] \ -exportselection false \ Index: library/ttk/defaults.tcl ================================================================== --- library/ttk/defaults.tcl +++ library/ttk/defaults.tcl @@ -41,11 +41,11 @@ [list disabled $colors(-disabledfg)] ttk::style configure TButton \ -anchor center -padding "3 3" -width -9 \ -relief raised -shiftrelief 1 - ttk::style map TButton -relief [list {!disabled pressed} sunken] + ttk::style map TButton -relief [list {!disabled pressed} sunken] ttk::style configure TCheckbutton \ -indicatorcolor "#ffffff" -indicatorrelief sunken -padding 1 ttk::style map TCheckbutton -indicatorcolor \ [list pressed $colors(-activebg) \ @@ -109,14 +109,12 @@ ttk::style configure Treeview \ -background $colors(-window) \ -foreground $colors(-text) ; ttk::style map Treeview \ -background [list disabled $colors(-frame)\ - {!disabled !selected} $colors(-window) \ selected $colors(-selectbg)] \ -foreground [list disabled $colors(-disabledfg) \ - {!disabled !selected} black \ selected $colors(-selectfg)] # Combobox popdown frame ttk::style layout ComboboxPopdownFrame { ComboboxPopdownFrame.border -sticky nswe Index: library/ttk/entry.tcl ================================================================== --- library/ttk/entry.tcl +++ library/ttk/entry.tcl @@ -55,10 +55,17 @@ # (Plus, who has a Meta key these days?) # : # Another judgment call. If anyone misses this, let me know # and I'll put it back. # + +##Bindings to register with macOS Services API. +bind T.Entry { + if {[tk windowingsystem] eq "aqua"} { + ::tk::RegisterServiceWidget %W + } +} ## Clipboard events: # bind TEntry <> { ttk::entry::Cut %W } bind TEntry <> { ttk::entry::Copy %W } @@ -209,11 +216,10 @@ } ## See $index -- Make sure that the character at $index is visible. # proc ttk::entry::See {w {index insert}} { - update idletasks ;# ensure scroll data up-to-date set c [$w index $index] # @@@ OR: check [$w index left] / [$w index right] if {$c < [$w index @0] || $c >= [$w index @[winfo width $w]]} { $w xview $c } Index: library/ttk/menubutton.tcl ================================================================== --- library/ttk/menubutton.tcl +++ library/ttk/menubutton.tcl @@ -8,11 +8,11 @@ # Keyboard: or accelerator key to post menu # # (In addition, when menu system is active, "dropdown" -- menu posts # on mouse-over. Ttk menubuttons don't implement this). # -# For keyboard and popdown mode, we hand off to tk_popup and let +# For keyboard and popdown mode, we hand off to tk_popup and let # the built-in Tk bindings handle the rest of the interaction. # # ON X11: # # Standard Tk menubuttons use a global grab on the menubutton. @@ -20,17 +20,17 @@ # since we need to process the final event, # and this might be delivered to the menu. So instead we # rely on the passive grab that occurs on events, # and transition to popdown mode when the mouse is released # or dragged outside the menubutton. -# +# # ON WINDOWS: # -# I'm not sure what the hell is going on here. [$menu post] apparently +# I'm not sure what the hell is going on here. [$menu post] apparently # sets up some kind of internal grab for native menus. # On this platform, just use [tk_popup] for all menu actions. -# +# # ON MACOS: # # Same probably applies here. # @@ -59,77 +59,150 @@ bind TMenubutton \ { if {[winfo exists %W]} { %W state !pressed } } } # PostPosition -- -# Returns the x and y coordinates where the menu -# should be posted, based on the menubutton and menu size -# and -direction option. +# Returns x and y coordinates and a menu item index. +# If the index is not an empty string the menu should +# be posted so that the upper left corner of the indexed +# menu item is located at the point (x, y). Otherwise +# the top left corner of the menu itself should be located +# at that point. # # TODO: adjust menu width to be at least as wide as the button # for -direction above, below. # -proc ttk::menubutton::PostPosition {mb menu} { - set x [winfo rootx $mb] - set y [winfo rooty $mb] - set dir [$mb cget -direction] - - set bw [winfo width $mb] - set bh [winfo height $mb] - set mw [winfo reqwidth $menu] - set mh [winfo reqheight $menu] - set sw [expr {[winfo screenwidth $menu] - $bw - $mw}] - set sh [expr {[winfo screenheight $menu] - $bh - $mh}] - - switch -- $dir { - above { if {$y >= $mh} { incr y -$mh } { incr y $bh } } - below { if {$y <= $sh} { incr y $bh } { incr y -$mh } } - left { if {$x >= $mw} { incr x -$mw } { incr x $bw } } - right { if {$x <= $sw} { incr x $bw } { incr x -$mw } } - flush { - # post menu atop menubutton. - # If there's a menu entry whose label matches the - # menubutton -text, assume this is an optionmenu - # and place that entry over the menubutton. - set index [FindMenuEntry $menu [$mb cget -text]] - if {$index ne ""} { - incr y -[$menu yposition $index] - } - } - } - - return [list $x $y] + +if {[tk windowingsystem] eq "aqua"} { + proc ::ttk::menubutton::PostPosition {mb menu} { + set menuPad 5 + set buttonPad 1 + set bevelPad 4 + set mh [winfo reqheight $menu] + set bh [expr {[winfo height $mb]} + $buttonPad] + set bbh [expr {[winfo height $mb]} + $bevelPad] + set mw [winfo reqwidth $menu] + set bw [winfo width $mb] + set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] - $menuPad}] + set entry "" + set entry [::tk::MenuFindName $menu [$mb cget -text]] + if {$entry eq ""} { + set entry 0 + } + set x [winfo rootx $mb] + set y [winfo rooty $mb] + switch [$mb cget -direction] { + above { + set entry "" + incr y [expr {-$mh + 2 * $menuPad}] + } + below { + set entry "" + incr y $bh + } + left { + incr y $menuPad + incr x -$mw + } + right { + incr y $menuPad + incr x $bw + } + default { + incr y $bbh + } + } + return [list $x $y $entry] + } +} else { + proc ::ttk::menubutton::PostPosition {mb menu} { + set mh [expr {[winfo reqheight $menu]}] + set bh [expr {[winfo height $mb]}] + set mw [expr {[winfo reqwidth $menu]}] + set bw [expr {[winfo width $mb]}] + set dF [expr {[winfo width $mb] - [winfo reqwidth $menu]}] + if {[tk windowingsystem] eq "win32"} { + incr mh 6 + incr mw 16 + } + set entry {} + set entry [::tk::MenuFindName $menu [$mb cget -text]] + if {$entry eq {}} { + set entry 0 + } + set x [winfo rootx $mb] + set y [winfo rooty $mb] + switch [$mb cget -direction] { + above { + set entry {} + incr y -$mh + # if we go offscreen to the top, show as 'below' + if {$y < [winfo vrooty $mb]} { + set y [expr {[winfo vrooty $mb] + [winfo rooty $mb]\ + + [winfo reqheight $mb]}] + } + } + below { + set entry {} + incr y $bh + # if we go offscreen to the bottom, show as 'above' + if {($y + $mh) > ([winfo vrooty $mb] + [winfo vrootheight $mb])} { + set y [expr {[winfo vrooty $mb] + [winfo vrootheight $mb] \ + + [winfo rooty $mb] - $mh}] + } + } + left { + incr x -$mw + } + right { + incr x $bw + } + default { + if {[$mb cget -style] eq ""} { + incr x [expr {([winfo width $mb] - \ + [winfo reqwidth $menu])/ 2}] + } else { + incr y $bh + } + } + } + return [list $x $y $entry] + } } # Popdown -- # Post the menu and set a grab on the menu. # proc ttk::menubutton::Popdown {mb} { if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} { return } - foreach {x y} [PostPosition $mb $menu] { break } - tk_popup $menu $x $y + foreach {x y entry} [PostPosition $mb $menu] { break } + tk_popup $menu $x $y $entry } # Pulldown (X11 only) -- # Called when Button1 is pressed on a menubutton. -# Posts the menu; a subsequent ButtonRelease +# Posts the menu; a subsequent ButtonRelease # or Leave event will set a grab on the menu. # proc ttk::menubutton::Pulldown {mb} { variable State if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} { return } - foreach {x y} [PostPosition $mb $menu] { break } set State(pulldown) 1 set State(oldcursor) [$mb cget -cursor] $mb state pressed $mb configure -cursor [$menu cget -cursor] - $menu post $x $y + foreach {x y entry} [PostPosition $mb $menu] { break } + if {$entry ne {}} { + $menu post $x $y $entry + } else { + $menu post $x $y + } tk_menuSetFocus $menu } # TransferGrab (X11 only) -- # Switch from pulldown mode (menubutton has an implicit grab) @@ -141,10 +214,11 @@ $mb configure -cursor $State(oldcursor) $mb state {!pressed !active} set State(pulldown) 0 set menu [$mb cget -menu] + foreach {x y entry} [PostPosition $mb $menu] { break } tk_popup $menu [winfo rootx $menu] [winfo rooty $menu] } } # FindMenuEntry -- Index: library/ttk/notebook.tcl ================================================================== --- library/ttk/notebook.tcl +++ library/ttk/notebook.tcl @@ -68,11 +68,11 @@ } } } # MnemonicTab $nb $key -- -# Scan all tabs in the specified notebook for one with the +# Scan all tabs in the specified notebook for one with the # specified mnemonic. If found, returns path name of tab; # otherwise returns "" # proc ttk::notebook::MnemonicTab {nb key} { set key [string toupper $key] @@ -92,12 +92,12 @@ # enableTraversal -- # Enable keyboard traversal for a notebook widget # by adding bindings to the containing toplevel window. # -# TLNotebooks($top) keeps track of the list of all traversal-enabled -# notebooks contained in the toplevel +# TLNotebooks($top) keeps track of the list of all traversal-enabled +# notebooks contained in the toplevel # proc ttk::notebook::enableTraversal {nb} { variable TLNotebooks set top [winfo toplevel $nb] @@ -143,11 +143,11 @@ set index [lsearch -exact $TLNotebooks($top) $nb] set TLNotebooks($top) [lreplace $TLNotebooks($top) $index $index] } } -# EnclosingNotebook $w -- +# EnclosingNotebook $w -- # Return the nearest traversal-enabled notebook widget # that contains $w. # # BUGS: this only works properly for tabs that are direct children # of the notebook widget. This routine should follow the @@ -169,11 +169,11 @@ return "" } # TLCycleTab -- # toplevel binding procedure for Control-Tab / Control-Shift-Tab -# Select the next/previous tab in the nearest ancestor notebook. +# Select the next/previous tab in the nearest ancestor notebook. # proc ttk::notebook::TLCycleTab {w dir} { set nb [EnclosingNotebook $w] if {$nb ne ""} { CycleTab $nb $dir Index: library/ttk/scrollbar.tcl ================================================================== --- library/ttk/scrollbar.tcl +++ library/ttk/scrollbar.tcl @@ -1,27 +1,9 @@ # # Bindings for TScrollbar widget # -# Still don't have a working ttk::scrollbar under OSX - -# Swap in a [tk::scrollbar] on that platform, -# unless user specifies -class or -style. -# -if {[tk windowingsystem] eq "aqua"} { - rename ::ttk::scrollbar ::ttk::_scrollbar - proc ttk::scrollbar {w args} { - set constructor ::tk::scrollbar - foreach {option _} $args { - if {$option eq "-class" || $option eq "-style"} { - set constructor ::ttk::_scrollbar - break - } - } - return [$constructor $w {*}$args] - } -} - namespace eval ttk::scrollbar { variable State # State(xPress) -- # State(yPress) -- initial position of mouse at start of drag. # State(first) -- value of -first at start of drag. @@ -84,11 +66,11 @@ } proc ttk::scrollbar::Drag {w x y} { variable State if {![info exists State(first)]} { - # Initial buttonpress was not on the thumb, + # Initial buttonpress was not on the thumb, # or something screwy has happened. In either case, ignore: return; } set xDelta [expr {$x - $State(xPress)}] set yDelta [expr {$y - $State(yPress)}] Index: library/ttk/treeview.tcl ================================================================== --- library/ttk/treeview.tcl +++ library/ttk/treeview.tcl @@ -44,11 +44,11 @@ bind Treeview \ { ttk::treeview::Select %W %x %y extend } bind Treeview <> \ { ttk::treeview::Select %W %x %y toggle } -ttk::copyBindings TtkScrollable Treeview +ttk::copyBindings TtkScrollable Treeview ### Binding procedures. # ## Keynav -- Keyboard navigation @@ -203,11 +203,11 @@ variable State $w drag $State(resizeColumn) $x } proc ttk::treeview::resize.release {w x} { - # no-op + $w drop } ### Heading activation. # @@ -334,10 +334,16 @@ } ## Toggle -- toggle opened/closed state of item # proc ttk::treeview::Toggle {w item} { + # don't allow toggling on indicators that + # are not present in front of leaf items + if {[$w children $item] == {}} { + return + } + # not a leaf, toggle! if {[$w item $item -open]} { CloseItem $w $item } else { OpenItem $w $item } Index: library/ttk/ttk.tcl ================================================================== --- library/ttk/ttk.tcl +++ library/ttk/ttk.tcl @@ -120,11 +120,11 @@ # proc ttk::LoadThemes {} { variable library # "default" always present: - uplevel #0 [list source [file join $library defaults.tcl]] + uplevel #0 [list source [file join $library defaults.tcl]] set builtinThemes [style theme names] foreach {theme scripts} { classic classicTheme.tcl alt altTheme.tcl Index: library/ttk/vistaTheme.tcl ================================================================== --- library/ttk/vistaTheme.tcl +++ library/ttk/vistaTheme.tcl @@ -1,11 +1,11 @@ # # Settings for Microsoft Windows Vista and Server 2008 # # The Vista theme can only be defined on Windows Vista and above. The theme -# is created in C due to the need to assign a theme-enabled function for +# is created in C due to the need to assign a theme-enabled function for # detecting when themeing is disabled. On systems that cannot support the # Vista theme, there will be no such theme created and we must not # evaluate this script. if {"vista" ni [ttk::style theme names]} { @@ -46,14 +46,12 @@ # Treeview: ttk::style configure Heading -font TkHeadingFont ttk::style configure Treeview -background SystemWindow ttk::style map Treeview \ -background [list disabled SystemButtonFace \ - {!disabled !selected} SystemWindow \ selected SystemHighlight] \ -foreground [list disabled SystemGrayText \ - {!disabled !selected} SystemWindowText \ selected SystemHighlightText] # Label and Toolbutton ttk::style configure TLabelframe.Label -foreground SystemButtonText @@ -151,11 +149,11 @@ ttk::style map TSpinbox \ -selectbackground [list !focus SystemWindow] \ -selectforeground [list !focus SystemWindowText] \ ; - + # SCROLLBAR elements (Vista includes a state for 'hover') ttk::style element create Vertical.Scrollbar.uparrow vsapi \ SCROLLBAR 1 {disabled 4 pressed 3 active 2 hover 17 {} 1} \ -syssize {SM_CXVSCROLL SM_CYVSCROLL} ttk::style element create Vertical.Scrollbar.downarrow vsapi \ @@ -187,20 +185,21 @@ ttk::style element create Horizontal.Progressbar.pbar vsapi \ PROGRESS 3 {{} 1} -padding 8 ttk::style layout Horizontal.TProgressbar { Horizontal.Progressbar.trough -sticky nswe -children { Horizontal.Progressbar.pbar -side left -sticky ns + Horizontal.Progressbar.text -sticky nesw } } ttk::style element create Vertical.Progressbar.pbar vsapi \ PROGRESS 3 {{} 1} -padding 8 ttk::style layout Vertical.TProgressbar { Vertical.Progressbar.trough -sticky nswe -children { Vertical.Progressbar.pbar -side bottom -sticky we } } - + # Scale ttk::style element create Horizontal.Scale.slider vsapi \ TRACKBAR 3 {disabled 5 focus 4 pressed 3 active 2 {} 1} \ -width 6 -height 12 ttk::style layout Horizontal.TScale { @@ -220,12 +219,12 @@ Vertical.Scale.track -sticky ns Vertical.Scale.slider -side top -sticky {} } } } - + # Treeview ttk::style configure Item -padding {4 0 0 0} - + package provide ttk::theme::vista 1.0 } } Index: library/ttk/winTheme.tcl ================================================================== --- library/ttk/winTheme.tcl +++ library/ttk/winTheme.tcl @@ -72,14 +72,12 @@ # Treeview: ttk::style configure Heading -font TkHeadingFont -relief raised ttk::style configure Treeview -background SystemWindow ttk::style map Treeview \ -background [list disabled SystemButtonFace \ - {!disabled !selected} SystemWindow \ selected SystemHighlight] \ -foreground [list disabled SystemGrayText \ - {!disabled !selected} SystemWindowText \ selected SystemHighlightText] ttk::style configure TProgressbar \ -background SystemHighlight -borderwidth 0 ; } Index: library/ttk/xpTheme.tcl ================================================================== --- library/ttk/xpTheme.tcl +++ library/ttk/xpTheme.tcl @@ -65,12 +65,10 @@ # Treeview: ttk::style configure Heading -font TkHeadingFont -relief raised ttk::style configure Treeview -background SystemWindow ttk::style map Treeview \ -background [list disabled SystemButtonFace \ - {!disabled !selected} SystemWindow \ selected SystemHighlight] \ -foreground [list disabled SystemGrayText \ - {!disabled !selected} SystemWindowText \ selected SystemHighlightText]; } } Index: library/xmfbox.tcl ================================================================== --- library/xmfbox.tcl +++ library/xmfbox.tcl @@ -208,11 +208,10 @@ proc ::tk::MotifFDialog_SetFilter {w type} { upvar ::tk::dialog::file::[winfo name $w] data variable ::tk::Priv set data(filter) [lindex $type 1] - set Priv(selectFileType) [lindex [lindex $type 0] 0] MotifFDialog_Update $w } # ::tk::MotifFDialog_Config -- @@ -979,11 +978,5 @@ variable ::tk::Priv unset -nocomplain Priv(lbAccel,$w) } -proc ::tk_getFileType {} { - variable ::tk::Priv - - return $Priv(selectFileType) -} - Index: macosx/GNUmakefile ================================================================== --- macosx/GNUmakefile +++ macosx/GNUmakefile @@ -100,11 +100,11 @@ PROJECT := tk PRODUCT_NAME := Tk UNIX_DIR := ${CURDIR}/../unix -VERSION := $(shell awk -F= '/^TK_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.in) +VERSION := $(shell awk -F= '/^TK_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.ac) TCL_VERSION := ${VERSION} wish := wish WISH = wish${VERSION} BUILD_TARGET := all tktest @@ -178,11 +178,11 @@ ${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \ ${UNIX_DIR}/tkConfig.sh.in Tk-Info.plist.in Wish-Info.plist.in mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \ if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \ --prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \ - --mandir="${MANDIR}" --enable-threads --enable-framework \ + --mandir="${MANDIR}" --enable-framework \ --with-tcl="${TCL_DIR}" \ ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi ifneq (${VERSION},${TCL_VERSION}) @cd "${OBJ_DIR}" && sed -e 's#/Versions/${TCL_VERSION}#/Versions/${VERSION}#' \ tkConfig.sh > tkConfig.sh.1 && mv -f tkConfig.sh.1 tkConfig.sh Index: macosx/README ================================================================== --- macosx/README +++ macosx/README @@ -24,11 +24,11 @@ 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. +aqua widgets and look&feel, and TkX11 using the traditional unix X11 widgets. 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. @@ -57,15 +57,10 @@ Given a potential package directory $pkg, Tcl on OSX checks for the file $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). - - 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. @@ -85,32 +80,10 @@ LaunchServices) than when it (or tclsh) is invoked from the Terminal, in particular PATH may not be what you expect. (Wish started by LaunchServices inherits loginwindow's environment variables, which are essentially those set in $HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell). -- TkAqua drawing is antialiased by default, but (outline) linewidth can be used -to control whether a line/shape is drawn antialiased. The antialiasing threshold -is 0 by default (i.e. antialias everything), it can be changed by setting - set tk::mac::CGAntialiasLimit -in your script before drawing, in which case lines (or shapes with outlines) -thinner than pixels will not be antialiased. - -- Text antialiasing by default uses the standard OS antialising settings. -Setting the global variable '::tk::mac::antialiasedtext' allows to control text -antialiasing from Tcl: a value of 1 enables AA, 0 disables AA and -1 restores -the default behaviour of respecting the OS settings. - -- Scrollbars: There are two scrollbar variants in Aqua, normal & small. The -normal scrollbar has a small dimension of 15, the small variant 11. -Access to the small variant was added in Tk 8.4.2. - -- The default metrics of native buttons, radiobuttons, checkboxes and -menubuttons in the Cocoa-based Tk 8.5.7 and later preserve compatibility with -the older Carbon-based implementation, you can turn off the compatibility -metrics to get more native-looking spacing by setting: - set tk::mac::useCompatibilityMetrics 0 - - TkAqua provides access to native OS X images via the Tk native bitmap facility (including any image file readable by NSImage). A native bitmap name is interpreted as follows (in order): - predefined builtin 32x32 icon name (stop, caution, document, etc) - name defined by [tk::mac::iconBitmap] @@ -182,14 +155,31 @@ Note that not all attributes are valid for all window classes. Support for the 3 argument form was added with the Cocoa-based Tk 8.5.7, at the same time support for some legacy Carbon-specific classes and attributes was removed (they are still accepted by the command but no longer have any effect). -- Another command available in the tk::unsupported::MacWindowStyle namespace is -tk::unsupported::MacWindowStyle tabbingid window ?newId? which can be used to -get or set the tabbingIdentifier for the NSWindow associated with a Tk Window. -See section 3 for details. +- Another command available in the tk::unsupported::MacWindowStyle namespace is: + tk::unsupported::MacWindowStyle tabbingid window ?newId? +which can be used to get or set the tabbingIdentifier for the NSWindow +associated with a Tk Window. See section 3 for details. + +- The command: + tk::unsupported::MacWindowStyle appearance window ?newAppearance? +is available when Tk is built and run on macOS 10.14 (Mojave) or later. In +that case the Ttk widgets all support the "Dark Mode" appearance which was +introduced in 10.14. The command accepts the following values for the optional +newAppearance option: "aqua", "darkaqua", or "auto". If the appearance is set +to aqua or darkaqua then the window will be displayed with the corresponding +appearance independent of any preferences settings. If it is set to "auto" +the appearance will be determined by the preferences. This command can be +used to opt out of Dark Mode on a per-window basis. + +- To determine the current appearance of a window in macOS 10.14 (Mojave) and +higher, one can use the command: + tk::unsupported::MacWindowStyle isdark +The boolean return value is true if the window is currently displayed with the +dark appearance. - 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. @@ -273,17 +263,55 @@ unique tabbingIdentifier. This is independent of any preferences setting. To ensure that we maintain consistency, changing the tabbingIdentifier of a window which is already displayed as a tab will also cause it to become a separate window. +4. Ttk, Dark Mode and semantic colors +--------------------------------------- + +With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua +appearance. Part of the implementation of the Dark Mode was to make +some of the named NSColors have dynamic values. Apple calls these +"semantic colors" because the name does not specify a specific color, +but rather refers to the context in which the color should be used. +Tk now provides the following semantic colors as system colors: +systemTextColor, systemTextBackgroundColor, systemSelectedTextColor, +systemSelectedTextBackgroundColor, systemControlTextColor, +systemDisabledControlTextColor, systemLabelColor, and +systemControlAccentColor. All of these except the last two were +present in OSX 10.0 (and those two are simulated in systems where they +do not exist). The change in 10.14 was that the RGB color value of +these colors became dynamic, meaning that the color value can change +when the application appearance changes. In particular, when a user +selects Dark Mode in the system preferences these colors change +appearance. For example systemTextColor is dark in Aqua and light in +DarkAqua. One additional color, systemSelectedTabTextColor, does not +exist in macOS but is used by Tk to match the different colors used +for Notebook tab text in different OS versions. + +The default background and foreground colors of most of the Tk widgets +have been set to semantic colors, which means that the widgets will change +appearance, and remain usable, when Dark Mode is selected in the system +preferences. However, to get a close match to the native Dark Mode style it +is recommended to use Ttk widgets when possible. + +Apple's tab view and GroupBox objects delimit their content by +displaying it within a rounded rectangle with a background color that +contrasts with the background of the containing object. This means +that the background color of a Ttk widget depends on how deeply it is +nested inside of other widgets that use contrasting backgrounds. To +support this, there are 8 contrasting system colors named +systemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7. +The systemWindowBackgroundColor is the standard background for a +dialog window and the others match the contrasting background colors +used in ttk::notebooks and ttk::labelframes which are nested to the +corresponding depth. -4. Building Tcl/Tk on macOS +5. Building Tcl/Tk on macOS ------------------------------ -- At least macOS 10.3 is required to build Tcl and TkX11, and macOS 10.6 -is required to build TkAqua. The XCode application provides everything -needed to build Tk, but it is not necessary to install the full XCode. +- macOS 10.6 is required to build TkAqua and TkX11. The XCode application provides everything needed to build Tk, but it is not necessary to install the full XCode. It suffices to install the Command Line Tools package, which can be done by running the command: xcode-select --install - Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in @@ -338,21 +366,10 @@ 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. - - To enable weak-linking, set the MACOSX_DEPLOYMENT_TARGET environment variable to the minimal OS version the binaries should be able to run on, e.g: export MACOSX_DEPLOYMENT_TARGET=10.6 This requires at least gcc 3.1; with gcc 4 or later, set/add to CFLAGS instead: export CFLAGS="-mmacosx-version-min=10.6" @@ -471,11 +488,11 @@ 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. +discussed in 5.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 @@ -504,11 +521,11 @@ 5.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 +NSAutoreleasePool* property is added to the TkApplication subclass of NSApplication. The TkpInit function calls [NSApp _setup] which initializes this property by creating an NSAutoreleasePool prior to calling [NSApp finishLaunching]. This mimics the behavior of the [NSApp run] method, which calls [NSApp finishLaunching] just before starting the event loop. @@ -529,11 +546,11 @@ 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 +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). 5.3 Clipping regions and "ghost windows" @@ -549,11 +566,11 @@ 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 +parent window. Much of the code in tkMacOSXSubwindows.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 @@ -653,5 +670,56 @@ that casts all window frames and menus as black. Tk 8.6.9 has added two virtual events, <> and <>, to allow you to update your Tk app's appearance when the system appearance changes. Just bind your appearance-updating code to these virtual events and you will see it triggered when the system appearance toggles between dark and light. + +7.0 Mac Services +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With 8.6.10, Tk supports the Mac's NSServices API, documented at +https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1 +and in TIP 536 and Tk's man page. Tk presents a simple, +straightforward API to implement the Services functionality. + +The Tk implementation of the NSServices API is intended for standalone +applications, such as one wrapped by the standalone version of Wish +and re-named into a different application. In particular such an +application would specify its own unique CFBundleIdentifier in its +Info.plist file. During development, however, if Wish itself is being +used as the receiver, it may be necessary to take some care to ensure +that the correct version of Wish.app is available as a receiver of +NSServices data. + +When one macOS app uses NSServices to send data to another app that is +not running, LaunchServices will launch the receiver. LaunchServices +assumes that the CFBundleIdentifier uniquely identifies an app among +all of the apps installed on a system. But this may not be the case +for Wish.app if, for example, you have compiled Tk from source at some +time in the past. In that case the Tk build directory will contain +its own copy of Wish.app that will be visible to LaunchServices. It +may be necessary when testing your app to take some steps to ensure +that LaunchServices is launching the correct Wish.app. Instructions +for doing this are provided below. + +The command line tool which manages the LaunchServices database has +an amazingly unwieldy path name. So, first, run this command: + +alias lsregister='/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister' + +Then you can reset the LaunchServices database like this: + +$ lsregister -kill +$ lsregister -seed + +To find out which versions of Wish.app have been located by +LaunchServices, run: + +$ lsregister -dump | grep path | grep Wish + +If more than one version of Wish is showing up in this list, eliminate +all of the unintended targets by running + +lsregister -u /path/to/bad/Wish.app + +Continue this until only the correct version of Wish shows up in the +list. Index: macosx/Tk-Common.xcconfig ================================================================== --- macosx/Tk-Common.xcconfig +++ macosx/Tk-Common.xcconfig @@ -34,13 +34,13 @@ LIBDIR = $(PREFIX)/lib MANDIR = $(PREFIX)/man PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc) PREFIX = /usr/local TCL_BUILD_DIR = $(OBJROOT)/../tcl/Tcl.build/$(CONFIGURATION)/Tcl.build/Objects -TCL_CONFIGURE_ARGS = --enable-threads --enable-dtrace +TCL_CONFIGURE_ARGS = --enable-dtrace TCL_FRAMEWORK_DIR = $(SYMROOT)/../tcl/$(CONFIGURATION) TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION) TCL_PACKAGE_PATH = "$(LIBDIR)" TCL_DEFS = HAVE_TCL_CONFIG_H TK_LIBRARY = $(LIBDIR)/tk$(VERSION) -TK_DEFS = HAVE_TK_CONFIG_H -VERSION = 8.6 +TK_DEFS = HAVE_TK_CONFIG_H TCL_NO_DEPRECATED +VERSION = 8.7 Index: macosx/Tk.xcode/project.pbxproj ================================================================== --- macosx/Tk.xcode/project.pbxproj +++ macosx/Tk.xcode/project.pbxproj @@ -1170,11 +1170,11 @@ F966BC6808F27A3D005CB29B /* winWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winWm.test; sourceTree = ""; }; F966BC6908F27A3D005CB29B /* wm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = wm.test; sourceTree = ""; }; F966BC6A08F27A3D005CB29B /* xmfbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.test; sourceTree = ""; }; F966BC6C08F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F966BC6D08F27A3D005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F966BC6E08F27A3D005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F966BC6E08F27A3D005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F966BC6F08F27A3D005CB29B /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; F966BC7008F27A3D005CB29B /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = ""; }; F966BC7108F27A3D005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F966BC7208F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F966BC7308F27A3D005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; @@ -1209,20 +1209,18 @@ F966BC9008F27A3D005CB29B /* tkUnixWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixWm.c; sourceTree = ""; }; F966BC9108F27A3D005CB29B /* tkUnixXId.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixXId.c; sourceTree = ""; }; F966BC9408F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F966BC9508F27A3D005CB29B /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = ""; }; F966BC9608F27A3E005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F966BC9708F27A3E005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F966BC9708F27A3E005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F966BC9908F27A3E005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F966BC9A08F27A3E005CB29B /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = ""; }; - F966BC9B08F27A3E005CB29B /* mkd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mkd.bat; sourceTree = ""; }; F966BC9C08F27A3E005CB29B /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = ""; }; F966BCEE08F27A3E005CB29B /* tk.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.rc; sourceTree = ""; }; F966BCEF08F27A3E005CB29B /* tk_base.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk_base.rc; sourceTree = ""; }; F966BCF208F27A3E005CB29B /* wish.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wish.rc; sourceTree = ""; }; F966BCF308F27A3E005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; - F966BCF408F27A3E005CB29B /* rmd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rmd.bat; sourceTree = ""; }; F966BCF508F27A3F005CB29B /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = ""; }; F966BCF608F27A3F005CB29B /* stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stubs.c; sourceTree = ""; }; F966BCF708F27A3F005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; F966BCF808F27A3F005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = ""; }; F966BCF908F27A3F005CB29B /* tkWin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWin.h; sourceTree = ""; }; @@ -1913,11 +1911,11 @@ F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = ""; }; F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = ""; }; F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = ""; }; F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = ""; }; F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F96D43D308F272B8004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = ""; }; F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = ""; }; F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = ""; }; F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = ""; }; F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = ""; }; @@ -1938,11 +1936,11 @@ F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = ""; }; F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = ""; }; F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = ""; }; F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F96D444208F272B9004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = ""; }; F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = ""; }; F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = ""; }; F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = ""; }; @@ -1982,11 +1980,11 @@ F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = ""; }; F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = ""; }; F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = ""; }; F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F96D447508F272BA004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = ""; }; F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = ""; }; F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = ""; }; @@ -2738,11 +2736,11 @@ F966BC6B08F27A3D005CB29B /* unix */ = { isa = PBXGroup; children = ( F966BC6C08F27A3D005CB29B /* aclocal.m4 */, F966BC6D08F27A3D005CB29B /* configure */, - F966BC6E08F27A3D005CB29B /* configure.in */, + F966BC6E08F27A3D005CB29B /* configure.ac */, F966BC6F08F27A3D005CB29B /* install-sh */, F966BC7008F27A3D005CB29B /* installManPage */, F966BC7108F27A3D005CB29B /* Makefile.in */, F966BC7208F27A3D005CB29B /* README */, F966BC7308F27A3D005CB29B /* tcl.m4 */, @@ -2785,14 +2783,13 @@ isa = PBXGroup; children = ( F966BC9408F27A3D005CB29B /* aclocal.m4 */, F966BC9508F27A3D005CB29B /* buildall.vc.bat */, F966BC9608F27A3E005CB29B /* configure */, - F966BC9708F27A3E005CB29B /* configure.in */, + F966BC9708F27A3E005CB29B /* configure.ac */, F966BC9908F27A3E005CB29B /* Makefile.in */, F966BC9A08F27A3E005CB29B /* makefile.vc */, - F966BC9B08F27A3E005CB29B /* mkd.bat */, F966BC9C08F27A3E005CB29B /* nmakehlp.c */, F966BC9D08F27A3E005CB29B /* rc */, F966BCF308F27A3E005CB29B /* README */, F966BCF408F27A3E005CB29B /* rmd.bat */, F966BCF508F27A3F005CB29B /* rules.vc */, @@ -3720,11 +3717,11 @@ F96D43D008F272B8004A47F5 /* tools */ = { isa = PBXGroup; children = ( F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */, F96D43D208F272B8004A47F5 /* configure */, - F96D43D308F272B8004A47F5 /* configure.in */, + F96D43D308F272B8004A47F5 /* configure.ac */, F96D442208F272B8004A47F5 /* eolFix.tcl */, F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */, F96D442508F272B8004A47F5 /* genStubs.tcl */, F96D442708F272B8004A47F5 /* index.tcl */, F96D442808F272B8004A47F5 /* installData.tcl */, @@ -3753,11 +3750,11 @@ F96D443E08F272B9004A47F5 /* unix */ = { isa = PBXGroup; children = ( F96D444008F272B9004A47F5 /* aclocal.m4 */, F96D444108F272B9004A47F5 /* configure */, - F96D444208F272B9004A47F5 /* configure.in */, + F96D444208F272B9004A47F5 /* configure.ac */, F96D444308F272B9004A47F5 /* dltest */, F96D444D08F272B9004A47F5 /* install-sh */, F96D444E08F272B9004A47F5 /* installManPage */, F96D444F08F272B9004A47F5 /* ldAix */, F96D445008F272B9004A47F5 /* Makefile.in */, @@ -3814,11 +3811,11 @@ children = ( F96D447008F272BA004A47F5 /* aclocal.m4 */, F96D447108F272BA004A47F5 /* buildall.vc.bat */, F96D447208F272BA004A47F5 /* cat.c */, F96D447408F272BA004A47F5 /* configure */, - F96D447508F272BA004A47F5 /* configure.in */, + F96D447508F272BA004A47F5 /* configure.ac */, F96D447708F272BA004A47F5 /* Makefile.in */, F96D447808F272BA004A47F5 /* makefile.vc */, F96D447908F272BA004A47F5 /* nmakehlp.c */, F96D447A08F272BA004A47F5 /* README */, F96D447C08F272BA004A47F5 /* rules.vc */, @@ -3966,11 +3963,11 @@ buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TCL_SRCROOT)/macosx/configure.ac", - "$(TCL_SRCROOT)/unix/configure.in", + "$(TCL_SRCROOT)/unix/configure.ac", "$(TCL_SRCROOT)/unix/tcl.m4", "$(TCL_SRCROOT)/unix/aclocal.m4", "$(TCL_SRCROOT)/unix/tclConfig.sh.in", "$(TCL_SRCROOT)/unix/Makefile.in", "$(TCL_SRCROOT)/unix/dltest/Makefile.in", @@ -3979,21 +3976,21 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; + shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; F9A5C5F608F651AB008AE941 /* Configure Tk */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TK_SRCROOT)/macosx/configure.ac", - "$(TK_SRCROOT)/unix/configure.in", + "$(TK_SRCROOT)/unix/configure.ac", "$(TK_SRCROOT)/unix/tcl.m4", "$(TK_SRCROOT)/unix/aclocal.m4", "$(TK_SRCROOT)/unix/tkConfig.sh.in", ); name = "Configure Tk"; @@ -4000,21 +3997,21 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tk/tkConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; + shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; F9FD30B40CC1AD070073837D /* Configure Tcl */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TCL_SRCROOT)/macosx/configure.ac", - "$(TCL_SRCROOT)/unix/configure.in", + "$(TCL_SRCROOT)/unix/configure.ac", "$(TCL_SRCROOT)/unix/tcl.m4", "$(TCL_SRCROOT)/unix/aclocal.m4", "$(TCL_SRCROOT)/unix/tclConfig.sh.in", "$(TCL_SRCROOT)/unix/Makefile.in", "$(TCL_SRCROOT)/unix/dltest/Makefile.in", @@ -4023,21 +4020,21 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; + shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; F9FD30B50CC1AD070073837D /* Configure Tk */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TK_SRCROOT)/macosx/configure.ac", - "$(TK_SRCROOT)/unix/configure.in", + "$(TK_SRCROOT)/unix/configure.ac", "$(TK_SRCROOT)/unix/tcl.m4", "$(TK_SRCROOT)/unix/aclocal.m4", "$(TK_SRCROOT)/unix/tkConfig.sh.in", ); name = "Configure Tk"; @@ -4044,11 +4041,11 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tk/tkConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi"; + shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ Index: macosx/Tk.xcodeproj/project.pbxproj ================================================================== --- macosx/Tk.xcodeproj/project.pbxproj +++ macosx/Tk.xcodeproj/project.pbxproj @@ -1170,11 +1170,11 @@ F966BC6808F27A3D005CB29B /* winWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winWm.test; sourceTree = ""; }; F966BC6908F27A3D005CB29B /* wm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = wm.test; sourceTree = ""; }; F966BC6A08F27A3D005CB29B /* xmfbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.test; sourceTree = ""; }; F966BC6C08F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F966BC6D08F27A3D005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F966BC6E08F27A3D005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F966BC6E08F27A3D005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F966BC6F08F27A3D005CB29B /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; F966BC7008F27A3D005CB29B /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = ""; }; F966BC7108F27A3D005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F966BC7208F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F966BC7308F27A3D005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; @@ -1209,20 +1209,18 @@ F966BC9008F27A3D005CB29B /* tkUnixWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixWm.c; sourceTree = ""; }; F966BC9108F27A3D005CB29B /* tkUnixXId.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixXId.c; sourceTree = ""; }; F966BC9408F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F966BC9508F27A3D005CB29B /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = ""; }; F966BC9608F27A3E005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F966BC9708F27A3E005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F966BC9708F27A3E005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F966BC9908F27A3E005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F966BC9A08F27A3E005CB29B /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = ""; }; - F966BC9B08F27A3E005CB29B /* mkd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mkd.bat; sourceTree = ""; }; F966BC9C08F27A3E005CB29B /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = ""; }; F966BCEE08F27A3E005CB29B /* tk.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.rc; sourceTree = ""; }; F966BCEF08F27A3E005CB29B /* tk_base.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk_base.rc; sourceTree = ""; }; F966BCF208F27A3E005CB29B /* wish.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wish.rc; sourceTree = ""; }; F966BCF308F27A3E005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; - F966BCF408F27A3E005CB29B /* rmd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rmd.bat; sourceTree = ""; }; F966BCF508F27A3F005CB29B /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = ""; }; F966BCF608F27A3F005CB29B /* stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stubs.c; sourceTree = ""; }; F966BCF708F27A3F005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; F966BCF808F27A3F005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = ""; }; F966BCF908F27A3F005CB29B /* tkWin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWin.h; sourceTree = ""; }; @@ -1913,11 +1911,11 @@ F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = ""; }; F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = ""; }; F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = ""; }; F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = ""; }; F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F96D43D308F272B8004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = ""; }; F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = ""; }; F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = ""; }; F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = ""; }; F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = ""; }; @@ -1938,11 +1936,11 @@ F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = ""; }; F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = ""; }; F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = ""; }; F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F96D444208F272B9004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = ""; }; F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = ""; }; F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = ""; }; F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = ""; }; @@ -1982,11 +1980,11 @@ F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = ""; }; F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = ""; }; F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = ""; }; F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; + F96D447508F272BA004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = ""; }; F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = ""; }; F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = ""; }; F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = ""; }; @@ -2738,11 +2736,11 @@ F966BC6B08F27A3D005CB29B /* unix */ = { isa = PBXGroup; children = ( F966BC6C08F27A3D005CB29B /* aclocal.m4 */, F966BC6D08F27A3D005CB29B /* configure */, - F966BC6E08F27A3D005CB29B /* configure.in */, + F966BC6E08F27A3D005CB29B /* configure.ac */, F966BC6F08F27A3D005CB29B /* install-sh */, F966BC7008F27A3D005CB29B /* installManPage */, F966BC7108F27A3D005CB29B /* Makefile.in */, F966BC7208F27A3D005CB29B /* README */, F966BC7308F27A3D005CB29B /* tcl.m4 */, @@ -2785,18 +2783,16 @@ isa = PBXGroup; children = ( F966BC9408F27A3D005CB29B /* aclocal.m4 */, F966BC9508F27A3D005CB29B /* buildall.vc.bat */, F966BC9608F27A3E005CB29B /* configure */, - F966BC9708F27A3E005CB29B /* configure.in */, + F966BC9708F27A3E005CB29B /* configure.ac */, F966BC9908F27A3E005CB29B /* Makefile.in */, F966BC9A08F27A3E005CB29B /* makefile.vc */, - F966BC9B08F27A3E005CB29B /* mkd.bat */, F966BC9C08F27A3E005CB29B /* nmakehlp.c */, F966BC9D08F27A3E005CB29B /* rc */, F966BCF308F27A3E005CB29B /* README */, - F966BCF408F27A3E005CB29B /* rmd.bat */, F966BCF508F27A3F005CB29B /* rules.vc */, F966BCF608F27A3F005CB29B /* stubs.c */, F966BCF708F27A3F005CB29B /* tcl.m4 */, F966BCF808F27A3F005CB29B /* tkConfig.sh.in */, F966BCF908F27A3F005CB29B /* tkWin.h */, @@ -3720,11 +3716,11 @@ F96D43D008F272B8004A47F5 /* tools */ = { isa = PBXGroup; children = ( F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */, F96D43D208F272B8004A47F5 /* configure */, - F96D43D308F272B8004A47F5 /* configure.in */, + F96D43D308F272B8004A47F5 /* configure.ac */, F96D442208F272B8004A47F5 /* eolFix.tcl */, F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */, F96D442508F272B8004A47F5 /* genStubs.tcl */, F96D442708F272B8004A47F5 /* index.tcl */, F96D442808F272B8004A47F5 /* installData.tcl */, @@ -3753,11 +3749,11 @@ F96D443E08F272B9004A47F5 /* unix */ = { isa = PBXGroup; children = ( F96D444008F272B9004A47F5 /* aclocal.m4 */, F96D444108F272B9004A47F5 /* configure */, - F96D444208F272B9004A47F5 /* configure.in */, + F96D444208F272B9004A47F5 /* configure.ac */, F96D444308F272B9004A47F5 /* dltest */, F96D444D08F272B9004A47F5 /* install-sh */, F96D444E08F272B9004A47F5 /* installManPage */, F96D444F08F272B9004A47F5 /* ldAix */, F96D445008F272B9004A47F5 /* Makefile.in */, @@ -3814,11 +3810,11 @@ children = ( F96D447008F272BA004A47F5 /* aclocal.m4 */, F96D447108F272BA004A47F5 /* buildall.vc.bat */, F96D447208F272BA004A47F5 /* cat.c */, F96D447408F272BA004A47F5 /* configure */, - F96D447508F272BA004A47F5 /* configure.in */, + F96D447508F272BA004A47F5 /* configure.ac */, F96D447708F272BA004A47F5 /* Makefile.in */, F96D447808F272BA004A47F5 /* makefile.vc */, F96D447908F272BA004A47F5 /* nmakehlp.c */, F96D447A08F272BA004A47F5 /* README */, F96D447C08F272BA004A47F5 /* rules.vc */, @@ -3969,11 +3965,11 @@ buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TCL_SRCROOT)/macosx/configure.ac", - "$(TCL_SRCROOT)/unix/configure.in", + "$(TCL_SRCROOT)/unix/configure.ac", "$(TCL_SRCROOT)/unix/tcl.m4", "$(TCL_SRCROOT)/unix/aclocal.m4", "$(TCL_SRCROOT)/unix/tclConfig.sh.in", "$(TCL_SRCROOT)/unix/Makefile.in", "$(TCL_SRCROOT)/unix/dltest/Makefile.in", @@ -3982,21 +3978,21 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; + shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; F9A5C5F608F651AB008AE941 /* Configure Tk */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TK_SRCROOT)/macosx/configure.ac", - "$(TK_SRCROOT)/unix/configure.in", + "$(TK_SRCROOT)/unix/configure.ac", "$(TK_SRCROOT)/unix/tcl.m4", "$(TK_SRCROOT)/unix/aclocal.m4", "$(TK_SRCROOT)/unix/tkConfig.sh.in", ); name = "Configure Tk"; @@ -4003,21 +3999,21 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tk/tkConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; + shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; F9FD30B40CC1AD070073837D /* Configure Tcl */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TCL_SRCROOT)/macosx/configure.ac", - "$(TCL_SRCROOT)/unix/configure.in", + "$(TCL_SRCROOT)/unix/configure.ac", "$(TCL_SRCROOT)/unix/tcl.m4", "$(TCL_SRCROOT)/unix/aclocal.m4", "$(TCL_SRCROOT)/unix/tclConfig.sh.in", "$(TCL_SRCROOT)/unix/Makefile.in", "$(TCL_SRCROOT)/unix/dltest/Makefile.in", @@ -4026,21 +4022,21 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; + shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; F9FD30B50CC1AD070073837D /* Configure Tk */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TK_SRCROOT)/macosx/configure.ac", - "$(TK_SRCROOT)/unix/configure.in", + "$(TK_SRCROOT)/unix/configure.ac", "$(TK_SRCROOT)/unix/tcl.m4", "$(TK_SRCROOT)/unix/aclocal.m4", "$(TK_SRCROOT)/unix/tkConfig.sh.in", ); name = "Configure Tk"; @@ -4047,11 +4043,11 @@ outputPaths = ( "$(DERIVED_FILE_DIR)/tk/tkConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi"; + shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tk/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tk\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ Index: macosx/Wish-Info.plist.in ================================================================== --- macosx/Wish-Info.plist.in +++ macosx/Wish-Info.plist.in @@ -34,10 +34,23 @@ CFBundleTypeRole Viewer + CFBundleURLTypes + + + CFBundleTypeRole + Viewer + CFBundleURLSchemes + + foo + + CFBundleURLName + Get Foo + + CFBundleExecutable Wish CFBundleGetInfoString Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@, Copyright © 1989-@TK_YEAR@ Tcl Core Team, @@ -76,7 +89,28 @@ OSAScriptingDefinition Wish.sdef NSHighResolutionCapable True + NSServices + + + NSMenuItem + + default + Wish: Display Test Data + + NSMessage + provideService + NSPortName + Wish + + NSSendTypes + + NSStringPboardType + NSPasteboardTypeString + + + + Index: macosx/Wish.sdef ================================================================== --- macosx/Wish.sdef +++ macosx/Wish.sdef @@ -26,10 +26,19 @@ + + + + + + + + Index: macosx/configure.ac ================================================================== --- macosx/configure.ac +++ macosx/configure.ac @@ -6,6 +6,6 @@ dnl Ensure that the config (auto)headers support is used, then just dnl include the configure sources from ../unix: m4_include(../unix/aclocal.m4) m4_define(SC_USE_CONFIG_HEADERS) -m4_include(../unix/configure.in) +m4_include(../unix/configure.ac) Index: macosx/tkMacOSXBitmap.c ================================================================== --- macosx/tkMacOSXBitmap.c +++ macosx/tkMacOSXBitmap.c @@ -47,10 +47,13 @@ {NULL} }; #define builtInIconSize 32 +#define OSTYPE_TO_UTI(x) (NSString *)UTTypeCreatePreferredIdentifierForTag( \ + kUTTagClassOSType, UTCreateStringForOSType(x), nil) + static Tcl_HashTable iconBitmapTable = {}; typedef struct { int kind, width, height; char *value; } IconBitmap; @@ -105,49 +108,54 @@ predefPtr->native = 1; Tcl_SetHashValue(predefHashPtr, predefPtr); } } } + /* *---------------------------------------------------------------------- * - * GetBitmapForIcon -- + * PixmapFromImage -- * * Results: - * Bitmap for the given IconRef. + * Returns a Pixmap with an NSImage drawn into it. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Pixmap -GetBitmapForIcon( +PixmapFromImage( Display *display, - IconRef icon, + NSImage* image, CGSize size) { TkMacOSXDrawingContext dc; Pixmap pixmap; pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0); if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) { if (dc.context) { - const CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, - .tx = 0, .ty = size.height }; - const CGRect r = { .origin = { .x = 0, .y = 0 }, .size = size }; - + CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, + .tx = 0, .ty = size.height}; CGContextConcatCTM(dc.context, t); - PlotIconRefInContext(dc.context, &r, kAlignAbsoluteCenter, - kTransformNone, NULL, kPlotIconRefNormalFlags, icon); + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext + graphicsContextWithGraphicsPort:dc.context + flipped:NO]]; + [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect + operation:NSCompositeCopy fraction:1.0]; + [NSGraphicsContext restoreGraphicsState]; } TkMacOSXRestoreDrawingContext(&dc); } return pixmap; } + /* *---------------------------------------------------------------------- * * TkpCreateNativeBitmap -- @@ -166,26 +174,18 @@ Pixmap TkpCreateNativeBitmap( Display *display, const void *source) /* Info about the icon to build. */ { - Pixmap pixmap; - IconRef icon; - OSErr err; - - err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator, - PTR2UINT(source), &icon); - if (err == noErr) { - pixmap = GetBitmapForIcon(display, icon, CGSizeMake(builtInIconSize, - builtInIconSize)); - ReleaseIconRef(icon); - } else { - pixmap = Tk_GetPixmap(display, None, builtInIconSize, - builtInIconSize, 0); - } + NSString *iconUTI = OSTYPE_TO_UTI(PTR2UINT(source)); + NSImage *iconImage = [[NSWorkspace sharedWorkspace] + iconForFileType: iconUTI]; + CGSize size = CGSizeMake(builtInIconSize, builtInIconSize); + Pixmap pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size)); return pixmap; } + /* *---------------------------------------------------------------------- * * OSTypeFromString -- @@ -208,19 +208,20 @@ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); Tcl_UtfToExternalDString(encoding, s, -1, &ds); if (Tcl_DStringLength(&ds) <= 4) { char string[4] = {}; - memcpy(string, Tcl_DStringValue(&ds), (size_t) Tcl_DStringLength(&ds)); + memcpy(string, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); *t = (OSType) string[0] << 24 | (OSType) string[1] << 16 | (OSType) string[2] << 8 | (OSType) string[3]; result = TCL_OK; } Tcl_DStringFree(&ds); Tcl_FreeEncoding(encoding); return result; } + /* *---------------------------------------------------------------------- * * TkpGetNativeAppBitmap -- @@ -307,54 +308,21 @@ if (image) { size = [image size]; } } if (image) { - TkMacOSXDrawingContext dc; - int depth = 0; - -#ifdef MAC_OSX_TK_TODO - for (NSImageRep *r in [image representations]) { - NSInteger bitsPerSample = [r bitsPerSample]; - if (bitsPerSample && bitsPerSample > depth) { - depth = bitsPerSample; - }; - } - if (depth == 1) { - /* TODO: convert BW NSImage to CGImageMask */ - } -#endif - pixmap = Tk_GetPixmap(display, None, size.width, size.height, depth); *width = size.width; *height = size.height; - if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) { - if (dc.context) { - CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, - .tx = 0, .ty = size.height}; - - CGContextConcatCTM(dc.context, t); - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext - graphicsContextWithGraphicsPort:dc.context flipped:NO]]; - [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect - operation:NSCompositeCopy fraction:1.0]; - [NSGraphicsContext restoreGraphicsState]; - } - TkMacOSXRestoreDrawingContext(&dc); - } + pixmap = PixmapFromImage(display, image, NSSizeToCGSize(size)); } else if (name) { OSType iconType; if (OSTypeFromString(name, &iconType) == TCL_OK) { - IconRef icon; - OSErr err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator, - iconType, &icon); - if (err == noErr) { - pixmap = GetBitmapForIcon(display, icon, NSSizeToCGSize(size)); - *width = size.width; - *height = size.height; - ReleaseIconRef(icon); - } + NSString *iconUTI = OSTYPE_TO_UTI(iconType); + printf("Found image for UTI %s\n", iconUTI.UTF8String); + NSImage *iconImage = [[NSWorkspace sharedWorkspace] + iconForFileType: iconUTI]; + pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size)); } } return pixmap; } Index: macosx/tkMacOSXButton.c ================================================================== --- macosx/tkMacOSXButton.c +++ macosx/tkMacOSXButton.c @@ -1,10 +1,10 @@ /* * tkMacOSXButton.c -- * - * This file implements the Macintosh specific portion of the - * button widgets. + * This file implements the Macintosh specific portion of the button + * widgets. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. * Copyright (c) 2006-2007 Daniel A. Steffen * Copyright 2007 Revar Desmera. @@ -27,22 +27,13 @@ /* * Extra padding used for computing the content size that should * be allowed when drawing the HITheme button. */ -#define HI_PADX 2 +#define HI_PADX 14 #define HI_PADY 1 -/* - * Some defines used to control what type of control is drawn. - */ - -#define DRAW_LABEL 0 /* Labels are treated genericly. */ -#define DRAW_CONTROL 1 /* Draw using the Native control. */ -#define DRAW_CUSTOM 2 /* Make our own button drawing. */ -#define DRAW_BEVEL 3 - /* * The delay in milliseconds between pulsing default button redraws. */ #define PULSE_TIMER_MSECS 62 /* Largest value that didn't look stuttery */ @@ -50,11 +41,10 @@ * Declaration of Mac specific button structure. */ typedef struct { - int drawType; Tk_3DBorder border; int relief; int offset; /* 0 means this is a normal widget. 1 means * it is an image button, so we offset the * image to make the button appear to move @@ -78,24 +68,27 @@ /* * Forward declarations for procedures defined later in this file: */ - -static void ButtonBackgroundDrawCB (const HIRect *btnbounds, MacButton *ptr, - SInt16 depth, Boolean isColorDev); -static void ButtonContentDrawCB (const HIRect *bounds, ThemeButtonKind kind, - const HIThemeButtonDrawInfo *info, MacButton *ptr, SInt16 depth, - Boolean isColorDev); -static void ButtonEventProc(ClientData clientData, XEvent *eventPtr); -static void TkMacOSXComputeButtonParams (TkButton * butPtr, ThemeButtonKind* btnkind, - HIThemeButtonDrawInfo* drawinfo); -static int TkMacOSXComputeButtonDrawParams (TkButton * butPtr, DrawParams * dpPtr); -static void TkMacOSXDrawButton (MacButton *butPtr, GC gc, Pixmap pixmap); -static void DrawButtonImageAndText(TkButton* butPtr); -static void PulseDefaultButtonProc(ClientData clientData); - +static void ButtonBackgroundDrawCB(const HIRect *btnbounds, + MacButton *ptr, SInt16 depth, Boolean isColorDev); +static void ButtonContentDrawCB(const HIRect *bounds, + ThemeButtonKind kind, + const HIThemeButtonDrawInfo *info, MacButton *ptr, + SInt16 depth, Boolean isColorDev); +static void ButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void TkMacOSXComputeButtonParams(TkButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo); +static int TkMacOSXComputeButtonDrawParams(TkButton *butPtr, + DrawParams * dpPtr); +static void TkMacOSXDrawButton(MacButton *butPtr, GC gc, + Pixmap pixmap); +static void DrawButtonImageAndText(TkButton *butPtr); +static void PulseDefaultButtonProc(ClientData clientData); /* * The class procedure table for the button widgets. */ @@ -103,19 +96,19 @@ sizeof(Tk_ClassProcs), /* size */ TkButtonWorldChanged, /* worldChangedProc */ }; static int bCount; - + /* *---------------------------------------------------------------------- * * TkpButtonSetDefaults -- * - * This procedure is invoked before option tables are created for - * buttons. It modifies some of the default values to match the current - * values defined for this platform. + * This procedure is invoked before option tables are created for buttons. + * It modifies some of the default values to match the current values + * defined for this platform. * * Results: * Some of the default values in *specPtr are modified. * * Side effects: @@ -125,13 +118,12 @@ */ void TkpButtonSetDefaults() { -/*No-op.*/ + /*No-op.*/ } - /* *---------------------------------------------------------------------- * * TkpCreateButton -- @@ -149,112 +141,130 @@ TkButton * TkpCreateButton( Tk_Window tkwin) { - MacButton *macButtonPtr = (MacButton *) ckalloc(sizeof(MacButton)); + MacButton *macButtonPtr = ckalloc(sizeof(MacButton)); Tk_CreateEventHandler(tkwin, ActivateMask, - ButtonEventProc, (ClientData) macButtonPtr); + ButtonEventProc, macButtonPtr); macButtonPtr->id = bCount++; macButtonPtr->flags = FIRST_DRAW; macButtonPtr->btnkind = kThemePushButton; macButtonPtr->defaultPulseHandler = NULL; bzero(&macButtonPtr->drawinfo, sizeof(macButtonPtr->drawinfo)); bzero(&macButtonPtr->lastdrawinfo, sizeof(macButtonPtr->lastdrawinfo)); - return (TkButton *)macButtonPtr; + return (TkButton *) macButtonPtr; } /* *---------------------------------------------------------------------- * * TkpDisplayButton -- * - * This procedure is invoked to display a button widget. It is - * normally invoked as an idle handler. + * This procedure is invoked to display a button widget. It is normally + * invoked as an idle handler. * * Results: * None. * * Side effects: - * Commands are output to X to display the button in its - * current mode. The REDRAW_PENDING flag is cleared. + * Commands are output to X to display the button in its current mode. The + * REDRAW_PENDING flag is cleared. * *---------------------------------------------------------------------- */ void TkpDisplayButton( ClientData clientData) /* Information about widget. */ { - MacButton *macButtonPtr = (MacButton *) clientData; - TkButton *butPtr = (TkButton *) clientData; + MacButton *macButtonPtr = clientData; + TkButton *butPtr = clientData; Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; DrawParams* dpPtr = &macButtonPtr->drawParams; int needhighlight = 0; + if (butPtr->flags & BUTTON_DELETED) { + return; + } butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } pixmap = (Pixmap) Tk_WindowId(tkwin); - TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); - - if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr) ) { - macButtonPtr->useTkText = 0; - } else { - macButtonPtr->useTkText = 1; - } - /* * Set up clipping region. Make sure the we are using the port * for this button, or we will set the wrong window's clip. */ + TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); + + if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) { + macButtonPtr->useTkText = 0; + } else { + macButtonPtr->useTkText = 1; + } if (macButtonPtr->useTkText) { if (butPtr->type == TYPE_BUTTON) { Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } else { Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } - /* Display image or bitmap or text for labels or custom controls. */ + /* + * Display image or bitmap or text for labels or custom controls. + */ + DrawButtonImageAndText(butPtr); - needhighlight = 1; + needhighlight = 1; } else { - /* Draw the native portion of the buttons. */ + /* + * Draw the native portion of the buttons. + */ + TkMacOSXDrawButton(macButtonPtr, dpPtr->gc, pixmap); - /* Draw highlight border, if needed. */ + /* + * Ask for the highlight border, if needed. + */ + if (butPtr->highlightWidth < 3) { needhighlight = 1; } } - /* Draw highlight border, if needed. */ + /* + * Draw highlight border, if needed. + */ + if (needhighlight) { - if ((butPtr->flags & GOT_FOCUS)) { - Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), - butPtr->highlightWidth, TK_RELIEF_SOLID); - } + GC gc = NULL; + if ((butPtr->flags & GOT_FOCUS) && butPtr->highlightColorPtr) { + gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + } else if (butPtr->type == TYPE_LABEL) { + gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap); + } + if (gc) { + TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); + } } } /* *---------------------------------------------------------------------- * * TkpComputeButtonGeometry -- * - * After changes in a button's text or bitmap, this procedure - * recomputes the button's geometry and passes this information - * along to the geometry manager for the window. + * After changes in a button's text or bitmap, this procedure recomputes + * the button's geometry and passes this information along to the geometry + * manager for the window. * * Results: * None. * * Side effects: @@ -267,40 +277,42 @@ TkpComputeButtonGeometry( TkButton *butPtr) /* Button whose geometry may have changed. */ { int width = 0, height = 0, charWidth = 1, haveImage = 0, haveText = 0; int txtWidth = 0, txtHeight = 0; - MacButton *mbPtr = (MacButton*)butPtr; + MacButton *mbPtr = (MacButton *) butPtr; Tk_FontMetrics fm; - DrawParams drawParams; - - /* - * First figure out the size of the contents of the button. - */ + char *text = Tcl_GetString(butPtr->textPtr); TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo); /* * If the indicator is on, get its size. */ - if ( butPtr->indicatorOn ) { - switch (butPtr->type) { - case TYPE_RADIO_BUTTON: - GetThemeMetric(kThemeMetricRadioButtonWidth, (SInt32 *)&butPtr->indicatorDiameter); - break; - case TYPE_CHECK_BUTTON: - GetThemeMetric(kThemeMetricCheckBoxWidth, (SInt32 *)&butPtr->indicatorDiameter); - break; - default: - break; - } - /* Allow 2px extra space next to the indicator. */ - butPtr->indicatorSpace = butPtr->indicatorDiameter + 2; + if (butPtr->indicatorOn) { + switch (butPtr->type) { + case TYPE_RADIO_BUTTON: + GetThemeMetric(kThemeMetricRadioButtonWidth, + (SInt32 *) &butPtr->indicatorDiameter); + break; + case TYPE_CHECK_BUTTON: + GetThemeMetric(kThemeMetricCheckBoxWidth, + (SInt32 *) &butPtr->indicatorDiameter); + break; + default: + break; + } + + /* + * Allow 2px extra space next to the indicator. + */ + + butPtr->indicatorSpace = butPtr->indicatorDiameter + 2; } else { - butPtr->indicatorSpace = 0; - butPtr->indicatorDiameter = 0; + butPtr->indicatorSpace = 0; + butPtr->indicatorDiameter = 0; } if (butPtr->image != NULL) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; @@ -310,247 +322,221 @@ } if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) { Tk_FreeTextLayout(butPtr->textLayout); butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, - Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, - butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); - - txtWidth = butPtr->textWidth; - txtHeight = butPtr->textHeight; - charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); - Tk_GetFontMetrics(butPtr->tkfont, &fm); - haveText = (txtWidth != 0 && txtHeight != 0); + text, -1, butPtr->wrapLength, butPtr->justify, 0, + &butPtr->textWidth, &butPtr->textHeight); + + txtWidth = butPtr->textWidth + 2*butPtr->padX; + txtHeight = butPtr->textHeight + 2*butPtr->padY; + haveText = 1; } if (haveImage && haveText) { /* Image and Text */ switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: - /* - * Image is above or below text. - */ - - height += txtHeight + butPtr->padY; - width = (width > txtWidth ? width : txtWidth); - break; - case COMPOUND_LEFT: - case COMPOUND_RIGHT: - /* - * Image is left or right of text. - */ - - width += txtWidth + butPtr->padX; - height = (height > txtHeight ? height : txtHeight); - break; - case COMPOUND_CENTER: - /* - * Image and text are superimposed. - */ - - width = (width > txtWidth ? width : txtWidth); - height = (height > txtHeight ? height : txtHeight); - break; - default: - break; + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + width += txtWidth + 2*butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + default: + break; } width += butPtr->indicatorSpace; - } else if (haveImage) { /* Image only */ - width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace; - height = butPtr->height > 0 ? butPtr->height : height; - + width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace; + height = butPtr->height > 0 ? butPtr->height : height; + if (butPtr->type == TYPE_BUTTON) { + /* + * Allow room to shift the image. + */ + width += 2; + height += 2; + } } else { /* Text only */ width = txtWidth + butPtr->indicatorSpace; height = txtHeight; if (butPtr->width > 0) { - width = butPtr->width * charWidth; + charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); + width = butPtr->width * charWidth + 2*butPtr->padX; } if (butPtr->height > 0) { - height = butPtr->height * fm.linespace; + Tk_GetFontMetrics(butPtr->tkfont, &fm); + height = butPtr->height * fm.linespace + 2*butPtr->padY; } } - /* Add padding */ - width += 2 * butPtr->padX; - height += 2 * butPtr->padY; - /* * Now figure out the size of the border decorations for the button. */ if (butPtr->highlightWidth < 0) { butPtr->highlightWidth = 0; } - butPtr->inset = 0; - butPtr->inset += butPtr->highlightWidth; - - if (TkMacOSXComputeButtonDrawParams(butPtr,&drawParams)) { - HIRect tmpRect; - HIRect contBounds; - int paddingx = 0; - int paddingy = 0; - - tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY); - - HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds); - /* If the content region has a minimum height, match it. */ - if (height < contBounds.size.height) { - height = contBounds.size.height; - } - - /* If the content region has a minimum width, match it. */ - if (width < contBounds.size.width) { - width = contBounds.size.width; - } - - /* Pad to fill difference between content bounds and button bounds. */ - paddingx = contBounds.origin.x; - paddingy = contBounds.origin.y; - - if (height < paddingx - 4) { - /* can't have buttons much shorter than button side diameter. */ - height = paddingx - 4; - } - - } else { - height += butPtr->borderWidth*2; - width += butPtr->borderWidth*2; - } + butPtr->inset = butPtr->borderWidth + butPtr->highlightWidth; width += butPtr->inset*2; height += butPtr->inset*2; if ([NSApp macMinorVersion] == 6) { - width += 12; + width += 12; } + if (mbPtr->btnkind == kThemePushButton) { + HIRect tmpRect; + HIRect contBounds; + /* + * A PushButton has a minimum size. We make sure that we are not + * underestimating the size by requesting the content size of a + * Pushbutton whose overall size is our content size expanded by the + * standard padding. + */ + + tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY); + HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds); + if (height < contBounds.size.height) { + height = contBounds.size.height; + } + if (width < contBounds.size.width) { + width = contBounds.size.width; + } + height += 2*HI_PADY; + width += 2*HI_PADX; + } Tk_GeometryRequest(butPtr->tkwin, width, height); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); } - + /* *---------------------------------------------------------------------- * * DrawButtonImageAndText -- * - * Draws the image and text associated with a button or label. + * Draws the image and text associated with a button or label. * * Results: - * None. + * None. * * Side effects: - * The image and text are drawn. + * The image and text are drawn. * *---------------------------------------------------------------------- */ static void DrawButtonImageAndText( - TkButton* butPtr) -{ - - MacButton *mbPtr = (MacButton*)butPtr; - Tk_Window tkwin = butPtr->tkwin; - Pixmap pixmap; - int haveImage = 0; - int haveText = 0; - int imageWidth = 0; - int imageHeight = 0; - int imageXOffset = 0; - int imageYOffset = 0; - int textXOffset = 0; - int textYOffset = 0; - int width = 0; - int height = 0; - int fullWidth = 0; - int fullHeight = 0; - int pressed = 0; - + TkButton *butPtr) +{ + + MacButton *mbPtr = (MacButton *) butPtr; + Tk_Window tkwin = butPtr->tkwin; + Pixmap pixmap; + int haveImage = 0, haveText = 0, pressed = 0; + int imageWidth = 0, imageHeight = 0; + int imageXOffset = 0, imageYOffset = 0; + int textXOffset = 0, textYOffset = 0; + int width = 0, height = 0; + int fullWidth = 0, fullHeight = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - DrawParams* dpPtr = &mbPtr->drawParams; - pixmap = (Pixmap)Tk_WindowId(tkwin); + DrawParams *dpPtr = &mbPtr->drawParams; + pixmap = (Pixmap) Tk_WindowId(tkwin); if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } - imageWidth = width; + imageWidth = width; imageHeight = height; if (mbPtr->drawinfo.state == kThemeStatePressed) { - /* Offset bitmaps by a bit when the button is pressed. */ + /* + * Offset bitmaps by a bit when the button is pressed. + */ + pressed = 1; } haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (haveImage && haveText) { /* Image and Text */ - int x; - int y; - textXOffset = 0; - textYOffset = 0; - fullWidth = 0; - fullHeight = 0; + int x, y; switch ((enum compound) butPtr->compound) { case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - if (butPtr->compound == COMPOUND_TOP) { - textYOffset = height + butPtr->padY; - } else { - imageYOffset = butPtr->textHeight + butPtr->padY; - } - fullHeight = height + butPtr->textHeight + butPtr->padY; - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - break; - } + case COMPOUND_BOTTOM: + /* Image is above or below text */ + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; + } + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - if (butPtr->compound == COMPOUND_LEFT) { - textXOffset = width + butPtr->padX; - } else { - imageXOffset = butPtr->textWidth + butPtr->padX; - } - fullWidth = butPtr->textWidth + butPtr->padX + width; - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } + case COMPOUND_RIGHT: + /* + * Image is left or right of text + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; + } + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed + */ + + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; default: - break; + break; } TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX + butPtr->borderWidth, butPtr->padY + butPtr->borderWidth, @@ -568,95 +554,93 @@ x += dpPtr->offset; y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; - textYOffset -= 1; if (butPtr->image != NULL) { - if ((butPtr->selectImage != NULL) && - (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, - width, height, pixmap, imageXOffset, imageYOffset); - } else if ((butPtr->tristateImage != NULL) && - (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, - width, height, pixmap, imageXOffset, imageYOffset); - } else { - Tk_RedrawImage(butPtr->image, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } - } else { - XSetClipOrigin(butPtr->display, dpPtr->gc, - imageXOffset, imageYOffset); - XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, (unsigned int) height, - imageXOffset, imageYOffset, 1); - XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); - } - + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, dpPtr->gc, + imageXOffset, imageYOffset); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, (unsigned int) width, (unsigned int) height, + imageXOffset, imageYOffset, 1); + XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); + } + + y += 1; /* Tweak to match native buttons. */ Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, butPtr->underline); } else if (haveImage) { /* Image only */ - int x = 0; - int y; + int x = 0, y; + TkComputeAnchor(butPtr->anchor, tkwin, - butPtr->padX + butPtr->borderWidth, - butPtr->padY + butPtr->borderWidth, - width + butPtr->indicatorSpace, - height, &x, &y); + butPtr->padX + butPtr->borderWidth, + butPtr->padY + butPtr->borderWidth, + width + butPtr->indicatorSpace, height, &x, &y); x += butPtr->indicatorSpace; if (pressed) { - x += dpPtr->offset; - y += dpPtr->offset; + x += dpPtr->offset; + y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { - - if ((butPtr->selectImage != NULL) && - (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } else if ((butPtr->tristateImage != NULL) && - (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } else { - Tk_RedrawImage(butPtr->image, 0, 0, width, height, - pixmap, imageXOffset, imageYOffset); - } - } else { - XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); - XCopyPlane(butPtr->display, butPtr->bitmap, - pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, - (unsigned int) height, - imageXOffset, imageYOffset, 1); - XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, (unsigned int) width, (unsigned int) height, + imageXOffset, imageYOffset, 1); + XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } } else { /* Text only */ int x, y; + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, - butPtr->textWidth + butPtr->indicatorSpace, - butPtr->textHeight, &x, &y); + butPtr->textWidth + butPtr->indicatorSpace, + butPtr->textHeight, &x, &y); x += butPtr->indicatorSpace; - Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, - x, y, 0, -1); + y += 1; /* Tweak to match native buttons */ + Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, x, y, 0, -1); } /* * If the button is disabled with a stipple rather than a special - * foreground color, generate the stippled effect. If the widget - * is selected and we use a different background color when selected, - * must temporarily modify the GC so the stippling is the right color. + * foreground color, generate the stippled effect. If the widget is + * selected and we use a different background color when selected, must + * temporarily modify the GC so the stippling is the right color. */ if (mbPtr->useTkText) { if ((butPtr->state == STATE_DISABLED) && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { @@ -690,22 +674,19 @@ * Draw the border and traversal highlight last. This way, if the * button's contents overflow they'll be covered up by the border. */ if (dpPtr->relief != TK_RELIEF_FLAT) { - int inset = butPtr->highlightWidth; - Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, - Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, - butPtr->borderWidth, dpPtr->relief); + int inset = butPtr->highlightWidth; + + Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, + Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, + butPtr->borderWidth, dpPtr->relief); } } - - } - - - - +} + /* *---------------------------------------------------------------------- * * TkpDestroyButton -- * @@ -723,10 +704,11 @@ void TkpDestroyButton( TkButton *butPtr) { MacButton *mbPtr = (MacButton *) butPtr; /* Mac button. */ + if (mbPtr->defaultPulseHandler) { Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler); } } @@ -733,13 +715,12 @@ /* *-------------------------------------------------------------- * * TkMacOSXDrawButton -- * - * This function draws the tk button using Mac controls - * In addition, this code may apply custom colors passed - * in the TkButton. + * This function draws the tk button using Mac controls. In addition, + * this code may apply custom colors passed in the TkButton. * * Results: * None. * * Side effects: @@ -754,27 +735,23 @@ GC gc, /* The GC we are drawing into - needed for * the bevel button */ Pixmap pixmap) /* The pixmap we are drawing into - needed * for the bevel button */ { - TkButton * butPtr = ( TkButton *)mbPtr; - TkWindow * winPtr; - HIRect cntrRect; + TkButton *butPtr = (TkButton *) mbPtr; + TkWindow *winPtr = (TkWindow *) butPtr->tkwin; + HIRect cntrRect; TkMacOSXDrawingContext dc; - DrawParams* dpPtr = &mbPtr->drawParams; + DrawParams *dpPtr = &mbPtr->drawParams; int useNewerHITools = 1; - winPtr = (TkWindow *)butPtr->tkwin; - TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo); - cntrRect = CGRectMake(winPtr->privatePtr->xOff, - winPtr->privatePtr->yOff, - Tk_Width(butPtr->tkwin), - Tk_Height(butPtr->tkwin)); + cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, + Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin)); - cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset); + cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset); if (useNewerHITools == 1) { HIRect contHIRec; static HIThemeButtonDrawInfo hiinfo; @@ -784,25 +761,33 @@ return; } hiinfo.version = 0; hiinfo.state = mbPtr->drawinfo.state; - hiinfo.kind = mbPtr->btnkind; + hiinfo.kind = mbPtr->btnkind; hiinfo.value = mbPtr->drawinfo.value; hiinfo.adornment = mbPtr->drawinfo.adornment; hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent(); if (hiinfo.animation.time.start == 0) { hiinfo.animation.time.start = hiinfo.animation.time.current; } - HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, - &contHIRec); + /* + * To avoid buttons with white text on a white background, we always + * set the state to inactive in Dark Mode. It isn't perfect but it is + * usable. Using a ttk::button would be a better choice, however. + */ + + if (TkMacOSXInDarkMode(butPtr->tkwin)) { + hiinfo.state = kThemeStateInactive; + } + HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, + kHIThemeOrientationNormal, &contHIRec); TkMacOSXRestoreDrawingContext(&dc); ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo, - (MacButton *)mbPtr, 32, true); - + (MacButton *) mbPtr, 32, true); } else { if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) { return; } @@ -814,47 +799,48 @@ /* *-------------------------------------------------------------- * * ButtonBackgroundDrawCB -- * - * This function draws the background that - * lies under checkboxes and radiobuttons. + * This function draws the background that lies under checkboxes and + * radiobuttons. * * Results: * None. * * Side effects: * The background gets updated to the current color. * *-------------------------------------------------------------- */ + static void -ButtonBackgroundDrawCB ( - const HIRect * btnbounds, +ButtonBackgroundDrawCB( + const HIRect *btnbounds, MacButton *ptr, SInt16 depth, Boolean isColorDev) { - MacButton* mbPtr = (MacButton*)ptr; - TkButton* butPtr = (TkButton*)mbPtr; - Tk_Window tkwin = butPtr->tkwin; + MacButton *mbPtr = (MacButton *) ptr; + TkButton *butPtr = (TkButton *) mbPtr; + Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; int usehlborder = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - pixmap = (Pixmap)Tk_WindowId(tkwin); + pixmap = (Pixmap) Tk_WindowId(tkwin); if (butPtr->type != TYPE_LABEL) { switch (mbPtr->btnkind) { - case kThemeSmallBevelButton: - case kThemeBevelButton: - case kThemeRoundedBevelButton: - case kThemePushButton: - usehlborder = 1; - break; + case kThemeSmallBevelButton: + case kThemeBevelButton: + case kThemeRoundedBevelButton: + case kThemePushButton: + usehlborder = 1; + break; } } if (usehlborder) { Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); @@ -886,31 +872,32 @@ const HIThemeButtonDrawInfo *drawinfo, MacButton *ptr, SInt16 depth, Boolean isColorDev) { - TkButton *butPtr = (TkButton *)ptr; - Tk_Window tkwin = butPtr->tkwin; + TkButton *butPtr = (TkButton *) ptr; + Tk_Window tkwin = butPtr->tkwin; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } /* - * Overlay Tk elements over button native region: drawing elements - * within button boundaries/native region causes unpredictable metrics. + * Overlay Tk elements over button native region: drawing elements within + * button boundaries/native region causes unpredictable metrics. */ + DrawButtonImageAndText( butPtr); } /* *-------------------------------------------------------------- * * ButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This procedure is invoked by the Tk dispatcher for various events on + * buttons. * * Results: * None. * * Side effects: @@ -922,12 +909,12 @@ static void ButtonEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkButton *buttonPtr = (TkButton *) clientData; - MacButton *mbPtr = (MacButton *) clientData; + TkButton *buttonPtr = clientData; + MacButton *mbPtr = clientData; if (eventPtr->type == ActivateNotify || eventPtr->type == DeactivateNotify) { if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) { return; @@ -936,11 +923,11 @@ mbPtr->flags |= ACTIVE; } else { mbPtr->flags &= ~ACTIVE; } if ((buttonPtr->flags & REDRAW_PENDING) == 0) { - Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) buttonPtr); + Tcl_DoWhenIdle(TkpDisplayButton, buttonPtr); buttonPtr->flags |= REDRAW_PENDING; } } } @@ -947,13 +934,13 @@ /* *---------------------------------------------------------------------- * * TkMacOSXComputeButtonParams -- * - * This procedure computes the various parameters used - * when creating a Carbon Appearance control. - * These are determined by the various tk button parameters + * This procedure computes the various parameters used when creating a + * Carbon Appearance control. These are determined by the various tk + * button parameters * * Results: * None. * * Side effects: @@ -962,15 +949,15 @@ *---------------------------------------------------------------------- */ static void TkMacOSXComputeButtonParams( - TkButton * butPtr, - ThemeButtonKind* btnkind, - HIThemeButtonDrawInfo *drawinfo) + TkButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo) { - MacButton *mbPtr = (MacButton *)butPtr; + MacButton *mbPtr = (MacButton *) butPtr; if (butPtr->borderWidth <= 2) { *btnkind = kThemeSmallBevelButton; } else if (butPtr->borderWidth == 3) { *btnkind = kThemeBevelButton; @@ -980,51 +967,50 @@ *btnkind = kThemePushButton; } if ((butPtr->image == None) && (butPtr->bitmap == None)) { switch (butPtr->type) { - case TYPE_BUTTON: - *btnkind = kThemePushButton; - break; - case TYPE_RADIO_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallRadioButton; - } else { - *btnkind = kThemeRadioButton; - } - break; - case TYPE_CHECK_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallCheckBox; - } else { - *btnkind = kThemeCheckBox; - } - break; + case TYPE_BUTTON: + *btnkind = kThemePushButton; + break; + case TYPE_RADIO_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallRadioButton; + } else { + *btnkind = kThemeRadioButton; + } + break; + case TYPE_CHECK_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallCheckBox; + } else { + *btnkind = kThemeCheckBox; + } + break; } } if (butPtr->indicatorOn) { switch (butPtr->type) { - case TYPE_RADIO_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallRadioButton; - } else { - *btnkind = kThemeRadioButton; - } - break; - case TYPE_CHECK_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallCheckBox; - } else { - *btnkind = kThemeCheckBox; - } - break; + case TYPE_RADIO_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallRadioButton; + } else { + *btnkind = kThemeRadioButton; + } + break; + case TYPE_CHECK_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallCheckBox; + } else { + *btnkind = kThemeCheckBox; + } + break; } } else { if (butPtr->type == TYPE_RADIO_BUTTON || - butPtr->type == TYPE_CHECK_BUTTON - ) { + butPtr->type == TYPE_CHECK_BUTTON) { if (*btnkind == kThemePushButton) { *btnkind = kThemeBevelButton; } } } @@ -1062,12 +1048,11 @@ drawinfo->adornment = kThemeAdornmentNone; if (butPtr->defaultState == DEFAULT_ACTIVE) { drawinfo->adornment |= kThemeAdornmentDefault; if (!mbPtr->defaultPulseHandler) { mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler( - PULSE_TIMER_MSECS, PulseDefaultButtonProc, - (ClientData) butPtr); + PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr); } } else if (mbPtr->defaultPulseHandler) { Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler); } if (butPtr->highlightWidth >= 3) { @@ -1080,13 +1065,12 @@ /* *---------------------------------------------------------------------- * * TkMacOSXComputeButtonDrawParams -- * - * This procedure computes the various parameters used - * when drawing a button - * These are determined by the various tk button parameters + * This procedure computes the various parameters used when drawing a + * button. These are determined by the various tk button parameters * * Results: * 1 if control will be used, 0 otherwise. * * Side effects: @@ -1098,29 +1082,28 @@ static int TkMacOSXComputeButtonDrawParams( TkButton *butPtr, DrawParams *dpPtr) { - MacButton *mbPtr = (MacButton *)butPtr; + MacButton *mbPtr = (MacButton *) butPtr; dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) || (butPtr->bitmap != None)); if (butPtr->type != TYPE_LABEL) { dpPtr->offset = 0; if (dpPtr->hasImageOrBitmap) { switch (mbPtr->btnkind) { - case kThemeSmallBevelButton: - case kThemeBevelButton: - case kThemeRoundedBevelButton: - case kThemePushButton: - dpPtr->offset = 1; - break; + case kThemeSmallBevelButton: + case kThemeBevelButton: + case kThemeRoundedBevelButton: + case kThemePushButton: + dpPtr->offset = 1; + break; } } } - dpPtr->border = butPtr->normalBorder; if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) { dpPtr->gc = butPtr->disabledGC; } else if (butPtr->type == TYPE_BUTTON && butPtr->state == STATE_ACTIVE) { @@ -1134,12 +1117,12 @@ && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) { dpPtr->border = butPtr->selectBorder; } /* - * Override the relief specified for the button if this is a - * checkbutton or radiobutton and there's no indicator. + * Override the relief specified for the button if this is a checkbutton or + * radiobutton and there's no indicator. */ dpPtr->relief = butPtr->relief; if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) { @@ -1147,33 +1130,22 @@ dpPtr->relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED; } } - /* - * Determine the draw type - */ - - if (butPtr->type == TYPE_LABEL) { - dpPtr->drawType = DRAW_LABEL; - } else if (butPtr->type == TYPE_BUTTON) { - if (!dpPtr->hasImageOrBitmap) { - dpPtr->drawType = DRAW_CONTROL; - } else { - dpPtr->drawType = DRAW_BEVEL; - } - } else if (butPtr->indicatorOn) { - dpPtr->drawType = DRAW_CONTROL; - } else if (dpPtr->hasImageOrBitmap) { - dpPtr->drawType = DRAW_BEVEL; - } else { - dpPtr->drawType = DRAW_CUSTOM; - } - - if ((dpPtr->drawType == DRAW_CONTROL) || (dpPtr->drawType == DRAW_BEVEL)) { + if (butPtr->type != TYPE_LABEL && (butPtr->type == TYPE_BUTTON || + butPtr->indicatorOn || dpPtr->hasImageOrBitmap)) { + /* + * Draw this widget as a native control. + */ + return 1; } else { + /* + * Draw this widget from scratch. + */ + return 0; } } /* @@ -1190,22 +1162,24 @@ * Side effects: * Sets a timer to run itself again. * *-------------------------------------------------------------- */ + static void PulseDefaultButtonProc(ClientData clientData) { - MacButton *mbPtr = (MacButton *)clientData; + MacButton *mbPtr = clientData; + TkpDisplayButton(clientData); mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler( PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData); } - + /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXClipboard.c ================================================================== --- macosx/tkMacOSXClipboard.c +++ macosx/tkMacOSXClipboard.c @@ -121,12 +121,13 @@ * once it has been retrieved. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { int result = TCL_ERROR; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + int haveExternalClip = + ([[NSPasteboard generalPasteboard] changeCount] != changeCount); - int haveExternalClip = ([[NSPasteboard generalPasteboard] changeCount] != changeCount); if (dispPtr && (haveExternalClip || dispPtr->clipboardActive) && selection == dispPtr->clipboardAtom && (target == XA_STRING || target == dispPtr->utf8Atom)) { NSString *string = nil; NSPasteboard *pb = [NSPasteboard generalPasteboard]; @@ -175,10 +176,11 @@ if (dispPtr && selection == dispPtr->clipboardAtom) { clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL; if (!dispPtr->clipboardActive) { NSPasteboard *pb = [NSPasteboard generalPasteboard]; + changeCount = [pb declareTypes:[NSArray array] owner:NSApp]; } } return Success; } @@ -186,12 +188,12 @@ /* *---------------------------------------------------------------------- * * TkMacOSXSelDeadWindow -- * - * This function is invoked just before a TkWindow is deleted. It - * performs selection-related cleanup. + * This function is invoked just before a TkWindow is deleted. It performs + * selection-related cleanup. * * Results: * None. * * Side effects: Index: macosx/tkMacOSXColor.c ================================================================== --- macosx/tkMacOSXColor.c +++ macosx/tkMacOSXColor.c @@ -15,15 +15,36 @@ */ #include "tkMacOSXPrivate.h" #include "tkColor.h" +/* + * The colorType specifies how the color value should be interpreted. For the + * unique rgbColor entry, the RGB values are generated from the pixel value of + * an XColor. The ttkBackground and semantic types are dynamic, meaning + * that they change when dark mode is enabled on OSX 10.13 and later. + */ + +enum colorType { + clearColor, /* There should be only one of these. */ + rgbColor, /* There should be only one of these. */ + appearance, /* There should be only one of these. */ + HIBrush, /* The value is a HITheme brush color table index. */ + HIText, /* The value is a HITheme text color table index. */ + HIBackground, /* The value is a HITheme background color table index. */ + ttkBackground, /* The value can be used as a parameter.*/ + semantic, /* The value can be used as a parameter.*/ +}; + +/* + + */ + struct SystemColorMapEntry { const char *name; - ThemeBrush brush; - ThemeTextColor textColor; - ThemeBackgroundKind background; + enum colorType type; + long value; }; /* unsigned char pixelCode; */ /* * Array of system color definitions: the array index is required to equal the * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept @@ -30,198 +51,211 @@ * in sync with the public pixel code values in tkMacOSXPort.h ! */ #define MIN_PIXELCODE 30 static const struct SystemColorMapEntry systemColorMap[] = { - { "Transparent", 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */ - { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */ - { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */ - { "HighlightText", kThemeBrushBlack, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */ - { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */ - { "ButtonText", 0, kThemeTextColorPushButtonActive, 0 }, /* 35: CONTROL_TEXT_PIXEL */ - { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 36 */ - { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */ - { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 38 */ - { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */ - { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 40 */ - { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */ - { "SheetBackground", kThemeBrushSheetBackground, 0, 0 }, /* 42 */ - { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */ - { "Black", kThemeBrushBlack, 0, 0 }, /* 44 */ - { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */ - { "White", kThemeBrushWhite, 0, 0 }, /* 46 */ - { "Menu", kThemeBrushMenuBackground, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */ - { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0 }, /* 48 */ - { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 49: MENU_DISABLED_PIXEL */ - { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0 }, /* 50 */ - { "MenuText", 0, kThemeTextColorMenuItemActive, 0 }, /* 51: MENU_TEXT_PIXEL */ - { "AppearanceColor", 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */ - { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0 }, /* 53 */ - { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0 }, /* 54 */ - { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0 }, /* 55 */ - { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0 }, /* 56 */ - { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0 }, /* 57 */ - { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0 }, /* 58 */ - { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0 }, /* 59 */ - { "ListViewBackground", kThemeBrushListViewBackground, 0, 0 }, /* 60 */ - { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0 }, /* 61 */ - { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0 }, /* 62 */ - { "ChasingArrows", kThemeBrushChasingArrows, 0, 0 }, /* 63 */ - { "DragHilite", kThemeBrushDragHilite, 0, 0 }, /* 64 */ - { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 65 */ - { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0 }, /* 66 */ - { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0 }, /* 67 */ - { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0 }, /* 68 */ - { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0 }, /* 69 */ - { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0 }, /* 70 */ - { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0 }, /* 71 */ - { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0 }, /* 72 */ - { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0 }, /* 73 */ - { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0 }, /* 74 */ - { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0 }, /* 75 */ - { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0 }, /* 76 */ - { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0 }, /* 77 */ - { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0 }, /* 78 */ - { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0 }, /* 79 */ - { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0 }, /* 80 */ - { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0 }, /* 81 */ - { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0 }, /* 82 */ - { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0 }, /* 83 */ - { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0 }, /* 84 */ - { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0 }, /* 85 */ - { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0 }, /* 86 */ - { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0 }, /* 87 */ - { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0 }, /* 88 */ - { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0 }, /* 89 */ - { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0 }, /* 90 */ - { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0 }, /* 91 */ - { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0 }, /* 92 */ - { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0 }, /* 93 */ - { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0 }, /* 94 */ - { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0 }, /* 95 */ - { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0 }, /* 96 */ - { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0 }, /* 97 */ - { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0 }, /* 98 */ - { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0 }, /* 99 */ - { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0 }, /* 100 */ - { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0 }, /* 101 */ - { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0 }, /* 102 */ - { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0 }, /* 103 */ - { "MenuBackground", kThemeBrushMenuBackground, 0, 0 }, /* 104 */ - { "Pixel", 0, 0, 0 }, /* 105: PIXEL_MAGIC */ - { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 106 */ - { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0 }, /* 107 */ - { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0 }, /* 108 */ - { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0 }, /* 109 */ - { "BlackText", 0, kThemeTextColorBlack, 0 }, /* 110 */ - { "DialogActiveText", 0, kThemeTextColorDialogActive, 0 }, /* 111 */ - { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0 }, /* 112 */ - { "AlertActiveText", 0, kThemeTextColorAlertActive, 0 }, /* 113 */ - { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0 }, /* 114 */ - { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0 }, /* 115 */ - { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0 }, /* 116 */ - { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0 }, /* 117 */ - { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0 }, /* 118 */ - { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0 }, /* 119 */ - { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0 }, /* 120 */ - { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0 }, /* 121 */ - { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0 }, /* 122 */ - { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0 }, /* 123 */ - { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0 }, /* 124 */ - { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0 }, /* 125 */ - { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0 }, /* 126 */ - { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0 }, /* 127 */ - { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0 }, /* 128 */ - { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0 }, /* 129 */ - { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0 }, /* 130 */ - { "IconLabelText", 0, kThemeTextColorIconLabel, 0 }, /* 131 */ - { "ListViewText", 0, kThemeTextColorListView, 0 }, /* 132 */ - { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0 }, /* 133 */ - { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0 }, /* 134 */ - { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0 }, /* 135 */ - { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0 }, /* 136 */ - { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0 }, /* 137 */ - { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0 }, /* 138 */ - { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0 }, /* 139 */ - { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0 }, /* 140 */ - { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0 }, /* 141 */ - { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0 }, /* 142 */ - { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0 }, /* 143 */ - { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0 }, /* 144 */ - { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 145 */ - { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 146 */ - { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0 }, /* 147 */ - { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0 }, /* 148 */ - { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0 }, /* 149 */ - { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0 }, /* 150 */ - { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0 }, /* 151 */ - { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0 }, /* 152 */ - { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0 }, /* 153 */ - { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0 }, /* 154 */ - { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0 }, /* 155 */ - { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0 }, /* 156 */ - { "NotificationText", 0, kThemeTextColorNotification, 0 }, /* 157 */ - { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0 }, /* 158 */ - { "WhiteText", 0, kThemeTextColorWhite, 0 }, /* 159 */ - { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane }, /* 160 */ - { "PlacardBackground", 0, 0, kThemeBackgroundPlacard }, /* 161 */ - { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader }, /* 162 */ - { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader }, /* 163 */ - { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox }, /* 164 */ - { "MetalBackground", 0, 0, kThemeBackgroundMetal }, /* 165 */ - { NULL, 0, 0, 0 } + { "Transparent", clearColor, 0 }, /* 30: TRANSPARENT_PIXEL */ + { "Highlight", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 31 */ + { "HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 32 */ + { "HighlightText", HIBrush, kThemeBrushBlack }, /* 33 */ + { "HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 34 */ + { "ButtonText", HIText, kThemeTextColorPushButtonActive }, /* 35 */ + { "PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 36 */ + { "ButtonFace", HIBrush, kThemeBrushButtonFaceActive }, /* 37 */ + { "SecondaryHighlightColor", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 38 */ + { "ButtonFrame", HIBrush, kThemeBrushButtonFrameActive }, /* 39 */ + { "AlternatePrimaryHighlightColor", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 40 */ + { "WindowBody", HIBrush, kThemeBrushDocumentWindowBackground }, /* 41 */ + { "SheetBackground", HIBrush, kThemeBrushSheetBackground }, /* 42 */ + { "MenuActive", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 43 */ + { "Black", HIBrush, kThemeBrushBlack }, /* 44 */ + { "MenuActiveText", HIText, kThemeTextColorMenuItemSelected }, /* 45 */ + { "White", HIBrush, kThemeBrushWhite }, /* 46 */ + { "Menu", HIBrush, kThemeBrushMenuBackground }, /* 47 */ + { "DialogBackgroundActive", HIBrush, kThemeBrushDialogBackgroundActive }, /* 48 */ + { "MenuDisabled", HIText, kThemeTextColorMenuItemDisabled }, /* 49 */ + { "DialogBackgroundInactive", HIBrush, kThemeBrushDialogBackgroundInactive }, /* 50 */ + { "MenuText", HIText, kThemeTextColorMenuItemActive }, /* 51 */ + { "AppearanceColor", appearance, 0 }, /* 52: APPEARANCE_PIXEL */ + { "AlertBackgroundActive", HIBrush, kThemeBrushAlertBackgroundActive }, /* 53 */ + { "AlertBackgroundInactive", HIBrush, kThemeBrushAlertBackgroundInactive }, /* 54 */ + { "ModelessDialogBackgroundActive", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 55 */ + { "ModelessDialogBackgroundInactive", HIBrush, kThemeBrushModelessDialogBackgroundInactive }, /* 56 */ + { "UtilityWindowBackgroundActive", HIBrush, kThemeBrushUtilityWindowBackgroundActive }, /* 57 */ + { "UtilityWindowBackgroundInactive", HIBrush, kThemeBrushUtilityWindowBackgroundInactive }, /* 58 */ + { "ListViewSortColumnBackground", HIBrush, kThemeBrushListViewSortColumnBackground }, /* 59 */ + { "ListViewBackground", HIBrush, kThemeBrushListViewBackground }, /* 60 */ + { "IconLabelBackground", HIBrush, kThemeBrushIconLabelBackground }, /* 61 */ + { "ListViewSeparator", HIBrush, kThemeBrushListViewSeparator }, /* 62 */ + { "ChasingArrows", HIBrush, kThemeBrushChasingArrows }, /* 63 */ + { "DragHilite", HIBrush, kThemeBrushDragHilite }, /* 64 */ + { "DocumentWindowBackground", HIBrush, kThemeBrushDocumentWindowBackground }, /* 65 */ + { "FinderWindowBackground", HIBrush, kThemeBrushFinderWindowBackground }, /* 66 */ + { "ScrollBarDelimiterActive", HIBrush, kThemeBrushScrollBarDelimiterActive }, /* 67 */ + { "ScrollBarDelimiterInactive", HIBrush, kThemeBrushScrollBarDelimiterInactive }, /* 68 */ + { "FocusHighlight", HIBrush, kThemeBrushFocusHighlight }, /* 69 */ + { "PopupArrowActive", HIBrush, kThemeBrushPopupArrowActive }, /* 70 */ + { "PopupArrowPressed", HIBrush, kThemeBrushPopupArrowPressed }, /* 71 */ + { "PopupArrowInactive", HIBrush, kThemeBrushPopupArrowInactive }, /* 72 */ + { "AppleGuideCoachmark", HIBrush, kThemeBrushAppleGuideCoachmark }, /* 73 */ + { "IconLabelBackgroundSelected", HIBrush, kThemeBrushIconLabelBackgroundSelected }, /* 74 */ + { "StaticAreaFill", HIBrush, kThemeBrushStaticAreaFill }, /* 75 */ + { "ActiveAreaFill", HIBrush, kThemeBrushActiveAreaFill }, /* 76 */ + { "ButtonFrameActive", HIBrush, kThemeBrushButtonFrameActive }, /* 77 */ + { "ButtonFrameInactive", HIBrush, kThemeBrushButtonFrameInactive }, /* 78 */ + { "ButtonFaceActive", HIBrush, kThemeBrushButtonFaceActive }, /* 79 */ + { "ButtonFaceInactive", HIBrush, kThemeBrushButtonFaceInactive }, /* 80 */ + { "ButtonFacePressed", HIBrush, kThemeBrushButtonFacePressed }, /* 81 */ + { "ButtonActiveDarkShadow", HIBrush, kThemeBrushButtonActiveDarkShadow }, /* 82 */ + { "ButtonActiveDarkHighlight", HIBrush, kThemeBrushButtonActiveDarkHighlight }, /* 83 */ + { "ButtonActiveLightShadow", HIBrush, kThemeBrushButtonActiveLightShadow }, /* 84 */ + { "ButtonActiveLightHighlight", HIBrush, kThemeBrushButtonActiveLightHighlight }, /* 85 */ + { "ButtonInactiveDarkShadow", HIBrush, kThemeBrushButtonInactiveDarkShadow }, /* 86 */ + { "ButtonInactiveDarkHighlight", HIBrush, kThemeBrushButtonInactiveDarkHighlight }, /* 87 */ + { "ButtonInactiveLightShadow", HIBrush, kThemeBrushButtonInactiveLightShadow }, /* 88 */ + { "ButtonInactiveLightHighlight", HIBrush, kThemeBrushButtonInactiveLightHighlight }, /* 89 */ + { "ButtonPressedDarkShadow", HIBrush, kThemeBrushButtonPressedDarkShadow }, /* 90 */ + { "ButtonPressedDarkHighlight", HIBrush, kThemeBrushButtonPressedDarkHighlight }, /* 91 */ + { "ButtonPressedLightShadow", HIBrush, kThemeBrushButtonPressedLightShadow }, /* 92 */ + { "ButtonPressedLightHighlight", HIBrush, kThemeBrushButtonPressedLightHighlight }, /* 93 */ + { "BevelActiveLight", HIBrush, kThemeBrushBevelActiveLight }, /* 94 */ + { "BevelActiveDark", HIBrush, kThemeBrushBevelActiveDark }, /* 95 */ + { "BevelInactiveLight", HIBrush, kThemeBrushBevelInactiveLight }, /* 96 */ + { "BevelInactiveDark", HIBrush, kThemeBrushBevelInactiveDark }, /* 97 */ + { "NotificationWindowBackground", HIBrush, kThemeBrushNotificationWindowBackground }, /* 98 */ + { "MovableModalBackground", HIBrush, kThemeBrushMovableModalBackground }, /* 99 */ + { "SheetBackgroundOpaque", HIBrush, kThemeBrushSheetBackgroundOpaque }, /* 100 */ + { "DrawerBackground", HIBrush, kThemeBrushDrawerBackground }, /* 101 */ + { "ToolbarBackground", HIBrush, kThemeBrushToolbarBackground }, /* 102 */ + { "SheetBackgroundTransparent", HIBrush, kThemeBrushSheetBackgroundTransparent }, /* 103 */ + { "MenuBackground", HIBrush, kThemeBrushMenuBackground }, /* 104 */ + { "Pixel", rgbColor, 0 }, /* 105: PIXEL_MAGIC */ + { "MenuBackgroundSelected", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 106 */ + { "ListViewOddRowBackground", HIBrush, kThemeBrushListViewOddRowBackground }, /* 107 */ + { "ListViewEvenRowBackground", HIBrush, kThemeBrushListViewEvenRowBackground }, /* 108 */ + { "ListViewColumnDivider", HIBrush, kThemeBrushListViewColumnDivider }, /* 109 */ + { "BlackText", HIText, kThemeTextColorBlack }, /* 110 */ + { "DialogActiveText", HIText, kThemeTextColorDialogActive }, /* 111 */ + { "DialogInactiveText", HIText, kThemeTextColorDialogInactive }, /* 112 */ + { "AlertActiveText", HIText, kThemeTextColorAlertActive }, /* 113 */ + { "AlertInactiveText", HIText, kThemeTextColorAlertInactive }, /* 114 */ + { "ModelessDialogActiveText", HIText, kThemeTextColorModelessDialogActive }, /* 115 */ + { "ModelessDialogInactiveText", HIText, kThemeTextColorModelessDialogInactive }, /* 116 */ + { "WindowHeaderActiveText", HIText, kThemeTextColorWindowHeaderActive }, /* 117 */ + { "WindowHeaderInactiveText", HIText, kThemeTextColorWindowHeaderInactive }, /* 118 */ + { "PlacardActiveText", HIText, kThemeTextColorPlacardActive }, /* 119 */ + { "PlacardInactiveText", HIText, kThemeTextColorPlacardInactive }, /* 120 */ + { "PlacardPressedText", HIText, kThemeTextColorPlacardPressed }, /* 121 */ + { "PushButtonActiveText", HIText, kThemeTextColorPushButtonActive }, /* 122 */ + { "PushButtonInactiveText", HIText, kThemeTextColorPushButtonInactive }, /* 123 */ + { "PushButtonPressedText", HIText, kThemeTextColorPushButtonPressed }, /* 124 */ + { "BevelButtonActiveText", HIText, kThemeTextColorBevelButtonActive }, /* 125 */ + { "BevelButtonInactiveText", HIText, kThemeTextColorBevelButtonInactive }, /* 126 */ + { "BevelButtonPressedText", HIText, kThemeTextColorBevelButtonPressed }, /* 127 */ + { "PopupButtonActiveText", HIText, kThemeTextColorPopupButtonActive }, /* 128 */ + { "PopupButtonInactiveText", HIText, kThemeTextColorPopupButtonInactive }, /* 129 */ + { "PopupButtonPressedText", HIText, kThemeTextColorPopupButtonPressed }, /* 130 */ + { "IconLabelText", HIText, kThemeTextColorIconLabel }, /* 131 */ + { "ListViewText", HIText, kThemeTextColorListView }, /* 132 */ + { "DocumentWindowTitleActiveText", HIText, kThemeTextColorDocumentWindowTitleActive }, /* 133 */ + { "DocumentWindowTitleInactiveText", HIText, kThemeTextColorDocumentWindowTitleInactive }, /* 134 */ + { "MovableModalWindowTitleActiveText", HIText, kThemeTextColorMovableModalWindowTitleActive }, /* 135 */ + { "MovableModalWindowTitleInactiveText",HIText, kThemeTextColorMovableModalWindowTitleInactive }, /* 136 */ + { "UtilityWindowTitleActiveText", HIText, kThemeTextColorUtilityWindowTitleActive }, /* 137 */ + { "UtilityWindowTitleInactiveText", HIText, kThemeTextColorUtilityWindowTitleInactive }, /* 138 */ + { "PopupWindowTitleActiveText", HIText, kThemeTextColorPopupWindowTitleActive }, /* 139 */ + { "PopupWindowTitleInactiveText", HIText, kThemeTextColorPopupWindowTitleInactive }, /* 140 */ + { "RootMenuActiveText", HIText, kThemeTextColorRootMenuActive }, /* 141 */ + { "RootMenuSelectedText", HIText, kThemeTextColorRootMenuSelected }, /* 142 */ + { "RootMenuDisabledText", HIText, kThemeTextColorRootMenuDisabled }, /* 143 */ + { "MenuItemActiveText", HIText, kThemeTextColorMenuItemActive }, /* 144 */ + { "MenuItemSelectedText", HIText, kThemeTextColorMenuItemSelected }, /* 145 */ + { "MenuItemDisabledText", HIText, kThemeTextColorMenuItemDisabled }, /* 146 */ + { "PopupLabelActiveText", HIText, kThemeTextColorPopupLabelActive }, /* 147 */ + { "PopupLabelInactiveText", HIText, kThemeTextColorPopupLabelInactive }, /* 148 */ + { "TabFrontActiveText", HIText, kThemeTextColorTabFrontActive }, /* 149 */ + { "TabNonFrontActiveText", HIText, kThemeTextColorTabNonFrontActive }, /* 150 */ + { "TabNonFrontPressedText", HIText, kThemeTextColorTabNonFrontPressed }, /* 151 */ + { "TabFrontInactiveText", HIText, kThemeTextColorTabFrontInactive }, /* 152 */ + { "TabNonFrontInactiveText", HIText, kThemeTextColorTabNonFrontInactive }, /* 153 */ + { "IconLabelSelectedText", HIText, kThemeTextColorIconLabelSelected }, /* 154 */ + { "BevelButtonStickyActiveText", HIText, kThemeTextColorBevelButtonStickyActive }, /* 155 */ + { "BevelButtonStickyInactiveText", HIText, kThemeTextColorBevelButtonStickyInactive }, /* 156 */ + { "NotificationText", HIText, kThemeTextColorNotification }, /* 157 */ + { "SystemDetailText", HIText, kThemeTextColorSystemDetail }, /* 158 */ + { "WhiteText", HIText, kThemeTextColorWhite }, /* 159 */ + { "TabPaneBackground", HIBackground, kThemeBackgroundTabPane }, /* 160 */ + { "PlacardBackground", HIBackground, kThemeBackgroundPlacard }, /* 161 */ + { "WindowHeaderBackground", HIBackground, kThemeBackgroundWindowHeader }, /* 162 */ + { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */ + { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */ + { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */ + + /* + * Colors based on "semantic" NSColors. + */ + + { "WindowBackgroundColor", ttkBackground, 0 }, /* 166 */ + { "WindowBackgroundColor1", ttkBackground, 1 }, /* 167 */ + { "WindowBackgroundColor2", ttkBackground, 2 }, /* 168 */ + { "WindowBackgroundColor3", ttkBackground, 3 }, /* 169 */ + { "WindowBackgroundColor4", ttkBackground, 4 }, /* 170 */ + { "WindowBackgroundColor5", ttkBackground, 5 }, /* 171 */ + { "WindowBackgroundColor6", ttkBackground, 6 }, /* 172 */ + { "WindowBackgroundColor7", ttkBackground, 7 }, /* 173 */ + { "TextColor", semantic, 0 }, /* 174 */ + { "SelectedTextColor", semantic, 1 }, /* 175 */ + { "LabelColor", semantic, 2 }, /* 176 */ + { "ControlTextColor", semantic, 3 }, /* 177 */ + { "DisabledControlTextColor", semantic, 4 }, /* 178 */ + { "SelectedTabTextColor", semantic, 5 }, /* 179 */ + { "TextBackgroundColor", semantic, 6 }, /* 180 */ + { "SelectedTextBackgroundColor", semantic, 7 }, /* 181 */ + { "ControlAccentColor", semantic, 8 }, /* 182 */ + { NULL, 0, 0 } }; -#define MAX_PIXELCODE 165 +#define FIRST_SEMANTIC_COLOR 166 +#define MAX_PIXELCODE 182 /* *---------------------------------------------------------------------- * - * GetThemeFromPixelCode -- + * GetEntryFromPixelCode -- * - * When given a pixel code corresponding to a theme system color, - * set one of brush, textColor or background to the corresponding - * Appearance Mgr theme constant. + * Extract a SystemColorMapEntry from the table. * * Results: - * Returns false if not a real pixel, true otherwise. + * Returns false if the code is out of bounds. * * Side effects: * None. * *---------------------------------------------------------------------- */ -static int -GetThemeFromPixelCode( +static bool +GetEntryFromPixelCode( unsigned char code, - ThemeBrush *brush, - ThemeTextColor *textColor, - ThemeBackgroundKind *background) + struct SystemColorMapEntry *entry) { if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) { - *brush = systemColorMap[code - MIN_PIXELCODE].brush; - *textColor = systemColorMap[code - MIN_PIXELCODE].textColor; - *background = systemColorMap[code - MIN_PIXELCODE].background; + *entry = systemColorMap[code - MIN_PIXELCODE]; + return true; } else { - *brush = 0; - *textColor = 0; - *background = 0; - } - if (!*brush && !*textColor && !*background && code != PIXEL_MAGIC && - code != TRANSPARENT_PIXEL) { return false; - } else { - return true; } } /* *---------------------------------------------------------------------- * - * GetThemeColor -- + * SetCGColorComponents -- * - * Get RGB color for a given system color or pixel value. + * Set the components of a CGColorRef from an XColor pixel value and a + * system color map entry. The pixel value is only used in the case where + * the color is of type rgbColor. In that case the normalized XColor RGB + * values are copied into the CGColorRef. * * Results: * OSStatus * * Side effects: @@ -228,64 +262,219 @@ * None. * *---------------------------------------------------------------------- */ +static NSColorSpace* deviceRGB = NULL; +static CGFloat blueAccentRGBA[4] = {0, 122.0 / 255, 1.0, 1.0}; +static CGFloat windowBackground[4] = + {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0}; + static OSStatus -GetThemeColor( +SetCGColorComponents( + struct SystemColorMapEntry entry, unsigned long pixel, - ThemeBrush brush, - ThemeTextColor textColor, - ThemeBackgroundKind background, CGColorRef *c) { OSStatus err = noErr; - - if (brush) { - err = ChkErr(HIThemeBrushCreateCGColor, brush, c); - /*} else if (textColor) { - err = ChkErr(GetThemeTextColor, textColor, 32, true, c);*/ - } else { - CGFloat rgba[4] = {0, 0, 0, 1}; - - switch ((pixel >> 24) & 0xff) { - case PIXEL_MAGIC: { - unsigned short red, green, blue; - red = (pixel >> 16) & 0xff; - green = (pixel >> 8) & 0xff; - blue = (pixel ) & 0xff; - red |= red << 8; - green |= green << 8; - blue |= blue << 8; - rgba[0] = red / 65535.0; - rgba[1] = green / 65535.0; - rgba[2] = blue / 65535.0; - break; - } - case TRANSPARENT_PIXEL: - rgba[3] = 0.0; - break; - } - - static CGColorSpaceRef deviceRGBSpace = NULL; - if (!deviceRGBSpace) { - deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); - } - *c = CGColorCreate(deviceRGBSpace, rgba ); - } - return err; + NSColor *bgColor, *color; + CGFloat rgba[4] = {0, 0, 0, 1}; +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 + NSInteger colorVariant; + static CGFloat graphiteAccentRGBA[4] = + {152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0}; +#endif + + if (!deviceRGB) { + deviceRGB = [NSColorSpace deviceRGBColorSpace]; + } + + /* + * This function is called before our autorelease pool is set up, + * so it needs its own pool. + */ + + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + switch (entry.type) { + case HIBrush: + err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c); + return err; + case rgbColor: + rgba[0] = ((pixel >> 16) & 0xff) / 255.0; + rgba[1] = ((pixel >> 8) & 0xff) / 255.0; + rgba[2] = ((pixel ) & 0xff) / 255.0; + break; + case ttkBackground: + + /* + * Prior to OSX 10.14, getComponents returns black when applied to + * windowBackGroundColor. + */ + + if ([NSApp macMinorVersion] < 14) { + for (int i=0; i<3; i++) { + rgba[i] = windowBackground[i]; + } + } else { + bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: + deviceRGB]; + [bgColor getComponents: rgba]; + } + if (rgba[0] + rgba[1] + rgba[2] < 1.5) { + for (int i=0; i<3; i++) { + rgba[i] += entry.value*8.0 / 255.0; + } + } else { + for (int i=0; i<3; i++) { + rgba[i] -= entry.value*8.0 / 255.0; + } + } + break; + case semantic: + switch (entry.value) { + case 0: + color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; + break; + case 1: + color = [[NSColor selectedTextColor] colorUsingColorSpace: deviceRGB]; + break; + case 2: + if ([NSApp macMinorVersion] > 9) { + color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB]; + } else { + color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; + } + break; + case 3: + color = [[NSColor controlTextColor] colorUsingColorSpace: + deviceRGB]; + break; + case 4: + color = [[NSColor disabledControlTextColor] colorUsingColorSpace: + deviceRGB]; + break; + case 5: + if ([NSApp macMinorVersion] > 6) { + color = [[NSColor whiteColor] colorUsingColorSpace: + deviceRGB]; + } else { + color = [[NSColor blackColor] colorUsingColorSpace: + deviceRGB]; + } + break; + case 6: + color = [[NSColor textBackgroundColor] colorUsingColorSpace: + deviceRGB]; + break; + case 7: + color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace: + deviceRGB]; + break; + case 8: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if (@available(macOS 10.14, *)) { + color = [[NSColor controlAccentColor] colorUsingColorSpace: + deviceRGB]; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; + } +#else + colorVariant = [[NSUserDefaults standardUserDefaults] + integerForKey:@"AppleAquaColorVariant"]; + if (colorVariant == 6) { + color = [NSColor colorWithColorSpace: deviceRGB + components: graphiteAccentRGBA + count: 4]; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; + } +#endif + break; + default: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 + if ([NSApp macMinorVersion] >= 10) { + color = [[NSColor labelColor] colorUsingColorSpace: + deviceRGB]; + break; + } +#endif + color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; + break; + } + [color getComponents: rgba]; + break; + case clearColor: + rgba[3] = 0.0; + break; + + /* + * There are no HITheme functions which convert Text or background colors + * to CGColors. (GetThemeTextColor has been removed, and it was never + * possible with backgrounds.) If we get one of these we return black. + */ + + case HIText: + case HIBackground: + default: + break; + } + *c = CGColorCreate(deviceRGB.CGColorSpace, rgba); + [pool drain]; + return err; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInDarkMode -- + * + * Tests whether the given window's NSView has a DarkAqua Appearance. + * + * Results: + * Returns true if the NSView is in DarkMode, false if not. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE Bool +TkMacOSXInDarkMode(Tk_Window tkwin) +{ + int result = false; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if ([NSApp macMinorVersion] >= 14) { + static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua"; + TkWindow *winPtr = (TkWindow*) tkwin; + NSView *view = TkMacOSXDrawableView(winPtr->privatePtr); + result = (view && + [view.effectiveAppearance.name isEqualToString:darkAqua]); + } +#endif + return result; } /* *---------------------------------------------------------------------- * * TkSetMacColor -- * - * Creates a CGColorRef from a X style pixel value. + * Sets the components of a CGColorRef from an XColor pixel value. + * The high order byte of the pixel value is used as an index into + * the system color table, and then SetCGColorComponents is called + * with the table entry and the pixel value. * * Results: - * Returns false if not a real pixel, true otherwise. + * Returns false if the high order byte is not a valid index, true + * otherwise. * * Side effects: * The variable macColor is set to a new CGColorRef, the caller is * responsible for releasing it! * @@ -297,18 +486,14 @@ unsigned long pixel, /* Pixel value to convert. */ void *macColor) /* CGColorRef to modify. */ { CGColorRef *color = (CGColorRef*)macColor; OSStatus err = -1; - ThemeBrush brush; - ThemeTextColor textColor; - ThemeBackgroundKind background; - - if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor, - &background)) { - err = ChkErr(GetThemeColor, pixel, brush, textColor, background, - color); + struct SystemColorMapEntry entry; + + if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) { + err = ChkErr(SetCGColorComponents, entry, pixel, color); } return (err == noErr); } /* @@ -319,11 +504,11 @@ * Maintain a per-GC cache of previously converted CGColorRefs * * Results: * None resp. retained CGColorRef for CopyCachedColor() * - * Side effects: + * Side effects:M * None. * *---------------------------------------------------------------------- */ @@ -448,10 +633,11 @@ NSColor *nsColor = nil; if (cgColor) { NSColorSpace *colorSpace = [[NSColorSpace alloc] initWithCGColorSpace:CGColorGetColorSpace(cgColor)]; + nsColor = [NSColor colorWithColorSpace:colorSpace components:CGColorGetComponents(cgColor) count:CGColorGetNumberOfComponents(cgColor)]; [colorSpace release]; CFRelease(cgColor); @@ -482,52 +668,60 @@ TkMacOSXSetColorInContext( GC gc, unsigned long pixel, CGContextRef context) { - OSStatus err = -1; - CGColorRef cgColor = CopyCachedColor(gc, pixel); - ThemeBrush brush; - ThemeTextColor textColor; - ThemeBackgroundKind background; - - if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, - &textColor, &background)) { - if (brush) { - err = ChkErr(HIThemeSetFill, brush, NULL, context, - kHIThemeOrientationNormal); - if (err == noErr) { - err = ChkErr(HIThemeSetStroke, brush, NULL, context, - kHIThemeOrientationNormal); - } - } else if (textColor) { - err = ChkErr(HIThemeSetTextFill, textColor, NULL, context, - kHIThemeOrientationNormal); - } else if (background) { - CGRect rect = CGContextGetClipBoundingBox(context); - HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, - background }; - - err = ChkErr(HIThemeApplyBackground, &rect, &info, - context, kHIThemeOrientationNormal); - } - if (err == noErr) { - return; - } - err = ChkErr(GetThemeColor, pixel, brush, textColor, background, - &cgColor); - if (err == noErr) { - SetCachedColor(gc, pixel, cgColor); - } - } else if (!cgColor) { - TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel); + OSStatus err = noErr; + CGColorRef cgColor = nil; + struct SystemColorMapEntry entry; + CGRect rect; + int code = (pixel >> 24) & 0xff; + HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};; + static CGColorSpaceRef deviceRGBSpace = NULL; + + if (!deviceRGBSpace) { + deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); + } + if (code < FIRST_SEMANTIC_COLOR) { + cgColor = CopyCachedColor(gc, pixel); + } + if (!cgColor && GetEntryFromPixelCode(code, &entry)) { + switch (entry.type) { + case HIBrush: + err = ChkErr(HIThemeSetFill, entry.value, NULL, context, + kHIThemeOrientationNormal); + if (err == noErr) { + err = ChkErr(HIThemeSetStroke, entry.value, NULL, context, + kHIThemeOrientationNormal); + } + break; + case HIText: + err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context, + kHIThemeOrientationNormal); + break; + case HIBackground: + info.kind = entry.value; + rect = CGContextGetClipBoundingBox(context); + err = ChkErr(HIThemeApplyBackground, &rect, &info, + context, kHIThemeOrientationNormal); + break; + default: + err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor); + if (err == noErr) { + SetCachedColor(gc, pixel, cgColor); + } + break; + } } if (cgColor) { CGContextSetFillColorWithColor(context, cgColor); CGContextSetStrokeColorWithColor(context, cgColor); CGColorRelease(cgColor); } + if (err != noErr) { + TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel); + } } /* *---------------------------------------------------------------------- * @@ -547,11 +741,11 @@ */ TkColor * TkpGetColor( Tk_Window tkwin, /* Window in which color will be used. */ - Tk_Uid name) /* Name of color to allocated (in form + Tk_Uid name) /* Name of color to be allocated (in form * suitable for passing to XParseColor). */ { Display *display = tkwin != None ? Tk_Display(tkwin) : NULL; Colormap colormap = tkwin!= None ? Tk_Colormap(tkwin) : None; TkColor *tkColPtr; @@ -559,26 +753,25 @@ /* * Check to see if this is a system color. Otherwise, XParseColor * will do all the work. */ + if (strncasecmp(name, "system", 6) == 0) { Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1); int idx, result; result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap, - sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx); + sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx); Tcl_DecrRefCount(strPtr); if (result == TCL_OK) { OSStatus err; CGColorRef c; unsigned char pixelCode = idx + MIN_PIXELCODE; - ThemeBrush brush = systemColorMap[idx].brush; - ThemeTextColor textColor = systemColorMap[idx].textColor; - ThemeBackgroundKind background = systemColorMap[idx].background; + struct SystemColorMapEntry entry = systemColorMap[idx]; - err = ChkErr(GetThemeColor, 0, brush, textColor, background, &c); + err = ChkErr(SetCGColorComponents, entry, 0, &c); if (err == noErr) { const size_t n = CGColorGetNumberOfComponents(c); const CGFloat *rgba = CGColorGetComponents(c); switch (n) { @@ -589,16 +782,16 @@ break; case 2: color.red = color.green = color.blue = rgba[0] * 65535.0; break; default: - Tcl_Panic("CGColor with %d components", (int) n); + Tcl_Panic("CGColor with %d components", (int) n); } color.pixel = ((((((pixelCode << 8) - | ((color.red >> 8) & 0xff)) << 8) - | ((color.green >> 8) & 0xff)) << 8) - | ((color.blue >> 8) & 0xff)); + | ((color.red >> 8) & 0xff)) << 8) + | ((color.green >> 8) & 0xff)) << 8) + | ((color.blue >> 8) & 0xff)); CGColorRelease(c); goto validXColor; } CGColorRelease(c); } Index: macosx/tkMacOSXConstants.h ================================================================== --- macosx/tkMacOSXConstants.h +++ macosx/tkMacOSXConstants.h @@ -77,26 +77,12 @@ #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 NSApplicationDefinedMask NSEventMaskApplicationDefined -#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground #define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow #define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel #define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow #define NSHUDWindowMask NSWindowStyleMaskHUDWindow #define NSTitledWindowMask NSWindowStyleMaskTitled Index: macosx/tkMacOSXCursor.c ================================================================== --- macosx/tkMacOSXCursor.c +++ macosx/tkMacOSXCursor.c @@ -183,20 +183,20 @@ /* * Declarations of static variables used in this file. */ -static TkMacOSXCursor * gCurrentCursor = NULL; +static TkMacOSXCursor *gCurrentCursor = NULL; /* A pointer to the current cursor. */ static int gResizeOverride = false; /* A boolean indicating whether we should use * the resize cursor during installations. */ static int gTkOwnsCursor = true;/* A boolean indicating whether Tk owns the * cursor. If not (for instance, in the case * where a Tk window is embedded in another * app's window, and the cursor is out of the - * tk window, we will not attempt to adjust + * Tk window, we will not attempt to adjust * the cursor. */ /* * Declarations of procedures local to this file */ @@ -276,10 +276,11 @@ static const CGFloat decodeWB[] = {1, 0}; CGColorSpaceRef colorspace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmap, pix*pix/8, NULL); + if (provider) { img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace, kCGBitmapByteOrderDefault, provider, decodeWB, 0, kCGRenderingIntentDefault); CFRelease(provider); @@ -297,18 +298,25 @@ if (maskedImg) { bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:maskedImg]; CFRelease(maskedImg); } - if (mask) { CFRelease(mask); } - if (img) { CFRelease(img); } - if (colorspace) { CFRelease(colorspace); } + if (mask) { + CFRelease(mask); + } + if (img) { + CFRelease(img); + } + if (colorspace) { + CFRelease(colorspace); + } if (bitmapImageRep) { image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)]; [image addRepresentation:bitmapImageRep]; [bitmapImageRep release]; } + uint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8); hotSpot.y = CFSwapInt16BigToHost(*hotSpotData++); hotSpot.x = CFSwapInt16BigToHost(*hotSpotData); haveHotSpot = 1; break; Index: macosx/tkMacOSXDefault.h ================================================================== --- macosx/tkMacOSXDefault.h +++ macosx/tkMacOSXDefault.h @@ -21,26 +21,30 @@ //#endif /* * The definitions below provide symbolic names for the default colors. * NORMAL_BG - Normal background color. + * NORMAL_FG - Normal foreground color. * ACTIVE_BG - Background color when widget is active. + * ACTIVE_FG - Foreground color when widget is active. * SELECT_BG - Background color for selected text. * SELECT_FG - Foreground color for selected text. * TROUGH - Background color for troughs in scales and scrollbars. * INDICATOR - Color for indicator when button is selected. * DISABLED - Foreground color when widget is disabled. */ #define BLACK "Black" #define WHITE "White" -#define NORMAL_BG "systemWindowBody" -#define ACTIVE_BG "systemButtonFacePressed" -#define ACTIVE_FG "systemPushButtonPressedText" -#define SELECT_BG "systemHighlight" -#define SELECT_FG NULL -#define INACTIVE_SELECT_BG "systemHighlightSecondary" +#define NORMAL_BG "systemWindowBackgroundColor" +#define TEXT_BG "systemTextBackgroundColor" +#define NORMAL_FG "systemTextColor" +#define ACTIVE_BG "systemWindowBackgroundColor" +#define ACTIVE_FG "systemTextColor" +#define SELECT_BG "systemSelectedTextBackgroundColor" +#define SELECT_FG "systemSelectedTextColor" +#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor" #define TROUGH "#c3c3c3" #define INDICATOR "#b03060" #define DISABLED "#a3a3a3" /* @@ -51,22 +55,21 @@ #define DEF_BUTTON_ACTIVE_BG_COLOR ACTIVE_BG #define DEF_BUTTON_ACTIVE_BG_MONO BLACK #define DEF_BUTTON_ACTIVE_FG_COLOR ACTIVE_FG #define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR #define DEF_BUTTON_ACTIVE_FG_MONO WHITE -/* #define DEF_BUTTON_BG_COLOR "systemButtonFace"*/ -#define DEF_BUTTON_BG_COLOR WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG #define DEF_BUTTON_BG_MONO WHITE #define DEF_BUTTON_BITMAP "" #define DEF_BUTTON_BORDER_WIDTH "2" #define DEF_BUTTON_CURSOR "" #define DEF_BUTTON_COMMAND "" #define DEF_BUTTON_COMPOUND "none" #define DEF_BUTTON_DEFAULT "disabled" #define DEF_BUTTON_DISABLED_FG_COLOR DISABLED #define DEF_BUTTON_DISABLED_FG_MONO "" -#define DEF_BUTTON_FG "systemButtonText" +#define DEF_BUTTON_FG NORMAL_FG #define DEF_CHKRAD_FG DEF_BUTTON_FG #define DEF_BUTTON_FONT "TkDefaultFont" #define DEF_BUTTON_HEIGHT "0" #define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR #define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO @@ -167,36 +170,35 @@ #define MAC_OSX_FOCUS_WIDTH 3 #define MAC_OSX_ENTRY_BORDER 2 #define MAC_OSX_ENTRY_RELIEF TK_RELIEF_SUNKEN #define MAC_OSX_ENTRY_SELECT_RELIEF TK_RELIEF_FLAT -#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_COLOR TEXT_BG #define DEF_ENTRY_BG_MONO WHITE #define DEF_ENTRY_BORDER_WIDTH "2" #define DEF_ENTRY_CURSOR "xterm" #define DEF_ENTRY_DISABLED_BG_COLOR NORMAL_BG #define DEF_ENTRY_DISABLED_BG_MONO WHITE #define DEF_ENTRY_DISABLED_FG DISABLED #define DEF_ENTRY_EXPORT_SELECTION "1" #define DEF_ENTRY_FONT "TkTextFont" -#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_FG NORMAL_FG #define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG #define DEF_ENTRY_HIGHLIGHT BLACK -/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" -#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BG NORMAL_FG #define DEF_ENTRY_INSERT_BD_COLOR "0" #define DEF_ENTRY_INSERT_BD_MONO "0" #define DEF_ENTRY_INSERT_OFF_TIME "300" #define DEF_ENTRY_INSERT_ON_TIME "600" -/* #define DEF_ENTRY_INSERT_WIDTH "2" */ #define DEF_ENTRY_INSERT_WIDTH "1" #define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_PLACEHOLDER "" +#define DEF_ENTRY_PLACEHOLDERFG "#b3b3b3" #define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG #define DEF_ENTRY_READONLY_BG_MONO WHITE #define DEF_ENTRY_RELIEF "sunken" -/* #define DEF_ENTRY_RELIEF "solid" */ #define DEF_ENTRY_SCROLL_COMMAND "" #define DEF_ENTRY_SELECT_COLOR SELECT_BG #define DEF_ENTRY_SELECT_MONO BLACK #define DEF_ENTRY_SELECT_BD_COLOR "1" #define DEF_ENTRY_SELECT_BD_MONO "0" @@ -211,11 +213,13 @@ /* * Defaults for frames: */ #define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_IMAGE NULL #define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BG_TILE "0" #define DEF_FRAME_BORDER_WIDTH "0" #define DEF_FRAME_CLASS "Frame" #define DEF_FRAME_COLORMAP "" #define DEF_FRAME_CONTAINER "0" #define DEF_FRAME_CURSOR "" @@ -235,28 +239,28 @@ */ #define DEF_LABELFRAME_BORDER_WIDTH "2" #define DEF_LABELFRAME_CLASS "Labelframe" #define DEF_LABELFRAME_RELIEF "groove" -#define DEF_LABELFRAME_FG "systemButtonText" +#define DEF_LABELFRAME_FG NORMAL_FG #define DEF_LABELFRAME_FONT "TkDefaultFont" #define DEF_LABELFRAME_TEXT "" #define DEF_LABELFRAME_LABELANCHOR "nw" /* * Defaults for listboxes: */ #define DEF_LISTBOX_ACTIVE_STYLE "dotbox" -#define DEF_LISTBOX_BG_COLOR WHITE +#define DEF_LISTBOX_BG_COLOR TEXT_BG #define DEF_LISTBOX_BG_MONO WHITE #define DEF_LISTBOX_BORDER_WIDTH "1" #define DEF_LISTBOX_CURSOR "" #define DEF_LISTBOX_DISABLED_FG DISABLED #define DEF_LISTBOX_EXPORT_SELECTION "1" #define DEF_LISTBOX_FONT "TkTextFont" -#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_FG NORMAL_FG #define DEF_LISTBOX_HEIGHT "10" #define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG #define DEF_LISTBOX_HIGHLIGHT BLACK #define DEF_LISTBOX_HIGHLIGHT_WIDTH "0" #define DEF_LISTBOX_JUSTIFY "left" @@ -310,10 +314,11 @@ #define DEF_MENU_ACTIVE_BG_COLOR "systemMenuActive" #define DEF_MENU_ACTIVE_BG_MONO BLACK #define DEF_MENU_ACTIVE_BORDER_WIDTH "0" #define DEF_MENU_ACTIVE_FG_COLOR "systemMenuActiveText" #define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_ACTIVE_RELIEF "flat" #define DEF_MENU_BG_COLOR "systemMenu" #define DEF_MENU_BG_MONO WHITE #define DEF_MENU_BORDER_WIDTH "0" #define DEF_MENU_CURSOR "arrow" #define DEF_MENU_DISABLED_FG_COLOR "systemMenuDisabled" @@ -332,36 +337,36 @@ /* * Defaults for menubuttons: */ -#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ANCHOR "w" #define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG -#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_BG_MONO WHITE #define DEF_MENUBUTTON_ACTIVE_FG_COLOR ACTIVE_FG -#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_ACTIVE_FG_MONO BLACK #define DEF_MENUBUTTON_BG_COLOR NORMAL_BG #define DEF_MENUBUTTON_BG_MONO WHITE #define DEF_MENUBUTTON_BITMAP "" -#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_BORDER_WIDTH "0" #define DEF_MENUBUTTON_CURSOR "" #define DEF_MENUBUTTON_DIRECTION "below" #define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED #define DEF_MENUBUTTON_DISABLED_FG_MONO "" #define DEF_MENUBUTTON_FONT "TkDefaultFont" -#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_FG NORMAL_FG #define DEF_MENUBUTTON_HEIGHT "0" #define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR #define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO #define DEF_MENUBUTTON_HIGHLIGHT BLACK #define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" #define DEF_MENUBUTTON_IMAGE NULL #define DEF_MENUBUTTON_INDICATOR "1" #define DEF_MENUBUTTON_JUSTIFY "left" #define DEF_MENUBUTTON_MENU "" -#define DEF_MENUBUTTON_PADX "4" -#define DEF_MENUBUTTON_PADY "3" +#define DEF_MENUBUTTON_PADX "0" +#define DEF_MENUBUTTON_PADY "0" #define DEF_MENUBUTTON_RELIEF "flat" #define DEF_MENUBUTTON_STATE "normal" #define DEF_MENUBUTTON_TAKE_FOCUS "0" #define DEF_MENUBUTTON_TEXT "" #define DEF_MENUBUTTON_TEXT_VARIABLE "" @@ -377,11 +382,11 @@ #define DEF_MESSAGE_ASPECT "150" #define DEF_MESSAGE_BG_COLOR NORMAL_BG #define DEF_MESSAGE_BG_MONO WHITE #define DEF_MESSAGE_BORDER_WIDTH "1" #define DEF_MESSAGE_CURSOR "" -#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FG NORMAL_FG #define DEF_MESSAGE_FONT "TkDefaultFont" #define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG #define DEF_MESSAGE_HIGHLIGHT BLACK #define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" #define DEF_MESSAGE_JUSTIFY "left" @@ -441,11 +446,11 @@ #define DEF_SCALE_BORDER_WIDTH "1" #define DEF_SCALE_COMMAND "" #define DEF_SCALE_CURSOR "" #define DEF_SCALE_DIGITS "0" #define DEF_SCALE_FONT "TkDefaultFont" -#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_COLOR NORMAL_FG #define DEF_SCALE_FG_MONO BLACK #define DEF_SCALE_FROM "0" #define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR #define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO #define DEF_SCALE_HIGHLIGHT BLACK @@ -498,23 +503,23 @@ /* * Defaults for texts: */ #define DEF_TEXT_AUTO_SEPARATORS "1" -#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_COLOR TEXT_BG #define DEF_TEXT_BG_MONO WHITE #define DEF_TEXT_BLOCK_CURSOR "0" #define DEF_TEXT_BORDER_WIDTH "0" #define DEF_TEXT_CURSOR "xterm" -#define DEF_TEXT_FG BLACK +#define DEF_TEXT_FG NORMAL_FG #define DEF_TEXT_EXPORT_SELECTION "1" #define DEF_TEXT_FONT "TkFixedFont" #define DEF_TEXT_HEIGHT "24" #define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG #define DEF_TEXT_HIGHLIGHT BLACK #define DEF_TEXT_HIGHLIGHT_WIDTH "3" -#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BG NORMAL_FG #define DEF_TEXT_INSERT_BD_COLOR "0" #define DEF_TEXT_INSERT_BD_MONO "0" #define DEF_TEXT_INSERT_OFF_TIME "300" #define DEF_TEXT_INSERT_ON_TIME "600" #define DEF_TEXT_INSERT_UNFOCUSSED "none" Index: macosx/tkMacOSXDialog.c ================================================================== --- macosx/tkMacOSXDialog.c +++ macosx/tkMacOSXDialog.c @@ -20,35 +20,43 @@ #define modalOK NSOKButton #define modalCancel NSCancelButton #else #define modalOK NSModalResponseOK #define modalCancel NSModalResponseCancel -#endif +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090 #define modalOther -1 #define modalError -2 -/*Vars for filtering in "open file" and "save file" dialogs.*/ +/* + * Vars for filtering in "open file" and "save file" dialogs. + */ + typedef struct { - bool doFileTypes; // show the accessory view which displays the filter menu - bool preselectFilter; // a filter was selected by the typevariable - bool userHasSelectedFilter; // The user has changed the filter in the accessory view - - NSMutableArray *fileTypeNames; // array of names, e.g. "Text document" - NSMutableArray *fileTypeExtensions; // array of allowed extensions per name, e.g. "txt", "doc" - NSMutableArray *fileTypeLabels; // displayed string, e.g. "Text document (.txt, .doc)" - NSMutableArray *fileTypeAllowsAll; // boolean if the all pattern (*.*) is included - - NSMutableArray *allowedExtensions; // set of all allowed extensions - bool allowedExtensionsAllowAll; // set of all allowed extensions includes *.* - - NSUInteger fileTypeIndex; // index of currently selected filter + bool doFileTypes; /* Show the accessory view which + * displays the filter menu */ + bool preselectFilter; /* A filter was selected by the + * typevariable. */ + bool userHasSelectedFilter; /* The user has changed the filter in + * the accessory view. */ + NSMutableArray *fileTypeNames; /* Array of names, e.g. "Text + * document". */ + NSMutableArray *fileTypeExtensions; /* Array of allowed extensions per + * name, e.g. "txt", "doc". */ + NSMutableArray *fileTypeLabels; /* Displayed string, e.g. "Text + * document (.txt, .doc)". */ + NSMutableArray *fileTypeAllowsAll; /* Boolean if the all pattern (*.*) is + * included. */ + NSMutableArray *allowedExtensions; /* Set of all allowed extensions. */ + bool allowedExtensionsAllowAll; /* Set of all allowed extensions + * includes *.* */ + NSUInteger fileTypeIndex; /* Index of currently selected + * filter. */ } filepanelFilterInfo; -filepanelFilterInfo filterInfo; - -NSOpenPanel *openpanel; -NSSavePanel *savepanel; +static filepanelFilterInfo filterInfo; +static NSOpenPanel *openpanel; +static NSSavePanel *savepanel; static const char *const colorOptionStrings[] = { "-initialcolor", "-parent", "-title", NULL }; enum colorOptions { @@ -164,14 +172,19 @@ [TYPE_YESNO] = {6, 5, 0}, [TYPE_YESNOCANCEL] = {6, 5, 4}, }; /* - * Construct a file URL from directory and filename. Either may - * be nil. If both are nil, returns nil. + * Construct a file URL from directory and filename. Either may be nil. If both + * are nil, returns nil. */ -static NSURL *getFileURL(NSString *directory, NSString *filename) { + +static NSURL * +getFileURL( + NSString *directory, + NSString *filename) +{ NSURL *url = nil; if (directory) { url = [NSURL fileURLWithPath:directory isDirectory:YES]; } if (filename) { @@ -227,11 +240,10 @@ Tcl_DecrRefCount(callbackInfo->cmdObj); ckfree(callbackInfo); } } - - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo { AlertCallbackInfo *callbackInfo = contextInfo; @@ -270,16 +282,22 @@ NSPopUpButton *button = (NSPopUpButton *)sender; filterInfo.fileTypeIndex = [button indexOfSelectedItem]; if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) { [openpanel setAllowsOtherFileTypes:YES]; - /* setAllowsOtherFileTypes might have no effect; it's inherited from the - * NSSavePanel, where it has the effect that it does not append an extension - * Setting the allowed file types to nil allows selecting any file */ + + /* + * setAllowsOtherFileTypes might have no effect; it's inherited from + * the NSSavePanel, where it has the effect that it does not append an + * extension. Setting the allowed file types to nil allows selecting + * any file. + */ + [openpanel setAllowedFileTypes:nil]; } else { - NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; + NSMutableArray *allowedtypes = + [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; [openpanel setAllowedFileTypes:allowedtypes]; [openpanel setAllowsOtherFileTypes:NO]; } filterInfo.userHasSelectedFilter = true; @@ -291,11 +309,12 @@ if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) { [savepanel setAllowsOtherFileTypes:YES]; [savepanel setAllowedFileTypes:nil]; } else { - NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; + NSMutableArray *allowedtypes = + [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; [savepanel setAllowedFileTypes:allowedtypes]; [savepanel setAllowsOtherFileTypes:NO]; } filterInfo.userHasSelectedFilter = true; @@ -382,10 +401,11 @@ [colorPanel setBecomesKeyOnlyIfNeeded:NO]; [colorPanel setShowsAlpha: NO]; [colorPanel _setUseModalAppearance:YES]; if (title) { NSString *s = [[NSString alloc] initWithUTF8String:title]; + [colorPanel setTitle:s]; [s release]; } if (initialColor) { [colorPanel setColor:initialColor]; @@ -413,20 +433,29 @@ end: return result; } -/* dissect the -filetype nested lists and store the information - * in the filterInfo structure */ -int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVariablePtr) { +/* + * Dissect the -filetype nested lists and store the information in the + * filterInfo structure. + */ + +static int +parseFileFilters( + Tcl_Interp *interp, + Tcl_Obj *fileTypesPtr, + Tcl_Obj *typeVariablePtr) +{ if (!fileTypesPtr) { filterInfo.doFileTypes = false; return TCL_OK; } FileFilterList fl; + TkInitFileFilters(&fl); if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) { TkFreeFileFilters(&fl); return TCL_ERROR; } @@ -443,15 +472,16 @@ filterInfo.allowedExtensionsAllowAll = NO; if (filterInfo.doFileTypes) { for (FileFilter *filterPtr = fl.filters; filterPtr; filterPtr = filterPtr->next) { - NSString * name = [[NSString alloc] initWithUTF8String: filterPtr -> name]; + NSString *name = [[NSString alloc] initWithUTF8String: filterPtr->name]; + [filterInfo.fileTypeNames addObject:name]; [name release]; - NSMutableArray * clauseextensions = [NSMutableArray array]; - NSMutableArray * displayextensions = [NSMutableArray array]; + NSMutableArray *clauseextensions = [NSMutableArray array]; + NSMutableArray *displayextensions = [NSMutableArray array]; bool allowsAll = NO; for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; clausePtr = clausePtr->next) { @@ -458,11 +488,11 @@ for (GlobPattern *globPtr = clausePtr->patterns; globPtr; globPtr = globPtr->next) { const char *str = globPtr->pattern; while (*str && (*str == '*' || *str == '.')) { str++; - } + } if (*str) { NSString *extension = [[NSString alloc] initWithUTF8String:str]; if (![filterInfo.allowedExtensions containsObject:extension]) { [filterInfo.allowedExtensions addObject:extension]; } @@ -470,41 +500,56 @@ [clauseextensions addObject:extension]; [displayextensions addObject:[@"." stringByAppendingString:extension]]; [extension release]; } else { - // it is the all pattern (*, .* or *.*) + /* + * It is the all pattern (*, .* or *.*) + */ + allowsAll = YES; filterInfo.allowedExtensionsAllowAll = YES; [displayextensions addObject:@"*"]; } } } [filterInfo.fileTypeExtensions addObject:clauseextensions]; [filterInfo.fileTypeAllowsAll addObject:[NSNumber numberWithBool:allowsAll]]; - NSMutableString * label = [[NSMutableString alloc] initWithString:name]; + NSMutableString *label = [[NSMutableString alloc] initWithString:name]; [label appendString:@" ("]; [label appendString:[displayextensions componentsJoinedByString:@", "]]; [label appendString:@")"]; [filterInfo.fileTypeLabels addObject:label]; [label release]; - } - /* Check if the typevariable exists and matches one of the names */ + /* + * Check if the typevariable exists and matches one of the names. + */ + filterInfo.preselectFilter = false; filterInfo.userHasSelectedFilter = false; if (typeVariablePtr) { - /* extract the variable content as a NSString */ - Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, typeVariablePtr, NULL, TCL_GLOBAL_ONLY); + /* + * Extract the variable content as a NSString. + */ - /* check that the typevariable exists */ + Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, + typeVariablePtr, NULL, TCL_GLOBAL_ONLY); + + /* + * Check that the typevariable exists. + */ + if (selectedFileTypeObj != NULL) { - const char *selectedFileType = Tcl_GetString(selectedFileTypeObj); - NSString *selectedFileTypeStr = [[NSString alloc] initWithUTF8String:selectedFileType]; - NSUInteger index = [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr]; + const char *selectedFileType = + Tcl_GetString(selectedFileTypeObj); + NSString *selectedFileTypeStr = + [[NSString alloc] initWithUTF8String:selectedFileType]; + NSUInteger index = + [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr]; if (index != NSNotFound) { filterInfo.fileTypeIndex = index; filterInfo.preselectFilter = true; } @@ -515,21 +560,28 @@ TkFreeFileFilters(&fl); return TCL_OK; } -bool filterCompatible(NSString *extension, int filterIndex) { - NSMutableArray *allowedExtensions = [filterInfo.fileTypeExtensions objectAtIndex: filterIndex]; +static bool +filterCompatible( + NSString *extension, + int filterIndex) +{ + NSMutableArray *allowedExtensions = + [filterInfo.fileTypeExtensions objectAtIndex: filterIndex]; - /* If this contains the all pattern, accept any extension */ + /* + * If this contains the all pattern, accept any extension. + */ + if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterIndex] boolValue]) { return true; } return [allowedExtensions containsObject: extension]; } - /* *---------------------------------------------------------------------- * * Tk_GetOpenFileObjCmd -- @@ -629,17 +681,20 @@ } if (title) { [openpanel setTitle:title]; - /* From OSX 10.11, the title string is silently ignored in the open panel. - * Prepend the title to the message in this case - * NOTE should be conditional on OSX version, but - * -mmacosx-version-min does not revert this behaviour*/ + /* + * From OSX 10.11, the title string is silently ignored in the open + * panel. Prepend the title to the message in this case. NOTE should + * be conditional on OSX version, but -mmacosx-version-min does not + * revert this behaviour + */ if (message) { - NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; + NSString *fullmessage = + [[NSString alloc] initWithFormat:@"%@\n%@", title, message]; [message release]; [title release]; message = fullmessage; } else { message = title; @@ -656,30 +711,41 @@ if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) { goto end; } if (filterInfo.doFileTypes) { - NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; - NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + NSView *accessoryView = [[NSView alloc] + initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; + NSTextField *label = [[NSTextField alloc] + initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; [label setStringValue:@"Filter:"]; [label setBordered:NO]; [label setBezeled:NO]; [label setDrawsBackground:NO]; - NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO]; + NSPopUpButton *popupButton = [[NSPopUpButton alloc] + initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; [popupButton setAction:@selector(selectFormat:)]; [accessoryView addSubview:label]; [accessoryView addSubview:popupButton]; if (filterInfo.preselectFilter) { - /* A specific filter was selected from the typevariable. Select it and - * open the accessory view */ + /* + * A specific filter was selected from the typevariable. Select it + * and open the accessory view. + */ + [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; - /* on OSX > 10.11, the optons are not visible by default. Ergo allow all file types + + /* + * On OSX > 10.11, the options are not visible by default. Ergo + * allow all file types [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]]; */ [openpanel setAllowedFileTypes:filterInfo.allowedExtensions]; } else { [openpanel setAllowedFileTypes:filterInfo.allowedExtensions]; @@ -691,11 +757,14 @@ [openpanel setAllowsOtherFileTypes:NO]; } [openpanel setAccessoryView:accessoryView]; } else { - /* No filters are given. Allow picking all files */ + /* + * No filters are given. Allow picking all files. + */ + [openpanel setAllowsOtherFileTypes:YES]; } if (cmdObj) { callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo)); @@ -709,24 +778,28 @@ callbackInfo->interp = interp; callbackInfo->multiple = multiple; parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; - if (directory || filename ) { - NSURL * fileURL = getFileURL(directory, filename); + if (directory || filename) { + NSURL *fileURL = getFileURL(directory, filename); + [openpanel setDirectoryURL:fileURL]; } [openpanel beginSheetModalForWindow:parent - completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:openpanel + completionHandler:^(NSInteger returnCode) { + [NSApp tkFilePanelDidEnd:openpanel returnCode:returnCode - contextInfo:callbackInfo ]; } ]; - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel]; + contextInfo:callbackInfo ]; + }]; + modalReturnCode = cmdObj ? modalOther : + [NSApp runModalForWindow:openpanel]; } else { - if (directory || filename ) { - NSURL * fileURL = getFileURL(directory, filename); + if (directory || filename) { + NSURL *fileURL = getFileURL(directory, filename); + [openpanel setDirectoryURL:fileURL]; } modalReturnCode = [openpanel runModal]; [NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode @@ -735,42 +808,54 @@ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (parentIsKey) { [parent makeKeyWindow]; } - if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && - filterInfo.doFileTypes) { + if ((typeVariablePtr && (modalReturnCode == NSOKButton)) + && filterInfo.doFileTypes) { /* - * The -typevariable must be set to the selected file type, if the dialog was not cancelled + * The -typevariable must be set to the selected file type, if the + * dialog was not cancelled. */ + NSUInteger selectedFilterIndex = filterInfo.fileTypeIndex; NSString *selectedFilter = NULL; + if (filterInfo.userHasSelectedFilter) { selectedFilterIndex = filterInfo.fileTypeIndex; selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex]; } else { - /* Difficult case: the user has not touched the filter settings, but we must - * return something in the typevariable. First check if the preselected type is compatible - * with the selected file, otherwise choose the first compatible type from the list, - * finally fall back to the empty string */ + /* + * Difficult case: the user has not touched the filter settings, + * but we must return something in the typevariable. First check if + * the preselected type is compatible with the selected file, + * otherwise choose the first compatible type from the list, + * finally fall back to the empty string. + */ + NSURL *selectedFile; + if (multiple) { - // Use the first file in the case of multiple selection - // Anyway it is not overly useful here + /* + * Use the first file in the case of multiple selection. + * Anyway it is not overly useful here. + */ selectedFile = [[openpanel URLs] objectAtIndex:0]; } else { selectedFile = [openpanel URL]; } NSString *extension = [selectedFile pathExtension]; + if (filterInfo.preselectFilter && - filterCompatible(extension, filterInfo.fileTypeIndex)) { + filterCompatible(extension, filterInfo.fileTypeIndex)) { selectedFilterIndex = filterInfo.fileTypeIndex; // The preselection from the typevariable selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex]; } else { // scan the list NSUInteger i; + for (i = 0; i < [filterInfo.fileTypeNames count]; i++) { if (filterCompatible(extension, i)) { selectedFilterIndex = i; break; } @@ -778,23 +863,21 @@ if (i == selectedFilterIndex) { selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex]; } else { selectedFilter = @""; } - } } Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, - Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); + Tcl_NewStringObj([selectedFilter UTF8String], -1), + TCL_GLOBAL_ONLY); } - end: return result; } - /* *---------------------------------------------------------------------- * * Tk_GetSaveFileObjCmd -- @@ -805,10 +888,11 @@ * Results: * A standard Tcl result. * * Side effects: * See user documentation. + * *---------------------------------------------------------------------- */ int Tk_GetSaveFileObjCmd( @@ -826,11 +910,11 @@ FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; NSString *directory = nil, *filename = nil, *defaultType = nil; NSString *message = nil, *title = nil; NSWindow *parent; - savepanel = [NSSavePanel savePanel]; + savepanel = [NSSavePanel savePanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; for (i = 1; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings, @@ -904,17 +988,21 @@ } if (title) { [savepanel setTitle:title]; - /* From OSX 10.11, the title string is silently ignored, if the save panel is a sheet. - * Prepend the title to the message in this case - * NOTE should be conditional on OSX version, but - * -mmacosx-version-min does not revert this behaviour*/ + /* + * From OSX 10.11, the title string is silently ignored, if the save + * panel is a sheet. Prepend the title to the message in this case. + * NOTE: should be conditional on OSX version, but -mmacosx-version-min + * does not revert this behaviour. + */ + if (haveParentOption) { if (message) { - NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; + NSString *fullmessage = + [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; [message release]; [title release]; message = fullmessage; } else { message = title; @@ -930,19 +1018,24 @@ if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) { goto end; } if (filterInfo.doFileTypes) { - NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; - NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + NSView *accessoryView = [[NSView alloc] + initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; + NSTextField *label = [[NSTextField alloc] + initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; [label setStringValue:NSLocalizedString(@"Format:", nil)]; [label setBordered:NO]; [label setBezeled:NO]; [label setDrawsBackground:NO]; - NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO]; + NSPopUpButton *popupButton = [[NSPopUpButton alloc] + initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; [popupButton setAction:@selector(saveFormat:)]; [accessoryView addSubview:label]; @@ -951,14 +1044,18 @@ [savepanel setAccessoryView:accessoryView]; [savepanel setAllowedFileTypes:[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]]; [savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll]; } 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 */ + /* + * 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]; [savepanel setAllowsOtherFileTypes:YES]; } @@ -976,31 +1073,43 @@ callbackInfo->interp = interp; callbackInfo->multiple = 0; parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { - parentIsKey = [parent isKeyWindow]; - if (directory) { + parentIsKey = [parent isKeyWindow]; + if (directory) { [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; } - /*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/ + + /* + * Check for file name, otherwise set to empty string; crashes with + * uncaught exception if set to nil. + */ + if (filename) { [savepanel setNameFieldStringValue:filename]; } else { [savepanel setNameFieldStringValue:@""]; } [savepanel beginSheetModalForWindow:parent - completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:savepanel + completionHandler:^(NSInteger returnCode) { + [NSApp tkFilePanelDidEnd:savepanel returnCode:returnCode - contextInfo:callbackInfo ]; } ]; - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:savepanel]; + contextInfo:callbackInfo]; + }]; + modalReturnCode = cmdObj ? modalOther : + [NSApp runModalForWindow:savepanel]; } else { if (directory) { [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; } - /*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/ + + /* + * Check for file name, otherwise set to empty string; crashes with + * uncaught exception if set to nil. + */ + if (filename) { [savepanel setNameFieldStringValue:filename]; } else { [savepanel setNameFieldStringValue:@""]; } @@ -1011,19 +1120,23 @@ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (parentIsKey) { [parent makeKeyWindow]; } - if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) { + if (typeVariablePtr && (modalReturnCode == NSOKButton) + && filterInfo.doFileTypes) { /* - * The -typevariable must be set to the selected file type, if the dialog was not cancelled + * The -typevariable must be set to the selected file type, if the + * dialog was not cancelled. */ - NSString * selectedFilter = [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex]; + + NSString *selectedFilter = + [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex]; Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, - Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); + Tcl_NewStringObj([selectedFilter UTF8String], -1), + TCL_GLOBAL_ONLY); } - end: return result; } @@ -1128,23 +1241,29 @@ Tcl_IncrRefCount(cmdObj); } callbackInfo->cmdObj = cmdObj; callbackInfo->interp = interp; callbackInfo->multiple = 0; - /*check for directory value, set to root if not specified; otherwise crashes with exception because of nil string parameter*/ + + /* + * Check for directory value, set to root if not specified; otherwise + * crashes with exception because of nil string parameter. + */ + if (!directory) { directory = @"/"; } parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; [panel beginSheetModalForWindow:parent - completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel - returnCode:returnCode - contextInfo:callbackInfo ]; } ]; + completionHandler:^(NSInteger returnCode) { + [NSApp tkFilePanelDidEnd:panel + returnCode:returnCode + contextInfo:callbackInfo]; + }]; modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; } else { [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; modalReturnCode = [panel runModal]; [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode @@ -1199,15 +1318,16 @@ * This replaces the old about dialog with a standard alert that displays * correctly on 10.14. */ NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL; - NSString *url = @"www.tcl-lang.org"; + NSString *url = @"www.tcl-lang.org"; NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)]; NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; + [credits insertText: [[NSAttributedString alloc] initWithString:[NSString stringWithFormat: @"\n" "Tcl and Tk are distributed under a modified BSD license: " "www.tcl.tk/software/tcltk/license.html\n\n" "%1$C 1987-%2$@ Tcl Core Team and Contributers.\n\n" @@ -1217,15 +1337,17 @@ "%1$C 2001-2009 Apple Inc.\n\n" "%1$C 2001-2002 Jim Ingham & Ian Reid\n\n" "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n" "%1$C 1998-2000 Scriptics Inc.\n\n" "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] - attributes:textAttributes] - replacementRange:NSMakeRange(0,0)]; + attributes:textAttributes] + replacementRange:NSMakeRange(0,0)]; [credits setDrawsBackground:NO]; [credits setEditable:NO]; - NSAlert *about = [[NSAlert alloc] init]; + + NSAlert *about = [[NSAlert alloc] init]; + [[about window] setTitle:@"About Tcl & Tk"]; [about setMessageText: version]; [about setInformativeText:url]; about.accessoryView = credits; [about runModal]; @@ -1376,11 +1498,12 @@ * Any '-default' option needs to know the '-type' option, which is * why we do this here. */ if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1], - alertButtonStrings, sizeof(char *), "-default value", TCL_EXACT, &index) != TCL_OK) { + alertButtonStrings, sizeof(char *), "-default value", + TCL_EXACT, &index) != TCL_OK) { goto end; } /* * Need to map from "ok" etc. to 1, 2, 3, right to left. @@ -1397,11 +1520,11 @@ } [alert setIcon:[NSApp applicationIconImage]]; [alert setAlertStyle:alertStyles[iconIndex]]; i = 0; while (i < 3 && alertButtonNames[typeIndex][i]) { - [alert addButtonWithTitle:(NSString*)alertButtonNames[typeIndex][i++]]; + [alert addButtonWithTitle:(NSString*) alertButtonNames[typeIndex][i++]]; } buttons = [alert buttons]; for (NSButton *b in buttons) { NSString *ke = [b keyEquivalent]; @@ -1426,14 +1549,15 @@ parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED > 1090 [alert beginSheetModalForWindow:parent - completionHandler:^(NSModalResponse returnCode) - { [NSApp tkAlertDidEnd:alert - returnCode:returnCode - contextInfo:callbackInfo ]; } ]; + completionHandler:^(NSModalResponse returnCode) { + [NSApp tkAlertDidEnd:alert + returnCode:returnCode + contextInfo:callbackInfo]; + }]; #else [alert beginSheetModalForWindow:parent modalDelegate:NSApp didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; @@ -1469,11 +1593,14 @@ Tcl_Obj *titleObj; Tcl_Obj *cmdObj; Tk_Window parent; } FontchooserData; -enum FontchooserEvent { FontchooserClosed, FontchooserSelection }; +enum FontchooserEvent { + FontchooserClosed, + FontchooserSelection +}; static void FontchooserEvent(int kind); static Tcl_Obj * FontchooserCget(FontchooserData *fcdPtr, int optionIndex); static int FontchooserConfigureCmd(ClientData clientData, @@ -1561,12 +1688,12 @@ /* *---------------------------------------------------------------------- * * FontchooserEvent -- * - * This processes events generated by user interaction with the - * font panel. + * This processes events generated by user interaction with the font + * panel. * * Results: * None. * * Side effects: @@ -1621,13 +1748,12 @@ /* *---------------------------------------------------------------------- * * FontchooserCget -- * - * Helper for the FontchooserConfigure command to return the - * current value of any of the options (which may be NULL in - * the structure) + * Helper for the FontchooserConfigure command to return the current value + * of any of the options (which may be NULL in the structure). * * Results: * Tcl object of option value. * * Side effects: @@ -1672,12 +1798,12 @@ } else { resObj = Tcl_NewObj(); } break; case FontchooserVisible: - resObj = Tcl_NewBooleanObj([[[NSFontManager sharedFontManager] - fontPanel:NO] isVisible]); + resObj = Tcl_NewWideIntObj([[[NSFontManager sharedFontManager] + fontPanel:NO] isVisible] != 0); break; default: resObj = Tcl_NewObj(); } return resObj; @@ -1686,12 +1812,12 @@ /* * ---------------------------------------------------------------------- * * FontchooserConfigureCmd -- * - * Implementation of the 'tk fontchooser configure' ensemble command. - * See the user documentation for what it does. + * Implementation of the 'tk fontchooser configure' ensemble command. See + * the user documentation for what it does. * * Results: * See the user documentation. * * Side effects: @@ -1820,11 +1946,12 @@ [fp setPanelFont:fontPanelFont isMultiple:NO]; [fm setSelectedFont:fontPanelFont isMultiple:NO]; [fm setSelectedAttributes:fontPanelFontAttributes isMultiple:NO]; if ([fp isVisible]) { - TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL); + TkSendVirtualEvent(fcdPtr->parent, + "TkFontchooserFontChanged", NULL); } break; case FontchooserCmd: if (fcdPtr->cmdObj) { Tcl_DecrRefCount(fcdPtr->cmdObj); @@ -1848,13 +1975,13 @@ /* * ---------------------------------------------------------------------- * * FontchooserShowCmd -- * - * Implements the 'tk fontchooser show' ensemble command. The - * per-interp configuration data for the dialog is held in an interp - * associated structure. + * Implements the 'tk fontchooser show' ensemble command. The per-interp + * configuration data for the dialog is held in an interp associated + * structure. * * Results: * See the user documentation. * * Side effects: @@ -1876,12 +2003,14 @@ if (fcdPtr->parent == None) { fcdPtr->parent = (Tk_Window) clientData; Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask, FontchooserParentEventHandler, fcdPtr); } + NSFontManager *fm = [NSFontManager sharedFontManager]; NSFontPanel *fp = [fm fontPanel:YES]; + if ([fp delegate] != NSApp) { [fp setDelegate:NSApp]; } if (![fp isVisible]) { [fm orderFrontFontPanel:NSApp]; @@ -1895,12 +2024,12 @@ /* * ---------------------------------------------------------------------- * * FontchooserHideCmd -- * - * Implementation of the 'tk fontchooser hide' ensemble. See the - * user documentation for details. + * Implementation of the 'tk fontchooser hide' ensemble. See the user + * documentation for details. * * Results: * See the user documentation. * * Side effects: @@ -1915,10 +2044,11 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO]; + if ([fp isVisible]) { [fp orderOut:NSApp]; } return TCL_OK; } @@ -1948,11 +2078,11 @@ FontchooserData *fcdPtr = clientData; if (eventPtr->type == DestroyNotify) { Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask, FontchooserParentEventHandler, fcdPtr); - fcdPtr->parent = None; + fcdPtr->parent = NULL; FontchooserHideCmd(NULL, NULL, 0, NULL); } } /* @@ -1995,12 +2125,12 @@ /* * ---------------------------------------------------------------------- * * TkInitFontchooser -- * - * Associate the font chooser configuration data with the Tcl - * interpreter. There is one font chooser per interp. + * Associate the font chooser configuration data with the Tcl interpreter. + * There is one font chooser per interp. * * Results: * None. * * Side effects: Index: macosx/tkMacOSXDraw.c ================================================================== --- macosx/tkMacOSXDraw.c +++ macosx/tkMacOSXDraw.c @@ -1,11 +1,10 @@ /* * tkMacOSXDraw.c -- * - * This file contains functions that perform drawing to - * Xlib windows. Most of the functions simple emulate - * Xlib functions. + * This file contains functions that perform drawing to Xlib windows. Most + * of the functions simply emulate Xlib functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright 2014 Marc Culler. @@ -29,20 +28,20 @@ #define TK_MAC_DEBUG_DRAWING #define TK_MAC_DEBUG_IMAGE_DRAWING #endif */ -#define radians(d) ((d) * (M_PI/180.0)) +#define radians(d) ((d) * (M_PI/180.0)) /* * Non-antialiased CG drawing looks better and more like X11 drawing when using * very fine lines, so decrease all linewidths by the following constant. */ #define NON_AA_CG_OFFSET .999 static int cgAntiAliasLimit = 0; -#define notAA(w) ((w) < cgAntiAliasLimit) +#define notAA(w) ((w) < cgAntiAliasLimit) static int useThemedToplevel = 0; static int useThemedFrame = 0; /* @@ -117,75 +116,75 @@ * deprecated by Apple in OSX 10.14 and also required the use of other * deprecated functions such as [NSView lockFocus]. Apple's suggested * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that * is what is being used here. However, that method only works when the * view has a valid CGContext, and a view is only guaranteed to have a - * valid context during a call to [NSView drawRect]. To further - * complicate matters, cacheDisplayInRect calls [NSView drawRect]. - * Essentially it is asking the view to draw a subrectangle of itself into - * a special graphics context which is linked to the BitmapImageRep. But - * our implementation of [NSView drawRect] does not allow recursive calls. - * If called recursively it returns immediately without doing any drawing. + * valid context during a call to [NSView drawRect]. To further complicate + * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is + * asking the view to draw a subrectangle of itself into a special + * graphics context which is linked to the BitmapImageRep. But our + * implementation of [NSView drawRect] does not allow recursive calls. If + * called recursively it returns immediately without doing any drawing. * So the bottom line is that this function either returns a NULL pointer - * or a black image. To make it useful would require a significant amount - * of rewriting of the drawRect method. Perhaps the next release of OSX + * or a black image. To make it useful would require a significant amount + * of rewriting of the drawRect method. Perhaps the next release of OSX * will include some more helpful ways of doing this. * * 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. + * 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 + * 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* + +NSBitmapImageRep * TkMacOSXBitmapRepFromDrawableRect( - Drawable drawable, - int x, - int y, - unsigned int width, - unsigned int height) + 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; + CGImageRef cg_image = NULL, sub_cg_image = NULL; NSBitmapImageRep *bitmap_rep = NULL; - NSView *view=NULL; - if ( mac_drawable->flags & TK_IS_PIXMAP ) { - + NSView *view = NULL; + if (mac_drawable->flags & TK_IS_PIXMAP) { /* * This MacDrawable is a bitmap, so its view is NULL. */ - cg_context = TkMacOSXGetCGContextForDrawable(drawable); CGRect image_rect = CGRectMake(x, y, width, height); - cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context); + + cg_context = TkMacOSXGetCGContextForDrawable(drawable); + cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect); - if ( sub_cg_image ) { + if (sub_cg_image) { bitmap_rep = [NSBitmapImageRep alloc]; [bitmap_rep initWithCGImage:sub_cg_image]; } - if ( cg_image ) { + if (cg_image) { CGImageRelease(cg_image); } - } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) { - + } else if ((view = TkMacOSXDrawableView(mac_drawable)) != NULL) { /* * 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); + view_height - height - y - mac_drawable->yOff, + width, height); /* * Attempt to copy from the view to a bitmapImageRep. If the view does * not have a valid CGContext, doing this will silently corrupt memory * and make a big mess. So, in that case, we mark the view as needing @@ -216,25 +215,24 @@ * * Results: * None. * * Side effects: - * Data is moved from a window or bitmap to a second window or - * bitmap. + * Data is moved from a window or bitmap to a second window or bitmap. * *---------------------------------------------------------------------- */ void XCopyArea( Display *display, /* Display. */ Drawable src, /* Source drawable. */ Drawable dst, /* Destination drawable. */ - GC gc, /* GC to use. */ + GC gc, /* GC to use. */ int src_x, /* X & Y, width & height */ int src_y, /* define the source rectangle */ - unsigned int width, /* that will be copied. */ + unsigned int width, /* that will be copied. */ unsigned int height, int dest_x, /* Dest X & Y on dest rect. */ int dest_y) { TkMacOSXDrawingContext dc; @@ -247,55 +245,53 @@ if (!width || !height) { return; } if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { - return; 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) { - bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); - srcRect = CGRectMake(src_x, src_y, width, height); - dstRect = CGRectMake(dest_x, dest_y, width, height); - TkMacOSXDrawCGImage(dst, gc, dc.context, img, - gc->foreground, gc->background, bounds, srcRect, dstRect); - CFRelease(img); - } else { - TkMacOSXDbgMsg("Failed to construct CGImage."); - } - - } else { + return; + } + + if (!dc.context) { TkMacOSXDbgMsg("Invalid destination drawable - no context."); return; } + + 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) { + bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); + srcRect = CGRectMake(src_x, src_y, width, height); + dstRect = CGRectMake(dest_x, dest_y, width, height); + TkMacOSXDrawCGImage(dst, gc, dc.context, img, + gc->foreground, gc->background, bounds, srcRect, dstRect); + CFRelease(img); + } else { + TkMacOSXDbgMsg("Failed to construct CGImage."); + } TkMacOSXRestoreDrawingContext(&dc); } /* *---------------------------------------------------------------------- * * XCopyPlane -- * - * Copies a bitmap from a source drawable to a destination - * drawable. The plane argument specifies which bit plane of - * the source contains the bitmap. Note that this implementation - * ignores the gc->function. + * Copies a bitmap from a source drawable to a destination drawable. The + * plane argument specifies which bit plane of the source contains the + * bitmap. Note that this implementation ignores the gc->function. * * Results: * None. * * Side effects: @@ -332,58 +328,88 @@ } if (srcDraw->flags & TK_IS_PIXMAP) { if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { return; } + CGContextRef context = dc.context; + if (context) { CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src); + if (img) { TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; unsigned long imageBackground = gc->background; - if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){ + + if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) { srcRect = CGRectMake(src_x, src_y, width, height); - CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap); - CGImageRef submask = CGImageCreateWithImageInRect(img, srcRect); + CGImageRef mask = TkMacOSXCreateCGImageWithDrawable( + clipPtr->value.pixmap); + CGImageRef submask = CGImageCreateWithImageInRect( + img, srcRect); CGRect rect = CGRectMake(dest_x, dest_y, width, height); + rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff); CGContextSaveGState(context); - /* Move the origin of the destination to top left. */ - CGContextTranslateCTM(context, 0, rect.origin.y + CGRectGetMaxY(rect)); + + /* + * Move the origin of the destination to top left. + */ + + CGContextTranslateCTM(context, + 0, rect.origin.y + CGRectGetMaxY(rect)); CGContextScaleCTM(context, 1, -1); - /* Fill with the background color, clipping to the mask. */ + + /* + * Fill with the background color, clipping to the mask. + */ + CGContextClipToMask(context, rect, submask); TkMacOSXSetColorInContext(gc, gc->background, dc.context); CGContextFillRect(context, rect); - /* Fill with the foreground color, clipping to the - intersection of img and mask. */ - CGImageRef subimage = CGImageCreateWithImageInRect(img, srcRect); + + /* + * Fill with the foreground color, clipping to the + * intersection of img and mask. + */ + + CGImageRef subimage = CGImageCreateWithImageInRect( + img, srcRect); CGContextClipToMask(context, rect, subimage); TkMacOSXSetColorInContext(gc, gc->foreground, context); CGContextFillRect(context, rect); CGContextRestoreGState(context); CGImageRelease(img); CGImageRelease(mask); CGImageRelease(submask); CGImageRelease(subimage); } else { - bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); + bounds = CGRectMake(0, 0, + srcDraw->size.width, srcDraw->size.height); srcRect = CGRectMake(src_x, src_y, width, height); dstRect = CGRectMake(dest_x, dest_y, width, height); - TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, - imageBackground, bounds, srcRect, dstRect); + TkMacOSXDrawCGImage(dst, gc, dc.context, img, + gc->foreground, imageBackground, bounds, + srcRect, dstRect); CGImageRelease(img); } - } else { /* no image */ + } else { + /* no image */ TkMacOSXDbgMsg("Invalid source drawable"); } } else { - TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context."); + 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); + } else { + /* + * Source drawable is a Window, not a Pixmap. + */ + + XCopyArea(display, src, dst, gc, src_x, src_y, width, height, + dest_x, dest_y); } } /* *---------------------------------------------------------------------- @@ -428,11 +454,11 @@ * None. * *---------------------------------------------------------------------- */ -static NSImage* +static NSImage * CreateNSImageWithPixmap( Pixmap pixmap, int width, int height) { @@ -464,11 +490,11 @@ * None. * *---------------------------------------------------------------------- */ -NSImage* +NSImage * TkMacOSXGetNSImageWithTkImage( Display *display, Tk_Image image, int width, int height) @@ -497,11 +523,11 @@ * None. * *---------------------------------------------------------------------- */ -NSImage* +NSImage * TkMacOSXGetNSImageWithBitmap( Display *display, Pixmap bitmap, GC gc, int width, @@ -548,27 +574,28 @@ const size_t bitsPerComponent = 8; size_t bitsPerPixel, bytesPerRow, len; CGColorSpaceRef colorspace = NULL; CGBitmapInfo bitmapInfo = #ifdef __LITTLE_ENDIAN__ - kCGBitmapByteOrder32Host; + kCGBitmapByteOrder32Host; #else - kCGBitmapByteOrderDefault; + kCGBitmapByteOrderDefault; #endif char *data; - CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height); + CGRect bounds = CGRectMake(0, 0, + macDraw->size.width, macDraw->size.height); if (macDraw->flags & TK_IS_BW_PIXMAP) { bitsPerPixel = 8; - bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly; + bitmapInfo = (CGBitmapInfo) kCGImageAlphaOnly; } else { colorspace = CGColorSpaceCreateDeviceRGB(); bitsPerPixel = 32; bitmapInfo |= kCGImageAlphaPremultipliedFirst; } - bytesPerRow = ((size_t) macDraw->size.width * bitsPerPixel + 127) >> 3 - & ~15; + bytesPerRow = ((size_t) + macDraw->size.width * bitsPerPixel + 127) >> 3 & ~15; len = macDraw->size.height * bytesPerRow; data = ckalloc(len); bzero(data, len); macDraw->context = CGBitmapContextCreate(data, macDraw->size.width, macDraw->size.height, bitsPerComponent, bytesPerRow, @@ -628,12 +655,12 @@ } } dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff); if (CGImageIsMask(image)) { if (macDraw->flags & TK_IS_BW_PIXMAP) { - - /* Set fill color to black; background comes from the context, + /* + * Set fill color to black; background comes from the context, * or is transparent. */ if (imageBackground != TRANSPARENT_PIXEL << 24) { CGContextClearRect(context, dstBounds); @@ -653,15 +680,17 @@ CGContextSetLineWidth(context, 1.0); CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.1); CGContextSetRGBFillColor(context, 0, 1, 0, 0.1); CGContextFillRect(context, dstBounds); CGContextStrokeRect(context, dstBounds); + CGPoint p[4] = {dstBounds.origin, CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMaxY(dstBounds)), CGPointMake(CGRectGetMinX(dstBounds), CGRectGetMaxY(dstBounds)), CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMinY(dstBounds)) }; + CGContextStrokeLineSegments(context, p, 4); CGContextRestoreGState(context); TkMacOSXDbgMsg("Drawing CGImage at (x=%f, y=%f), (w=%f, h=%f)", dstBounds.origin.x, dstBounds.origin.y, dstBounds.size.width, dstBounds.size.height); @@ -734,16 +763,17 @@ prevx += points[i].x; prevy += points[i].y; CGContextAddLineToPoint(dc.context, prevx, prevy); } } + /* - * In the case of closed polylines, the first and last points - * are the same. We want miter or bevel join be rendered also - * at this point, this needs telling CoreGraphics that the - * path is closed. + * In the case of closed polylines, the first and last points are the + * same. We want miter or bevel join be rendered also at this point, + * this needs telling CoreGraphics that the path is closed. */ + if ((points[0].x == points[npoints-1].x) && (points[0].y == points[npoints-1].y)) { CGContextClosePath(dc.context); } CGContextStrokePath(dc.context); @@ -818,14 +848,14 @@ *---------------------------------------------------------------------- */ void XFillPolygon( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ - XPoint* points, /* Array of points. */ + XPoint *points, /* Array of points. */ int npoints, /* Number of points. */ int shape, /* Shape to draw. */ int mode) /* Drawing mode. */ { MacDrawable *macWin = (MacDrawable *) d; @@ -900,12 +930,11 @@ if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; rect = CGRectMake( - macWin->xOff + x + o, - macWin->yOff + y + o, + macWin->xOff + x + o, macWin->yOff + y + o, width, height); CGContextStrokeRect(dc.context, rect); } TkMacOSXRestoreDrawingContext(&dc); } @@ -914,21 +943,19 @@ /* *---------------------------------------------------------------------- * * XDrawRectangles -- * - * Draws the outlines of the specified rectangles as if a - * five-point PolyLine protocol request were specified for each - * rectangle: + * Draws the outlines of the specified rectangles as if a five-point + * PolyLine protocol request were specified for each rectangle: * * [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y] * - * For the specified rectangles, these functions do not draw a - * pixel more than once. XDrawRectangles draws the rectangles in - * the order listed in the array. If rectangles intersect, the - * intersecting pixels are drawn multiple times. Draws a - * rectangle. + * For the specified rectangles, these functions do not draw a pixel more + * than once. XDrawRectangles draws the rectangles in the order listed in + * the array. If rectangles intersect, the intersecting pixels are drawn + * multiple times. Draws a rectangle. * * Results: * None. * * Side effects: @@ -989,11 +1016,11 @@ *---------------------------------------------------------------------- */ int XFillRectangles( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ XRectangle *rectangles, /* Rectangle array. */ int n_rectangles) /* Number of rectangles. */ { @@ -1025,10 +1052,58 @@ } /* *---------------------------------------------------------------------- * + * TkMacOSXDrawSolidBorder -- + * + * Draws a border rectangle of specified thickness inside the bounding + * rectangle of a Tk Window. The border rectangle can be inset within the + * bounding rectangle. For a highlight border the inset should be 0, but + * for a solid border around the actual window the inset should equal the + * thickness of the highlight border. The color of the border rectangle + * is the foreground color of the graphics context passed to the function. + * + * Results: + * None. + * + * Side effects: + * Draws a rectangular border inside the bounding rectangle of a window. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void +TkMacOSXDrawSolidBorder( + Tk_Window tkwin, + GC gc, + int inset, + int thickness) +{ + Drawable d = Tk_WindowId(tkwin); + TkMacOSXDrawingContext dc; + CGRect outerRect, innerRect; + + if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { + return; + } + if (dc.context) { + outerRect = CGRectMake(Tk_X(tkwin), Tk_Y(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin)); + outerRect = CGRectInset(outerRect, inset, inset); + innerRect = CGRectInset(outerRect, thickness, thickness); + CGContextBeginPath(dc.context); + CGContextAddRect(dc.context, outerRect); + CGContextAddRect(dc.context, innerRect); + CGContextEOFillPath(dc.context); + } + TkMacOSXRestoreDrawingContext(&dc); +} + +/* + *---------------------------------------------------------------------- + * * XDrawArc -- * * Draw an arc. * * Results: @@ -1040,11 +1115,11 @@ *---------------------------------------------------------------------- */ void XDrawArc( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ int x, int y, /* Upper left of bounding rect. */ unsigned int width, /* Width & height. */ unsigned int height, @@ -1097,18 +1172,17 @@ /* *---------------------------------------------------------------------- * * XDrawArcs -- * - * Draws multiple circular or elliptical arcs. Each arc is - * specified by a rectangle and two angles. The center of the - * circle or ellipse is the center of the rect- angle, and the - * major and minor axes are specified by the width and height. - * Positive angles indicate counterclock- wise motion, and - * negative angles indicate clockwise motion. If the magnitude - * of angle2 is greater than 360 degrees, XDrawArcs truncates it - * to 360 degrees. + * Draws multiple circular or elliptical arcs. Each arc is specified by a + * rectangle and two angles. The center of the circle or ellipse is the + * center of the rect- angle, and the major and minor axes are specified + * by the width and height. Positive angles indicate counterclock- wise + * motion, and negative angles indicate clockwise motion. If the magnitude + * of angle2 is greater than 360 degrees, XDrawArcs truncates it to 360 + * degrees. * * Results: * None. * * Side effects: @@ -1123,11 +1197,10 @@ Drawable d, GC gc, XArc *arcArr, int nArcs) { - MacDrawable *macWin = (MacDrawable *) d; TkMacOSXDrawingContext dc; XArc *arcPtr; int i, lw = gc->line_width; @@ -1193,11 +1266,11 @@ *---------------------------------------------------------------------- */ void XFillArc( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ int x, int y, /* Upper left of bounding rect. */ unsigned int width, /* Width & height. */ unsigned int height, @@ -1358,17 +1431,16 @@ /* *---------------------------------------------------------------------- * * TkScrollWindow -- * - * Scroll a rectangle of the specified window and accumulate - * a damage region. + * 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. + * 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. * *---------------------------------------------------------------------- @@ -1383,51 +1455,67 @@ int dx, int dy, /* Distance rectangle should be moved. */ TkRegion damageRgn) /* Region to accumulate damage in. */ { Drawable drawable = Tk_WindowId(tkwin); MacDrawable *macDraw = (MacDrawable *) drawable; - TKContentView *view = (TKContentView *)TkMacOSXDrawableView(macDraw); + TKContentView *view = (TKContentView *) TkMacOSXDrawableView(macDraw); CGRect srcRect, dstRect; 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). */ + 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); + bounds.size.height - height - (macDraw->yOff + y), + width, height); scrollDst = NSOffsetRect(scrollSrc, dx, -dy); - /* Limit scrolling to the window content area. */ + /* + * Limit scrolling to the window content area. + */ + visRect = [view visibleRect]; scrollSrc = NSIntersectionRect(scrollSrc, visRect); scrollDst = NSIntersectionRect(scrollDst, visRect); - if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) { + 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. + * This region is described in NSView coordinates (y=0 at the + * bottom) and converted to Tk coordinates later. */ srcRect = CGRectMake(x, y, width, height); dstRect = CGRectOffset(srcRect, dx, dy); - /* Compute the damage. */ + /* + * Compute the damage. + */ + dmgRgn = HIShapeCreateMutableWithRect(&srcRect); extraRgn = HIShapeCreateWithRect(&dstRect); - ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn); + ChkErr(HIShapeDifference, dmgRgn, extraRgn, + (HIMutableShapeRef) dmgRgn); result = HIShapeIsEmpty(dmgRgn) ? 0 : 1; - /* Convert to Tk coordinates, offset by the window origin. */ + /* + * Convert to Tk coordinates, offset by the window origin. + */ + TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); if (extraRgn) { CFRelease(extraRgn); } - /* Scroll the rectangle. */ + /* + * Scroll the rectangle. + */ + [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)]; } } else { dmgRgn = HIShapeCreateEmpty(); TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); @@ -1470,12 +1558,12 @@ * TkMacOSXSetUpDrawingContext -- * * Set up a drawing context for the given drawable and GC. * * Results: - * Boolean indicating whether it is ok to draw; if false, drawing - * context was not setup, so do not attempt to draw and do not call + * Boolean indicating whether it is ok to draw; if false, drawing context + * was not setup, so do not attempt to draw and do not call * TkMacOSXRestoreDrawingContext(). * * Side effects: * None. * @@ -1484,22 +1572,22 @@ Bool TkMacOSXSetupDrawingContext( Drawable d, GC gc, - int useCG, /* advisory only ! */ + int useCG, /* advisory only ! */ TkMacOSXDrawingContext *dcPtr) { - MacDrawable *macDraw = ((MacDrawable*)d); + MacDrawable *macDraw = (MacDrawable *) d; Bool canDraw = true; NSWindow *win = NULL; TkMacOSXDrawingContext dc = {}; CGRect clipBounds; /* - * If the drawable is not a pixmap and it has an associated - * NSWindow then we know we are drawing to a window. + * If the drawable is not a pixmap and it has an associated NSWindow then + * we know we are drawing to a window. */ if (!(macDraw->flags & TK_IS_PIXMAP)) { win = TkMacOSXDrawableWindow(d); } @@ -1514,49 +1602,47 @@ canDraw = false; goto end; } /* - * If we already have a CGContext, use it. Otherwise, if we - * are drawing to a window then we can get one from the - * window. + * If we already have a CGContext, use it. Otherwise, if we are drawing to + * a window then we can get one from the window. */ dc.context = TkMacOSXGetCGContextForDrawable(d); if (dc.context) { dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context); } else if (win) { NSView *view = TkMacOSXDrawableView(macDraw); - if (view) { - - /* - * We can only draw into the view when the current CGContext is - * valid and belongs to the view. Validity can only be guaranteed - * inside of a view's drawRect or setFrame methods. The isDrawing - * attribute tells us whether we are being called from one of those - * methods. - * - * If the CGContext is not valid, or belongs to a different View, - * then we mark our view as needing display and return failure. - * It should get drawn in a later call to drawRect. - */ - - if (view != [NSView focusView]) { - [view setNeedsDisplay:YES]; - canDraw = false; - goto end; - } - dc.view = view; - dc.context = GET_CGCONTEXT; - dc.portBounds = NSRectToCGRect([view bounds]); - if (dc.clipRgn) { - clipBounds = CGContextGetClipBoundingBox(dc.context); - } - } else { + + if (!view) { Tcl_Panic("TkMacOSXSetupDrawingContext(): " "no NSView to draw into !"); } + + /* + * We can only draw into the view when the current CGContext is valid + * and belongs to the view. Validity can only be guaranteed inside of + * a view's drawRect or setFrame methods. The isDrawing attribute + * tells us whether we are being called from one of those methods. + * + * If the CGContext is not valid, or belongs to a different View, then + * we mark our view as needing display and return failure. It should + * get drawn in a later call to drawRect. + */ + + if (view != [NSView focusView]) { + [view setNeedsDisplay:YES]; + canDraw = false; + goto end; + } + dc.view = view; + dc.context = GET_CGCONTEXT; + dc.portBounds = NSRectToCGRect([view bounds]); + if (dc.clipRgn) { + clipBounds = CGContextGetClipBoundingBox(dc.context); + } } else { Tcl_Panic("TkMacOSXSetupDrawingContext(): " "no context to draw into !"); } @@ -1563,12 +1649,17 @@ /* * Configure the drawing context. */ if (dc.context) { - CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = dc.portBounds.size.height}; + CGAffineTransform t = { + .a = 1, .b = 0, + .c = 0, .d = -1, + .tx = 0, + .ty = dc.portBounds.size.height + }; + dc.portBounds.origin.x += macDraw->xOff; dc.portBounds.origin.y += macDraw->yOff; CGContextSaveGState(dc.context); CGContextSetTextDrawingMode(dc.context, kCGTextFill); CGContextConcatCTM(dc.context, t); @@ -1579,10 +1670,11 @@ CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1); CGContextEOFillPath(dc.context); CGContextRestoreGState(dc.context); #endif /* TK_MAC_DEBUG_DRAWING */ CGRect r; + if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect( *HIShapeGetBounds(dc.clipRgn, &r), CGRectApplyAffineTransform(clipBounds, t))) { ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); CGContextEOClip(dc.context); @@ -1606,51 +1698,61 @@ TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); if (win) { CGContextSetPatternPhase(dc.context, CGSizeMake( dc.portBounds.size.width, dc.portBounds.size.height)); } - if(gc->function != GXcopy) { + if (gc->function != GXcopy) { TkMacOSXDbgMsg("Logical functions other than GXcopy are " "not supported for CG drawing!"); } - /* When should we antialias? */ + + /* + * When should we antialias? + */ + shouldAntialias = !notAA(gc->line_width); if (!shouldAntialias) { - /* Make non-antialiased CG drawing look more like X11 */ + /* + * Make non-antialiased CG drawing look more like X11. + */ + w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); } CGContextSetShouldAntialias(dc.context, shouldAntialias); CGContextSetLineWidth(dc.context, w); if (gc->line_style != LineSolid) { int num = 0; - char *p = &(gc->dashes); + char *p = &gc->dashes; CGFloat dashOffset = gc->dash_offset; CGFloat lengths[10]; while (p[num] != '\0' && num < 10) { lengths[num] = p[num]; num++; } CGContextSetLineDash(dc.context, dashOffset, lengths, num); } - if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { + if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { CGContextSetLineCap(dc.context, - cgCap[(unsigned)gc->cap_style]); + cgCap[(unsigned) gc->cap_style]); } if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) { CGContextSetLineJoin(dc.context, - cgJoin[(unsigned)gc->join_style]); + cgJoin[(unsigned) gc->join_style]); } } } end: #ifdef TK_MAC_DEBUG_DRAWING if (!canDraw && win != NULL) { TkWindow *winPtr = TkMacOSXGetTkWindow(win); - if (winPtr) fprintf(stderr, "Cannot draw in %s - postponing.\n", - Tk_PathName(winPtr)); + + if (winPtr) { + fprintf(stderr, "Cannot draw in %s - postponing.\n", + Tk_PathName(winPtr)); + } } #endif if (!canDraw && dc.clipRgn) { CFRelease(dc.clipRgn); dc.clipRgn = NULL; @@ -1717,11 +1819,13 @@ if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(macDraw->winPtr); #ifdef TK_MAC_DEBUG_DRAWING TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName); + NSView *view = TkMacOSXDrawableView(macDraw); + CGContextSaveGState(context); CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, [view bounds].size.height)); ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context); CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1); @@ -1741,12 +1845,12 @@ /* *---------------------------------------------------------------------- * * TkMacOSXSetUpClippingRgn -- * - * Set up the clipping region so that drawing only occurs on the - * specified X subwindow. + * Set up the clipping region so that drawing only occurs on the specified + * X subwindow. * * Results: * None. * * Side effects: @@ -1764,12 +1868,12 @@ /* *---------------------------------------------------------------------- * * TkpClipDrawableToRect -- * - * Clip all drawing into the drawable d to the given rectangle. - * If width or height are negative, reset to no clipping. + * Clip all drawing into the drawable d to the given rectangle. If width + * or height are negative, reset to no clipping. * * Results: * None. * * Side effects: @@ -1830,12 +1934,12 @@ Drawable d, GC gc, HIShapeRef *clipRgnPtr) /* must point to initialized variable */ { if (gc && gc->clip_mask && - ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { - TkRegion gcClip = ((TkpClipMask*)gc->clip_mask)->value.region; + ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) { + TkRegion gcClip = ((TkpClipMask *) gc->clip_mask)->value.region; int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin; int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin; HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn; TkMacOSXOffsetRegion(gcClip, xOffset, yOffset); @@ -1854,14 +1958,13 @@ /* *---------------------------------------------------------------------- * * TkMacOSXMakeStippleMap -- * - * Given a drawable and a stipple pattern this function draws the - * pattern repeatedly over the drawable. The drawable can then - * be used as a mask for bit-bliting a stipple pattern over an - * object. + * Given a drawable and a stipple pattern this function draws the pattern + * repeatedly over the drawable. The drawable can then be used as a mask + * for bit-bliting a stipple pattern over an object. * * Results: * A BitMap data structure. * * Side effects: @@ -1881,25 +1984,25 @@ /* *---------------------------------------------------------------------- * * TkpDrawHighlightBorder -- * - * This procedure draws a rectangular ring around the outside of - * a widget to indicate that it has received the input focus. + * This procedure draws a rectangular ring around the outside of a widget + * to indicate that it has received the input focus. * - * On the Macintosh, this puts a 1 pixel border in the bgGC color - * between the widget and the focus ring, except in the case where - * highlightWidth is 1, in which case the border is left out. + * On the Macintosh, this puts a 1 pixel border in the bgGC color between + * the widget and the focus ring, except in the case where highlightWidth + * is 1, in which case the border is left out. * * For proper Mac L&F, use highlightWidth of 3. * * Results: * None. * * Side effects: - * A rectangle "width" pixels wide is drawn in "drawable", - * corresponding to the outer area of "tkwin". + * A rectangle "width" pixels wide is drawn in "drawable", corresponding + * to the outer area of "tkwin". * *---------------------------------------------------------------------- */ void @@ -1922,14 +2025,14 @@ } /* *---------------------------------------------------------------------- * - * TkpDrawFrame -- + * TkpDrawFrameEx -- * - * This procedure draws the rectangular frame area. If the user - * has requested themeing, it draws with the background theme. + * This procedure draws the rectangular frame area. If the user has + * requested themeing, it draws with the background theme. * * Results: * None. * * Side effects: @@ -1937,12 +2040,13 @@ * *---------------------------------------------------------------------- */ void -TkpDrawFrame( +TkpDrawFrameEx( Tk_Window tkwin, + Drawable drawable, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief) { @@ -1956,15 +2060,13 @@ if (themedBorder) { border = themedBorder; } } - Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), - border, highlightWidth, highlightWidth, - Tk_Width(tkwin) - 2 * highlightWidth, - Tk_Height(tkwin) - 2 * highlightWidth, - borderWidth, relief); + Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth, + highlightWidth, Tk_Width(tkwin) - 2 * highlightWidth, + Tk_Height(tkwin) - 2 * highlightWidth, borderWidth, relief); } /* * Local Variables: * mode: objc Index: macosx/tkMacOSXEmbed.c ================================================================== --- macosx/tkMacOSXEmbed.c +++ macosx/tkMacOSXEmbed.c @@ -270,28 +270,29 @@ if (TkpScanWindowId(interp, string, (Window *)&parent) != TCL_OK) { return TCL_ERROR; } usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent); - if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) { + if (usePtr == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't create child of window \"%s\"", string)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL); + } + return TCL_ERROR; + } else if (!(usePtr->flags & TK_CONTAINER)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "window \"%s\" doesn't have -container option set", usePtr->pathName)); Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL); return TCL_ERROR; } /* - * The code below can probably be simplified given we have already - * discovered 'usePtr' above. - */ - - /* - * Save information about the container and the embedded window in a - * Container structure. Currently, there must already be an existing - * Container structure, since we only allow the case where both container - * and embedded app. are in the same process. + * Since we do not allow embedding into windows belonging to a different + * process, we know that a container will exist showing the parent window + * as the parent. This loop finds that container. */ for (containerPtr = firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->parent == (Window) parent) { @@ -310,20 +311,10 @@ winPtr->privatePtr = NULL; return TCL_ERROR; } macWin->winPtr = winPtr; - winPtr->privatePtr = macWin; - - /* - * The grafPtr will be NULL for a Tk in Tk embedded window. It is none of - * our business what it is for a Tk not in Tk embedded window, but we will - * initialize it to NULL, and let the registerWinProc set it. In any case, - * you must always use TkMacOSXGetDrawablePort to get the portPtr. It will - * correctly find the container's port. - */ - macWin->view = nil; macWin->context = NULL; macWin->size = CGSizeZero; macWin->visRgn = NULL; macWin->aboveVisRgn = NULL; @@ -331,76 +322,41 @@ macWin->referenceCount = 0; macWin->flags = TK_CLIP_INVALID; macWin->toplevel = macWin; macWin->toplevel->referenceCount++; + winPtr->privatePtr = macWin; winPtr->flags |= TK_EMBEDDED; /* * Make a copy of the TK_EMBEDDED flag, since sometimes we need this to * get the port after the TkWindow structure has been freed. */ macWin->flags |= TK_EMBEDDED; - - /* - * Now check whether it is embedded in another Tk widget. If not (the - * first case below) we see if there is an in-process embedding handler - * registered, and if so, let that fill in the rest of the macWin. - */ - - if (containerPtr == NULL) { - /* - * If someone has registered an in-process embedding handler, then - * see if it can handle this window... - */ - - if (tkMacOSXEmbedHandler == NULL || - tkMacOSXEmbedHandler->registerWinProc((long) parent, - (Tk_Window) winPtr) != TCL_OK) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "The window ID %s does not correspond to a valid Tk Window", - string)); - Tcl_SetErrorCode(interp, "TK", "EMBED", "HANDLE", NULL); - return TCL_ERROR; - } - - containerPtr = ckalloc(sizeof(Container)); - - containerPtr->parentPtr = NULL; - containerPtr->embedded = (Window) macWin; - containerPtr->embeddedPtr = macWin->winPtr; - containerPtr->nextPtr = firstContainerPtr; - firstContainerPtr = containerPtr; - } else { - /* - * The window is embedded in another Tk window. - */ - - macWin->xOff = parent->winPtr->privatePtr->xOff + - parent->winPtr->changes.border_width + - winPtr->changes.x; - macWin->yOff = parent->winPtr->privatePtr->yOff + - parent->winPtr->changes.border_width + - winPtr->changes.y; - - /* - * Finish filling up the container structure with the embedded - * window's information. - */ - - containerPtr->embedded = (Window) macWin; - containerPtr->embeddedPtr = macWin->winPtr; - - /* - * Create an event handler to clean up the Container structure when - * tkwin is eventually deleted. - */ - - Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, - winPtr); - } + macWin->xOff = parent->winPtr->privatePtr->xOff + + parent->winPtr->changes.border_width + + winPtr->changes.x; + macWin->yOff = parent->winPtr->privatePtr->yOff + + parent->winPtr->changes.border_width + + winPtr->changes.y; + + /* + * Finish filling up the container structure with the embedded window's + * information. + */ + + containerPtr->embedded = (Window) macWin; + containerPtr->embeddedPtr = macWin->winPtr; + + /* + * Create an event handler to clean up the Container structure when + * tkwin is eventually deleted. + */ + + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + EmbeddedEventProc, winPtr); return TCL_OK; } /* @@ -540,13 +496,11 @@ *---------------------------------------------------------------------- * * TkpClaimFocus -- * * This procedure is invoked when someone asks for the input focus to be - * put on a window in an embedded application, but the application - * doesn't currently have the focus. It requests the input focus from the - * container application. + * put on a window in an embedded application. * * Results: * None. * * Side effects: @@ -581,11 +535,11 @@ event.xfocus.send_event = 1; event.xfocus.display = topLevelPtr->display; event.xfocus.window = containerPtr->parent; event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS; event.xfocus.detail = force; - Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL); + Tk_HandleEvent(&event); } /* *---------------------------------------------------------------------- * @@ -612,43 +566,69 @@ { int all; Container *containerPtr; Tcl_DString dString; char buffer[50]; + Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL; if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) { all = 1; } else { all = 0; } Tcl_DStringInit(&dString); for (containerPtr = firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { + if (containerPtr->embeddedPtr != NULL) { + embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp; + } + if (containerPtr->parentPtr != NULL) { + parentInterp = containerPtr->parentPtr->mainPtr->interp; + } + if (embeddedInterp != interp && parentInterp != interp) { + continue; + } Tcl_DStringStartSublist(&dString); + + /* + * Parent id + */ + if (containerPtr->parent == None) { Tcl_DStringAppendElement(&dString, ""); } else if (all) { - sprintf(buffer, "0x%x", (int) containerPtr->parent); + sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", + (size_t) containerPtr->parent); Tcl_DStringAppendElement(&dString, buffer); } else { Tcl_DStringAppendElement(&dString, "XXX"); } - if (containerPtr->parentPtr == NULL) { + + /* + * Parent pathName + */ + + if (containerPtr->parentPtr == NULL || + parentInterp != interp) { Tcl_DStringAppendElement(&dString, ""); } else { Tcl_DStringAppendElement(&dString, containerPtr->parentPtr->pathName); } - if (containerPtr->embedded == None) { - Tcl_DStringAppendElement(&dString, ""); - } else if (all) { - sprintf(buffer, "0x%x", (int) containerPtr->embedded); - Tcl_DStringAppendElement(&dString, buffer); - } else { - Tcl_DStringAppendElement(&dString, "XXX"); - } - if (containerPtr->embeddedPtr == NULL) { + + /* + * On X11 embedded is a wrapper, which does not exist on macOS. + */ + + Tcl_DStringAppendElement(&dString, ""); + + /* + * Embedded window pathName + */ + + if (containerPtr->embeddedPtr == NULL || + embeddedInterp != interp) { Tcl_DStringAppendElement(&dString, ""); } else { Tcl_DStringAppendElement(&dString, containerPtr->embeddedPtr->pathName); } @@ -801,10 +781,11 @@ if (!firstContainerPtr) { /* * When the interpreter is being dismantled this can be nil. */ + return; } /* * Ignore any X protocol errors that happen in this procedure (almost any @@ -866,11 +847,13 @@ XMapWindow(eventPtr->xmaprequest.display, eventPtr->xmaprequest.window); } else if (eventPtr->type == DestroyNotify) { /* - * The embedded application is gone. Destroy the container window. + * It is not clear whether the container should be destroyed + * when an embedded window is destroyed. See ticket [67384bce7d]. + * Here we are following unix, by destroying the container. */ Tk_DestroyWindow((Tk_Window) winPtr); } Tk_DeleteErrorHandler(errHandler); @@ -902,10 +885,18 @@ { Container *containerPtr = clientData; Tk_ErrorHandler errHandler; if (eventPtr->type == ConfigureNotify) { + + /* + * Send a ConfigureNotify to the embedded application. + */ + + if (containerPtr->embeddedPtr != None) { + TkDoConfigureNotify(containerPtr->embeddedPtr); + } if (containerPtr->embedded != None) { /* * Ignore errors, since the embedded application could have * deleted its window. */ @@ -1050,15 +1041,14 @@ TkWindow *winPtr = containerPtr->parentPtr; /* * Forward the requested size into our geometry management hierarchy via * the container window. We need to send a Configure event back to the - * embedded application if we decide not to honor its request; to make - * this happen, process all idle event handlers synchronously here (so - * that the geometry managers have had a chance to do whatever they want - * to do), and if the window's size didn't change then generate a - * configure event. + * embedded application if we decide not to honor its request; to make this + * happen, process all idle event handlers synchronously here (so that the + * geometry managers have had a chance to do whatever they want to do), and + * if the window's size didn't change then generate a configure event. */ Tk_GeometryRequest((Tk_Window) winPtr, width, height); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) { /* Empty loop body. */ @@ -1076,12 +1066,12 @@ * * This is currently a stub. It is called to notify an embedded * application of its current size and location. This procedure is called * when the embedded application made a geometry request that we did not * grant, so that the embedded application knows that its geometry didn't - * change after all. It is a response to ConfigureRequest events, which - * we do not currently synthesize on the Mac + * change after all. It is a response to ConfigureRequest events, which we + * do not currently synthesize on the Mac * * Results: * None. * * Side effects: @@ -1137,12 +1127,12 @@ if (containerPtr->parentPtr != NULL && containerPtr->parentPtr->flags & TK_BOTH_HALVES) { XEvent event; - event.xany.serial = - LastKnownRequestProcessed(Tk_Display(containerPtr->parentPtr)); + event.xany.serial = LastKnownRequestProcessed( + Tk_Display(containerPtr->parentPtr)); event.xany.send_event = False; event.xany.display = Tk_Display(containerPtr->parentPtr); event.xany.type = DestroyNotify; event.xany.window = containerPtr->parent; Index: macosx/tkMacOSXEntry.c ================================================================== --- macosx/tkMacOSXEntry.c +++ macosx/tkMacOSXEntry.c @@ -122,20 +122,21 @@ if (isSpinbox) { int incDecWidth; /* - * Temporarily change the width of the widget so that the same code can - * be used for drawing the Entry portion of the Spinbox as is used to - * draw an ordinary Entry. The width must be restored before - * returning. + * If native spinbox buttons are going to be drawn, then temporarily + * change the width of the widget so that the same code can be used + * for drawing the Entry portion of the Spinbox as is used to draw + * an ordinary Entry. The width must be restored before returning. */ oldWidth = Tk_Width(tkwin); - ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH, - &incDecWidth); - Tk_Width(tkwin) -= incDecWidth + 1; + if (ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH, + &incDecWidth) != 0) { + Tk_Width(tkwin) -= incDecWidth + 1; + } } /* * The focus ring is drawn with an Alpha at the outside part of the ring, * so we have to draw over the edges of the ring before drawing the focus @@ -184,14 +185,14 @@ * such that the native widget drawing is a good fit. This version just * returns 0, so platforms that don't do special native drawing don't * have to implement it. * * Results: - * 1 if it has drawn the border, 0 if not. + * 1 if it has drawn the buttons, 0 if not. * * Side effects: - * May draw the entry border into pixmap. + * May draw the buttons into pixmap. * *-------------------------------------------------------------- */ int @@ -256,13 +257,13 @@ * overdraw the spin buttons with the focus highlight. So now we have to * draw the highlightbackground. */ bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d); - rects[0].x = bounds.origin.x; + rects[0].x = Tk_Width(tkwin) - incDecWidth - 1; rects[0].y = 0; - rects[0].width = Tk_Width(tkwin); + rects[0].width = incDecWidth + 1; rects[0].height = Tk_Height(tkwin); XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1); if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) { return 0; Index: macosx/tkMacOSXEvent.c ================================================================== --- macosx/tkMacOSXEvent.c +++ macosx/tkMacOSXEvent.c @@ -112,49 +112,33 @@ * * TkMacOSXFlushWindows -- * * This routine is a stub called by XSync, which is called during the Tk * update command. The language specification does not require that the - * update command be synchronous but many of the tests assume that is the - * case. It is not naturally the case on macOS since many idle tasks are - * run inside of the drawRect method of a window's contentView, and that - * method will not be called until after this function returns. To make - * the tests work, we attempt to force this to be synchronous by waiting - * until drawRect has been called for each window. The mechanism we use - * for this is to have drawRect post an ApplicationDefined NSEvent on the - * AppKit event queue when it finishes drawing, and wait for it here. + * update command be synchronous but many of the tests implicitly assume + * that it is. It is definitely asynchronous on macOS since many idle + * tasks are run inside of the drawRect method of a window's contentView, + * which will not be called until after this function returns. * * Results: * None. * - * Side effects: - * Calls the drawRect method of the contentView of each visible - * window. + * Side effects: Processes all pending idle events then calls the display + * method of each visible window. * *---------------------------------------------------------------------- */ MODULE_SCOPE void TkMacOSXFlushWindows(void) { - NSArray *macWindows = [NSApp orderedWindows]; - - if ([macWindows count] > 0) { - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){} - } - if ([NSApp isDrawing]) { - for (NSWindow *w in macWindows) { - if (TkMacOSXGetXWindow(w)) { - [w setViewsNeedDisplay:YES]; - } - } - } else { - for (NSWindow *w in macWindows) { - if (TkMacOSXGetXWindow(w)) { - [w display]; - } - } + if (Tk_GetNumMainWindows() == 0) { + return; + } + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){} + for (NSWindow *w in [NSApp orderedWindows]) { + [w display]; } } /* Index: macosx/tkMacOSXFont.c ================================================================== --- macosx/tkMacOSXFont.c +++ macosx/tkMacOSXFont.c @@ -1,10 +1,10 @@ /* * tkMacOSXFont.c -- * - * Contains the Macintosh implementation of the platform-independant - * font package interface. + * Contains the Macintosh implementation of the platform-independent font + * package interface. * * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright 2008-2009, Apple Inc. * @@ -30,13 +30,12 @@ * The following structure represents our Macintosh-specific implementation * of a font object. */ typedef struct { - TkFont font; /* Stuff used by generic font package. Must - * be first in structure. */ - + TkFont font; /* Stuff used by generic font package. Must be + * first in structure. */ NSFont *nsFont; NSDictionary *nsAttributes; } MacFont; /* @@ -81,21 +80,25 @@ static int antialiasedTextEnabled = -1; static NSCharacterSet *whitespaceCharacterSet = nil; static NSCharacterSet *lineendingCharacterSet = nil; -static void GetTkFontAttributesForNSFont(NSFont *nsFont, - TkFontAttributes *faPtr); -static NSFont *FindNSFont(const char *familyName, NSFontTraitMask traits, - NSInteger weight, CGFloat size, int fallbackToDefault); -static void InitFont(NSFont *nsFont, const TkFontAttributes *reqFaPtr, - MacFont * fontPtr); -static int CreateNamedSystemFont(Tcl_Interp *interp, Tk_Window tkwin, - const char* name, TkFontAttributes *faPtr); -static void DrawCharsInContext(Display *display, Drawable drawable, GC gc, - Tk_Font tkfont, const char *source, int numBytes, int rangeStart, - int rangeLength, int x, int y, double angle); +static void GetTkFontAttributesForNSFont(NSFont *nsFont, + TkFontAttributes *faPtr); +static NSFont * FindNSFont(const char *familyName, + NSFontTraitMask traits, NSInteger weight, + CGFloat size, int fallbackToDefault); +static void InitFont(NSFont *nsFont, + const TkFontAttributes *reqFaPtr, + MacFont *fontPtr); +static int CreateNamedSystemFont(Tcl_Interp *interp, + Tk_Window tkwin, const char *name, + TkFontAttributes *faPtr); +static void DrawCharsInContext(Display *display, Drawable drawable, + GC gc, Tk_Font tkfont, const char *source, + int numBytes, int rangeStart, int rangeLength, + int x, int y, double angle); #pragma mark - #pragma mark Font Helpers: #define GetNSFontTraitsFromTkFontAttributes(faPtr) \ @@ -230,11 +233,11 @@ CGFloat kern = 0.0; NSFontRenderingMode renderingMode = NSFontDefaultRenderingMode; int ascent, descent/*, dontAA*/; static const UniChar ch[] = {'.', 'W', ' ', 0xc4, 0xc1, 0xc2, 0xc3, 0xc7}; /* ., W, Space, Auml, Aacute, Acirc, Atilde, Ccedilla */ - #define nCh (sizeof(ch) / sizeof(UniChar)) +#define nCh (sizeof(ch) / sizeof(UniChar)) CGGlyph glyphs[nCh]; CGRect boundingRects[nCh]; fontPtr->font.fid = (Font) fontPtr; faPtr = &fontPtr->font.fa; @@ -242,11 +245,15 @@ *faPtr = *reqFaPtr; } else { TkInitFontAttributes(faPtr); } fontPtr->nsFont = nsFont; - // some don't like antialiasing on fixed-width even if bigger than limit + + /* + * Some don't like antialiasing on fixed-width even if bigger than limit + */ + // dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10; if (antialiasedTextEnabled >= 0/* || dontAA*/) { renderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ? NSFontIntegerAdvancementsRenderingMode : NSFontAntialiasedRenderingMode; @@ -292,11 +299,11 @@ NSUnderlineStyleNone], NSStrikethroughStyleAttributeName, [NSNumber numberWithInt:fmPtr->fixed ? 0 : 1], NSLigatureAttributeName, [NSNumber numberWithDouble:kern], NSKernAttributeName, nil]; fontPtr->nsAttributes = [nsAttributes retain]; - #undef nCh +#undef nCh } /* *------------------------------------------------------------------------- * @@ -356,14 +363,18 @@ Tk_Window tkwin = (Tk_Window) mainPtr->winPtr; const struct SystemFontMapEntry *systemFont = systemFontMap; NSFont *nsFont; TkFontAttributes fa; NSMutableCharacterSet *cs; - /* Since we called before TkpInit, we need our own autorelease pool. */ + /* + * Since we called before TkpInit, we need our own autorelease pool. + */ NSAutoreleasePool *pool = [NSAutoreleasePool new]; - /* force this for now */ + /* + * Force this for now. + */ if (!mainPtr->winPtr->mainPtr) { mainPtr->winPtr->mainPtr = mainPtr; } while (systemFont->systemName) { nsFont = (NSFont*) CTFontCreateUIFontForLanguage( @@ -411,21 +422,21 @@ * TkpGetNativeFont -- * * Map a platform-specific native font name to a TkFont. * * Results: - * The return value is a pointer to a TkFont that represents the - * native font. If a native font by the given name could not be - * found, the return value is NULL. + * The return value is a pointer to a TkFont that represents the native + * font. If a native font by the given name could not be found, the return + * value is NULL. * - * Every call to this procedure returns a new TkFont structure, even - * if the name has already been seen before. The caller should call + * Every call to this procedure returns a new TkFont structure, even if + * the name has already been seen before. The caller should call * TkpDeleteFont() when the font is no longer needed. * - * The caller is responsible for initializing the memory associated - * with the generic TkFont when this function returns and releasing - * the contents of the generics TkFont before calling TkpDeleteFont(). + * The caller is responsible for initializing the memory associated with + * the generic TkFont when this function returns and releasing the + * contents of the generics TkFont before calling TkpDeleteFont(). * * Side effects: * None. * *--------------------------------------------------------------------------- @@ -447,12 +458,12 @@ } else if (strcmp(name, MENUITEMFONT_NAME) == 0) { themeFontId = kThemeMenuItemFont; } else { return NULL; } - ctFont = CTFontCreateUIFontForLanguage(HIThemeGetUIFontType( - themeFontId), 0, NULL); + ctFont = CTFontCreateUIFontForLanguage( + HIThemeGetUIFontType(themeFontId), 0, NULL); if (ctFont) { fontPtr = ckalloc(sizeof(MacFont)); InitFont((NSFont*) ctFont, NULL, fontPtr); } @@ -466,23 +477,22 @@ * * Given a desired set of attributes for a font, find a font with the * closest matching attributes. * * Results: - * The return value is a pointer to a TkFont that represents the font - * with the desired attributes. If a font with the desired attributes - * could not be constructed, some other font will be substituted - * automatically. - * - * Every call to this procedure returns a new TkFont structure, even - * if the specified attributes have already been seen before. The - * caller should call TkpDeleteFont() to free the platform- specific - * data when the font is no longer needed. - * - * The caller is responsible for initializing the memory associated - * with the generic TkFont when this function returns and releasing - * the contents of the generic TkFont before calling TkpDeleteFont(). + * The return value is a pointer to a TkFont that represents the font with + * the desired attributes. If a font with the desired attributes could not + * be constructed, some other font will be substituted automatically. + * + * Every call to this procedure returns a new TkFont structure, even if + * the specified attributes have already been seen before. The caller + * should call TkpDeleteFont() to free the platform- specific data when + * the font is no longer needed. + * + * The caller is responsible for initializing the memory associated with + * the generic TkFont when this function returns and releasing the + * contents of the generic TkFont before calling TkpDeleteFont(). * * Side effects: * None. * *--------------------------------------------------------------------------- @@ -490,20 +500,20 @@ TkFont * TkpGetFontFromAttributes( TkFont *tkFontPtr, /* If non-NULL, store the information in this * existing TkFont structure, rather than - * allocating a new structure to hold the - * font; the existing contents of the font - * will be released. If NULL, a new TkFont - * structure is allocated. */ + * allocating a new structure to hold the font; + * the existing contents of the font will be + * released. If NULL, a new TkFont structure is + * allocated. */ Tk_Window tkwin, /* For display where font will be used. */ const TkFontAttributes *faPtr) /* Set of attributes to match. */ { MacFont *fontPtr; - int points = (int)(TkFontGetPoints(tkwin, faPtr->size) + 0.5); + int points = (int) (TkFontGetPoints(tkwin, faPtr->size) + 0.5); NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr); NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5); NSFont *nsFont; nsFont = FindNSFont(faPtr->family, traits, weight, points, 0); @@ -536,13 +546,13 @@ *--------------------------------------------------------------------------- * * TkpDeleteFont -- * * Called to release a font allocated by TkpGetNativeFont() or - * TkpGetFontFromAttributes(). The caller should have already - * released the fields of the TkFont that are used exclusively by the - * generic TkFont code. + * TkpGetFontFromAttributes(). The caller should have already released the + * fields of the TkFont that are used exclusively by the generic TkFont + * code. * * Results: * TkFont is deallocated. * * Side effects: @@ -565,12 +575,12 @@ /* *--------------------------------------------------------------------------- * * TkpGetFontFamilies -- * - * Return information about the font families that are available on - * the display of the given window. + * Return information about the font families that are available on the + * display of the given window. * * Results: * Modifies interp's result object to hold a list of all the available * font families. * @@ -598,16 +608,16 @@ /* *------------------------------------------------------------------------- * * TkpGetSubFonts -- * - * A function used by the testing package for querying the actual - * screen fonts that make up a font object. + * A function used by the testing package for querying the actual screen + * fonts that make up a font object. * * Results: - * Modifies interp's result object to hold a list containing the names - * of the screen fonts that make up the given font object. + * Modifies interp's result object to hold a list containing the names of + * the screen fonts that make up the given font object. * * Side effects: * None. * *------------------------------------------------------------------------- @@ -640,12 +650,12 @@ /* *---------------------------------------------------------------------- * * TkpGetFontAttrsForChar -- * - * Retrieve the font attributes of the actual font used to render a - * given character. + * Retrieve the font attributes of the actual font used to render a given + * character. * * Results: * None. * * Side effects: @@ -743,14 +753,13 @@ * * This one is almost the same as Tk_MeasureChars(), but with access to * all the characters on the line for context. * * Results: - * The return value is the number of bytes from source that - * fit into the span that extends from 0 to maxLength. *lengthPtr is - * filled with the x-coordinate of the right edge of the last - * character that did fit. + * The return value is the number of bytes from source that fit into the + * span that extends from 0 to maxLength. *lengthPtr is filled with the + * x-coordinate of the right edge of the last character that did fit. * * Side effects: * None. * *--------------------------------------------------------------------------- @@ -772,15 +781,15 @@ * the flags argument is ignored. */ int flags, /* Various flag bits OR-ed together: * TK_PARTIAL_OK means include the last char * which only partially fits on this line. * TK_WHOLE_WORDS means stop on a word - * boundary, if possible. TK_AT_LEAST_ONE - * means return at least one character even - * if no characters fit. If TK_WHOLE_WORDS - * and TK_AT_LEAST_ONE are set and the first - * word doesn't fit, we return at least one + * boundary, if possible. TK_AT_LEAST_ONE means + * return at least one character even if no + * characters fit. If TK_WHOLE_WORDS and + * TK_AT_LEAST_ONE are set and the first word + * doesn't fit, we return at least one * character or whatever characters fit into * maxLength. TK_ISOLATE_END means that the * last character should not be considered in * context with the rest of the string (used * for breaking lines). */ @@ -862,18 +871,17 @@ [cs characterIsMember:[string characterAtIndex:(index - 1)]]) { index--; } /* - * If there is no line breakpoint in the source string between - * its start and the index position that fits in maxWidth, then + * If there is no line breakpoint in the source string between its + * start and the index position that fits in maxWidth, then * CTTypesetterSuggestLineBreak() returns that very last index. - * However if the TK_WHOLE_WORDS flag is set, we want to break - * at a word boundary. In this situation, unless TK_AT_LEAST_ONE - * is set, we must report that zero chars actually fit (in other - * words the smallest word of the source string is still larger - * than maxWidth). + * However if the TK_WHOLE_WORDS flag is set, we want to break at a + * word boundary. In this situation, unless TK_AT_LEAST_ONE is set, we + * must report that zero chars actually fit (in other words the + * smallest word of the source string is still larger than maxWidth). */ if ((index >= start) && (index < len) && (flags & TK_WHOLE_WORDS) && !(flags & TK_AT_LEAST_ONE) && ![cs characterIsMember:[string characterAtIndex:index]]) { @@ -901,13 +909,16 @@ line = CTTypesetterCreateLine(typesetter, range); width = CTLineGetTypographicBounds(line, NULL, NULL, NULL); CFRelease(line); } - /* The call to CTTypesetterSuggestClusterBreak above will always - return at least one character regardless of whether it exceeded - it or not. Clean that up now. */ + /* + * The call to CTTypesetterSuggestClusterBreak above will always return + * at least one character regardless of whether it exceeded it or not. + * Clean that up now. + */ + while (width > maxWidth && !(flags & TK_PARTIAL_OK) && index > start+(flags & TK_AT_LEAST_ONE)) { range.length = --index; line = CTTypesetterCreateLine(typesetter, range); width = CTLineGetTypographicBounds(line, NULL, NULL, NULL); @@ -944,11 +955,11 @@ * * With ATSUI we need the line context to do this right, so we have the * actual implementation in TkpDrawCharsInContext(). * * Results: - * None. + * None. * * Side effects: * Information gets drawn on the screen. * *--------------------------------------------------------------------------- @@ -962,12 +973,12 @@ Tk_Font tkfont, /* Font in which characters will be drawn; must * be the same as font used in GC. */ const char *source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ int x, int y) /* Coordinates at which to place origin of the * string when drawing. */ @@ -984,12 +995,12 @@ Tk_Font tkfont, /* Font in which characters will be drawn; * must be the same as font used in GC. */ const char *source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ double x, double y, /* Coordinates at which to place origin of * string when drawing. */ @@ -1027,12 +1038,12 @@ Tk_Font tkfont, /* Font in which characters will be drawn; must * be the same as font used in GC. */ const char * source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ int rangeStart, /* Index of first byte to draw. */ int rangeLength, /* Length of range to draw in bytes. */ @@ -1052,12 +1063,12 @@ Tk_Font tkfont, /* Font in which characters will be drawn; must * be the same as font used in GC. */ const char * source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ int rangeStart, /* Index of first byte to draw. */ int rangeLength, /* Length of range to draw in bytes. */ @@ -1089,10 +1100,11 @@ string = [[NSString alloc] initWithBytesNoCopy:(void*)source length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO]; if (!string) { return; } + context = drawingContext.context; fg = TkMacOSXCreateCGColor(gc, gc->foreground); attributes = [fontPtr->nsAttributes mutableCopy]; [attributes setObject:(id)fg forKey:(id)kCTForegroundColorAttributeName]; CFRelease(fg); @@ -1117,10 +1129,11 @@ CGContextSetTextPosition(context, x, y); start = Tcl_NumUtfChars(source, rangeStart); len = Tcl_NumUtfChars(source, rangeStart + rangeLength); if (start > 0) { CGRect clipRect = CGRectInfinite, startBounds; + line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start)); startBounds = CTLineGetImageBounds(line, context); CFRelease(line); clipRect.origin.x = startBounds.origin.x + startBounds.size.width; CGContextClipToRect(context, clipRect); @@ -1239,13 +1252,14 @@ traitsOfFont:nsFont]; id underline = [nsAttributes objectForKey: NSUnderlineStyleAttributeName]; id strikethrough = [nsAttributes objectForKey: NSStrikethroughStyleAttributeName]; + objv[i++] = Tcl_NewStringObj(familyName, -1); - objv[i++] = Tcl_NewIntObj([nsFont pointSize]); -#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1)) + objv[i++] = Tcl_NewWideIntObj([nsFont pointSize]); +#define S(s) Tcl_NewStringObj(STRINGIFY(s), (int)(sizeof(STRINGIFY(s))-1)) objv[i++] = (traits & NSBoldFontMask) ? S(bold) : S(normal); objv[i++] = (traits & NSItalicFontMask) ? S(italic) : S(roman); if ([underline respondsToSelector:@selector(intValue)] && ([underline intValue] & (NSUnderlineStyleSingle | NSUnderlineStyleThick | NSUnderlineStyleDouble))) { @@ -1265,12 +1279,13 @@ *---------------------------------------------------------------------- * * TkMacOSXUseAntialiasedText -- * * Enables or disables application-wide use of antialiased text (where - * available). Sets up a linked Tcl global variable to allow - * disabling of antialiased text from tcl. + * available). Sets up a linked Tcl global variable to allow disabling of + * antialiased text from Tcl. + * * The possible values for this variable are: * * -1 - Use system default as configurable in "System Prefs" -> "General". * 0 - Unconditionally disable antialiasing. * 1 - Unconditionally enable antialiasing. Index: macosx/tkMacOSXFont.h ================================================================== --- macosx/tkMacOSXFont.h +++ macosx/tkMacOSXFont.h @@ -1,9 +1,9 @@ /* * tkMacOSXFont.h -- * - * Contains the Macintosh implementation of the platform-independant + * Contains the Macintosh implementation of the platform-independent * font package interface. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. Index: macosx/tkMacOSXHLEvents.c ================================================================== --- macosx/tkMacOSXHLEvents.c +++ macosx/tkMacOSXHLEvents.c @@ -31,16 +31,17 @@ /* * 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); +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); +static void RunSimpleTclCommand(Tcl_Interp *interp, + const char *command); #pragma mark TKApplication(TKHLEvents) @implementation TKApplication(TKHLEvents) - (void) terminate: (id) sender @@ -76,59 +77,51 @@ } - (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - Tcl_Interp *interp = _eventInterp; - - if (interp && - Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){ - int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication", - -1, TCL_EVAL_GLOBAL); - if (code != TCL_OK) { - Tcl_BackgroundException(_eventInterp, code); - } - } + RunSimpleTclCommand(_eventInterp, "::tk::mac::OpenApplication"); } - (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { [NSApp activateIgnoringOtherApps: YES]; - if (_eventInterp && Tcl_FindCommand(_eventInterp, - "::tk::mac::ReopenApplication", NULL, 0)) { - int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication", - -1, TCL_EVAL_GLOBAL); - if (code != TCL_OK){ - Tcl_BackgroundException(_eventInterp, code); - } - } + RunSimpleTclCommand(_eventInterp, "::tk::mac::ReopenApplication"); } - (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - if (_eventInterp && - Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)){ - int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowPreferences", - -1, TCL_EVAL_GLOBAL); - if (code != TCL_OK) { - Tcl_BackgroundException(_eventInterp, code); - } - } + RunSimpleTclCommand(_eventInterp, "::tk::mac::ShowPreferences"); } - (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument"); + tkMacOSXProcessFiles(event, replyEvent, _eventInterp, + "::tk::mac::OpenDocument"); } - (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::PrintDocument"); + NSString* file = [[event paramDescriptorForKeyword:keyDirectObject] + stringValue]; + const char *printFile = [file UTF8String]; + Tcl_DString print; + + Tcl_DStringInit(&print); + if (Tcl_FindCommand(_eventInterp, "::tk::mac::PrintDocument", NULL, 0)) { + Tcl_DStringAppend(&print, "::tk::mac::PrintDocument", -1); + } + Tcl_DStringAppendElement(&print, printFile); + int tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&print), + Tcl_DStringLength(&print), TCL_EVAL_GLOBAL); + if (tclErr != TCL_OK) { + Tcl_BackgroundException(_eventInterp, tclErr); + } } - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { @@ -150,68 +143,77 @@ if (theDesc == nil) { return; } err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType, - NULL, 0, NULL); + NULL, 0, NULL); if (err != noErr) { sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err); - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, - errString, strlen(errString)); + AEPutParamPtr((AppleEvent *) [replyEvent aeDesc], keyErrorString, + typeChar, errString, strlen(errString)); return; } - if (MissedAnyParameters((AppleEvent*)theDesc)) { + if (MissedAnyParameters((AppleEvent *) theDesc)) { sprintf(errString, "AEDoScriptHandler: extra parameters"); - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, - errString, strlen(errString)); + AEPutParamPtr((AppleEvent *) [replyEvent aeDesc], keyErrorString, + typeChar, errString, strlen(errString)); return; } + Tcl_Preserve(_eventInterp); if (initialType == typeFileURL || initialType == typeAlias) { /* * The descriptor can be coerced to a file url. Source the file, or * pass the path as a string argument to ::tk::mac::DoScriptFile if * that procedure exists. */ + err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type, - (Ptr) URLBuffer, URL_MAX_LENGTH, &actual); + (Ptr) URLBuffer, URL_MAX_LENGTH, &actual); if (err == noErr && actual > 0){ URLBuffer[actual] = '\0'; NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer]; NSURL *fileURL = [NSURL URLWithString:urlString]; Tcl_DString command; + Tcl_DStringInit(&command); - if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){ + if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)) { Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1); } else { Tcl_DStringAppend(&command, "source", -1); } Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]); tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command), - Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); + Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); } - } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, - NULL, 0, &actual)) { + } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, + &type, NULL, 0, &actual)) { if (actual > 0) { /* * The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or * or pass the text as a string argument to ::tk::mac::DoScriptText * if that procedure exists. */ + char *data = ckalloc(actual + 1); - if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, - data, actual, NULL)) { - if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){ + + if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, + &type, data, actual, NULL)) { + if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", + NULL, 0)) { Tcl_DString command; + Tcl_DStringInit(&command); Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1); Tcl_DStringAppendElement(&command, data); - tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command), - Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); + tclErr = Tcl_EvalEx(_eventInterp, + Tcl_DStringValue(&command), + Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); } else { - tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL); + tclErr = Tcl_EvalEx(_eventInterp, data, actual, + TCL_EVAL_GLOBAL); } } ckfree(data); } } else { @@ -222,36 +224,78 @@ typeString[i] = ((char*)&initialType)[3-i]; } typeString[4] = '\0'; sprintf(errString, "AEDoScriptHandler: invalid script type '%s', " "must be coercable to 'furl' or 'utf8'", typeString); - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString, - strlen(errString)); + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, + typeChar, errString, strlen(errString)); } + /* * If we ran some Tcl code, put the result in the reply. */ + if (tclErr >= 0) { int reslen; const char *result = - Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen); + Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen); + if (tclErr == TCL_OK) { - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar, - result, reslen); + AEPutParamPtr((AppleEvent *) [replyEvent aeDesc], keyDirectObject, + typeChar, result, reslen); } else { - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, - result, reslen); - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32, - (Ptr) &tclErr,sizeof(int)); + AEPutParamPtr((AppleEvent *) [replyEvent aeDesc], keyErrorString, + typeChar, result, reslen); + AEPutParamPtr((AppleEvent *) [replyEvent aeDesc], keyErrorNumber, + typeSInt32, (Ptr) &tclErr, sizeof(int)); } } + Tcl_Release(_eventInterp); return; } + +- (void)handleURLEvent:(NSAppleEventDescriptor*)event + withReplyEvent:(NSAppleEventDescriptor*)replyEvent +{ + NSString* url = [[event paramDescriptorForKeyword:keyDirectObject] + stringValue]; + const char *cURL = [url UTF8String]; + Tcl_DString launch; + + Tcl_DStringInit(&launch); + if (Tcl_FindCommand(_eventInterp, "::tk::mac::LaunchURL", NULL, 0)) { + Tcl_DStringAppend(&launch, "::tk::mac::LaunchURL", -1); + } + Tcl_DStringAppendElement(&launch, cURL); + int tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&launch), + Tcl_DStringLength(&launch), TCL_EVAL_GLOBAL); + if (tclErr != TCL_OK) { + Tcl_BackgroundException(_eventInterp, tclErr); + } +} + @end #pragma mark - + +static void +RunSimpleTclCommand( + Tcl_Interp *interp, + const char *command) +{ + int code; + if (interp && Tcl_FindCommand(interp, command, NULL, 0)) { + Tcl_Preserve(interp); + code = Tcl_EvalEx(interp, command, -1, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + Tcl_BackgroundException(interp, code); + } + Tcl_Release(interp); + } +} + /* *---------------------------------------------------------------------- * * TkMacOSXProcessFiles -- * @@ -285,11 +329,12 @@ AEKeyword keyword; Tcl_DString command, pathName; int code; /* - * Do nothing if we don't have an interpreter or the procedure doesn't exist. + * Do nothing if we don't have an interpreter or the procedure doesn't + * exist. */ if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) { return; } @@ -351,16 +396,18 @@ /* * Handle the event by evaluating the Tcl expression we constructed. */ + Tcl_Preserve(interp); code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_BackgroundException(interp, code); } Tcl_DStringFree(&command); + Tcl_Release(interp); } /* *---------------------------------------------------------------------- * @@ -380,11 +427,12 @@ void TkMacOSXInitAppleEvents( Tcl_Interp *interp) /* not used */ { - NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager]; + NSAppleEventManager *aeManager = + [NSAppleEventManager sharedAppleEventManager]; static Boolean initialized = FALSE; if (!initialized) { initialized = TRUE; @@ -407,16 +455,21 @@ [aeManager setEventHandler:NSApp andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEOpenDocuments]; [aeManager setEventHandler:NSApp - andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:) + andSelector:@selector(handlePrintDocumentsEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEPrintDocuments]; [aeManager setEventHandler:NSApp andSelector:@selector(handleDoScriptEvent:withReplyEvent:) forEventClass:kAEMiscStandards andEventID:kAEDoScript]; + + [aeManager setEventHandler:NSApp + andSelector:@selector(handleURLEvent:withReplyEvent:) + forEventClass:kInternetEventClass andEventID:kAEGetURL]; + } } /* *---------------------------------------------------------------------- @@ -486,20 +539,25 @@ ReallyKillMe( Tcl_Event *eventPtr, int flags) { Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp; + + Tcl_Preserve(interp); + int quit = Tcl_FindCommand(interp, "::tk::mac::Quit", NULL, 0)!=NULL; - int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL); + int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, + TCL_EVAL_GLOBAL); if (code != TCL_OK) { /* * Should be never reached... */ Tcl_BackgroundException(interp, code); } + Tcl_Release(interp); return 1; } /* *---------------------------------------------------------------------- @@ -529,14 +587,13 @@ typeWildCard, &returnedType, NULL, 0, &actualSize); return (err != errAEDescNotFound); } - /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXImage.c ================================================================== --- macosx/tkMacOSXImage.c +++ macosx/tkMacOSXImage.c @@ -21,11 +21,11 @@ _XInitImageFuncPtrs( XImage *image) { return 0; } - + /* *---------------------------------------------------------------------- * * TkMacOSXCreateCGImageWithXImage -- * @@ -79,40 +79,41 @@ } } else { data = memcpy(ckalloc(len), image->data + image->xoffset, len); } if (data) { - provider = CGDataProviderCreateWithData(data, data, len, releaseData); + provider = CGDataProviderCreateWithData(data, data, len, + releaseData); } if (provider) { - img = CGImageMaskCreate(image->width, image->height, bitsPerComponent, - bitsPerPixel, image->bytes_per_line, provider, decode, 0); + 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) { - + } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) { /* * Color image */ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); if (image->width == 0 && image->height == 0) { - /* * CGCreateImage complains on early macOS releases. */ return NULL; } bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = (image->byte_order == MSBFirst ? - kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big); + kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big); bitmapInfo |= kCGImageAlphaLast; data = memcpy(ckalloc(len), image->data + image->xoffset, len); if (data) { - provider = CGDataProviderCreateWithData(data, data, len, releaseData); + 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); @@ -125,11 +126,10 @@ TkMacOSXDbgMsg("Unsupported image type"); } return img; } - /* *---------------------------------------------------------------------- * * XGetImage -- * @@ -177,19 +177,18 @@ 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; + 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__ @@ -203,35 +202,35 @@ if (width == 0 || height == 0) { return NULL; } bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable, - x, y, width, height); + 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 ) { + 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. + * 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) { @@ -246,20 +245,20 @@ *(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); + (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. + * 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; } @@ -321,44 +320,44 @@ 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; + 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; } @@ -387,10 +386,11 @@ { if (image && image->data) { unsigned char *dstPtr = ((unsigned char*) image->data) + (y * image->bytes_per_line) + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); + if (image->bits_per_pixel == 32) { *((unsigned int*) dstPtr) = pixel; } else { unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff; unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff; @@ -418,11 +418,11 @@ } } } return 0; } - + /* *---------------------------------------------------------------------- * * XCreateImage -- * @@ -449,10 +449,11 @@ unsigned int height, int bitmap_pad, int bytes_per_line) { XImage *ximage; + display->request++; ximage = ckalloc(sizeof(XImage)); ximage->height = height; ximage->width = width; @@ -459,13 +460,16 @@ 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 + + /* + * 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; @@ -474,11 +478,14 @@ ximage->bitmap_unit = 8; } if (bitmap_pad) { ximage->bitmap_pad = bitmap_pad; } else { - /* Use 16 byte alignment for best Quartz perfomance */ + /* + * Use 16 byte alignment for best Quartz perfomance. + */ + ximage->bitmap_pad = 128; } if (bytes_per_line) { ximage->bytes_per_line = bytes_per_line; } else { @@ -509,13 +516,13 @@ /* *---------------------------------------------------------------------- * * TkPutImage -- * - * Copies a rectangular subimage of an XImage into a drawable. - * Currently this is only called by TkImgPhotoDisplay, using - * a Window as the drawable. + * Copies a rectangular subimage of an XImage into a drawable. Currently + * this is only called by TkImgPhotoDisplay, using a Window as the + * drawable. * * Results: * None. * * Side effects: @@ -557,17 +564,19 @@ if (!(macDraw->flags & TK_IS_PIXMAP)) { CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop); } if (img) { - /* If the XImage has big pixels, the source is rescaled to reflect + /* + * If the XImage has big pixels, the source is rescaled to reflect * the actual pixel dimensions. This is not currently used, but * could arise if the image were copied from a retina monitor and * redrawn on an ordinary monitor. */ int pp = image->pixelpower; + bounds = CGRectMake(0, 0, image->width, image->height); srcRect = CGRectMake(src_x<foreground, gc->background, Index: macosx/tkMacOSXInit.c ================================================================== --- macosx/tkMacOSXInit.c +++ macosx/tkMacOSXInit.c @@ -26,10 +26,17 @@ * to the auto_path. */ static char scriptPath[PATH_MAX + 1] = ""; +/* + * Forward declarations... + */ + +static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip, + int objc, Tcl_Obj *const objv[]); + #pragma mark TKApplication(TKInit) @implementation TKApplication @synthesize poolLock = _poolLock; @synthesize macMinorVersion = _macMinorVersion; @@ -43,11 +50,11 @@ #undef DEBUG_LOCK @implementation TKApplication(TKInit) - (void) _resetAutoreleasePool { - if([self poolLock] == 0) { + if ([self poolLock] == 0) { [_mainPool drain]; _mainPool = [NSAutoreleasePool new]; } else { #ifdef DEBUG_LOCK fprintf(stderr, "Pool is locked with count %d!!!!\n", [self poolLock]); @@ -100,11 +107,10 @@ * Construct the menu bar. */ _defaultMainMenu = nil; [self _setupMenus]; - /* * Initialize event processing. */ TkMacOSXInitAppleEvents(_eventInterp); @@ -115,16 +121,26 @@ TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0); } -(void)applicationDidFinishLaunching:(NSNotification *)notification { + /* - * It is not safe to force activation of the NSApp until this - * method is called. Activating too early can cause the menu - * bar to be unresponsive. + * It is not safe to force activation of the NSApp until this method is + * called. Activating too early can cause the menu bar to be unresponsive. */ + [NSApp activateIgnoringOtherApps: YES]; + + /* + * Process events to ensure that the root window is fully initialized. See + * ticket 56a1823c73. + */ + + [NSApp _lockAutoreleasePool]; + while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {} + [NSApp _unlockAutoreleasePool]; } - (void) _setup: (Tcl_Interp *) interp { /* @@ -140,11 +156,11 @@ /* * Record the OS version we are running on. */ int minorVersion; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion); #else NSOperatingSystemVersion systemVersion; systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; minorVersion = systemVersion.minorVersion; @@ -299,12 +315,12 @@ close(0); close(1); } /* - * Instantiate our NSApplication object. This needs to be - * done before we check whether to open a console window. + * Instantiate our NSApplication object. This needs to be done before + * we check whether to open a console window. */ NSAutoreleasePool *pool = [NSAutoreleasePool new]; [[NSUserDefaults standardUserDefaults] registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys: @@ -315,10 +331,21 @@ nil]]; [TKApplication sharedApplication]; [pool drain]; [NSApp _setup:interp]; [NSApp finishLaunching]; + Tk_MacOSXSetupTkNotifier(); + + /* + * If the root window is mapped before the App has finished launching + * it will open off screen (see ticket 56a1823c73). To avoid this we + * ask Tk to process an event with no wait. We expect Tcl_DoOneEvent + * to wait until the Mac event loop has been created and then return + * immediately since the queue is empty. + */ + + Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT); /* * If we don't have a TTY and stdin is a special character file of * length 0, (e.g. /dev/null, which is what Finder sets when double * clicking Wish) then use the Tk based console interpreter. @@ -331,12 +358,12 @@ Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); /* - * Only show the console if we don't have a startup script - * and tcl_interactive hasn't been set already. + * Only show the console if we don't have a startup script and + * tcl_interactive hasn't been set already. */ if (Tcl_GetStartupScript(NULL) == NULL) { const char *intvar = Tcl_GetVar2(interp, "tcl_interactive", NULL, TCL_GLOBAL_ONLY); @@ -351,12 +378,10 @@ } } } - Tk_MacOSXSetupTkNotifier(); - if (tkLibPath[0] != '\0') { Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY); } if (scriptPath[0] != '\0') { @@ -364,20 +389,24 @@ TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); } Tcl_CreateObjCommand(interp, "::tk::mac::standardAboutPanel", TkMacOSXStandardAboutPanelObjCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::mac::registerServiceWidget", + TkMacOSXRegisterServiceWidgetObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap", TkMacOSXIconBitmapObjCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", + TkMacOSXGetAppPathCmd, NULL, NULL); /* - * Workaround for 3efbe4a397; console not accepting keyboard input on 10.14 - * if displayed before main window. This places console in background and it - * accepts input after being raised. + * Initialize the NSServices object here. Apple's docs say to do this + * in applicationDidFinishLaunching, but the Tcl interpreter is not + * initialized until this function call. */ - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + TkMacOSXServices_Init(interp); return TCL_OK; } /* @@ -414,10 +443,58 @@ name = p+1; } } Tcl_DStringAppend(namePtr, name, -1); } + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetAppPathCmd -- + * + * Returns the path of the Wish application bundle. + * + * Results: + * Returns the application path. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TkMacOSXGetAppPathCmd( + ClientData ignored, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return TCL_ERROR; + } + + /* + * Get the application path URL and convert it to a string path reference. + */ + + CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFStringRef appPath = + CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle); + + /* + * Convert (and copy) the string reference into a Tcl result. + */ + + Tcl_SetObjResult(interp, Tcl_NewStringObj( + CFStringGetCStringPtr(appPath, CFStringGetSystemEncoding()), -1)); + + CFRelease(mainBundleURL); + CFRelease(appPath); + return TCL_OK; +} /* *---------------------------------------------------------------------- * * TkpDisplayWarning -- @@ -481,11 +558,11 @@ if (appMainURL != NULL) { CFURLRef scriptFldrURL; char startupScript[PATH_MAX + 1]; - if (CFURLGetFileSystemRepresentation (appMainURL, true, + if (CFURLGetFileSystemRepresentation(appMainURL, true, (unsigned char *) startupScript, PATH_MAX)) { Tcl_SetStartupScript(Tcl_NewStringObj(startupScript,-1), NULL); scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(NULL, appMainURL); if (scriptFldrURL != NULL) { Index: macosx/tkMacOSXInt.h ================================================================== --- macosx/tkMacOSXInt.h +++ macosx/tkMacOSXInt.h @@ -69,10 +69,11 @@ HIShapeRef drawRgn; /* Clipped drawing region */ int referenceCount; /* Don't delete toplevel until children are * gone. */ struct TkWindowPrivate *toplevel; /* Pointer to the toplevel datastruct. */ + CGFloat fillRGBA[4]; /* Background used by the ttk FillElement */ int flags; /* Various state see defines below. */ }; typedef struct TkWindowPrivate MacDrawable; /* @@ -84,10 +85,11 @@ #define TK_HOST_EXISTS 0x04 #define TK_DRAWN_UNDER_MENU 0x08 #define TK_IS_PIXMAP 0x10 #define TK_IS_BW_PIXMAP 0x20 #define TK_DO_NOT_DRAW 0x40 +#define TTK_HAS_CONTRASTING_BG 0x80 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the * TkWindow structure for the window, but in the MacWin. This way we can @@ -198,14 +200,24 @@ MODULE_SCOPE void TkpRetainRegion(TkRegion r); MODULE_SCOPE void TkpReleaseRegion(TkRegion r); MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta); MODULE_SCOPE Bool TkpAppIsDrawing(void); MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin); -MODULE_SCOPE Bool TkTestAppIsDrawing(void); +MODULE_SCOPE Bool TkTestLogDisplay(void); +MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin); /* * Include the stubbed internal platform-specific API. */ #include "tkIntPlatDecls.h" #endif /* _TKMACINT */ + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ Index: macosx/tkMacOSXKeyEvent.c ================================================================== --- macosx/tkMacOSXKeyEvent.c +++ macosx/tkMacOSXKeyEvent.c @@ -22,26 +22,23 @@ #define TK_MAC_DEBUG_KEYBOARD #endif */ #define NS_KEYLOG 0 - -static Tk_Window grabWinPtr = NULL; - /* Current grab window, NULL if no grab. */ static Tk_Window keyboardGrabWinPtr = NULL; /* Current keyboard grab window. */ static NSWindow *keyboardGrabNSWindow = nil; - /* NSWindow for the current keyboard grab window. */ + /* NSWindow for the current keyboard grab + * window. */ static NSModalSession modalSession = nil; - static BOOL processingCompose = NO; static BOOL finishedCompose = NO; - static int caret_x = 0, caret_y = 0, caret_height = 0; -static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state); -static unsigned isFunctionKey(unsigned int code); +static void setupXEvent(XEvent *xEvent, NSWindow *w, + unsigned int state); +static unsigned isFunctionKey(unsigned int code); unsigned short releaseCode; #pragma mark TKApplication(TKKeyEvent) @@ -51,26 +48,25 @@ - (NSEvent *) tkProcessKeyEvent: (NSEvent *) theEvent { #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); #endif - NSWindow* w; - NSEventType type = [theEvent type]; + NSWindow *w; + NSEventType type = [theEvent type]; NSUInteger modifiers = ([theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask); - NSUInteger len = 0; - BOOL repeat = NO; - unsigned short keyCode = [theEvent keyCode]; - NSString *characters = nil, *charactersIgnoringModifiers = nil; + NSUInteger len = 0; + BOOL repeat = NO; + unsigned short keyCode = [theEvent keyCode]; + NSString *characters = nil, *charactersIgnoringModifiers = nil; static NSUInteger savedModifiers = 0; static NSMutableArray *nsEvArray; - if (nsEvArray == nil) - { + if (nsEvArray == nil) { nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1]; processingCompose = NO; - } + } w = [theEvent window]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; XEvent xEvent; @@ -110,351 +106,393 @@ default: return theEvent; /* Unrecognized key event. */ } - /* Create an Xevent to add to the Tk queue. */ + /* + * Create an Xevent to add to the Tk queue. + */ + if (!processingCompose) { unsigned int state = 0; if (modifiers & NSAlphaShiftKeyMask) { - state |= LockMask; + state |= LockMask; } if (modifiers & NSShiftKeyMask) { - state |= ShiftMask; + state |= ShiftMask; } if (modifiers & NSControlKeyMask) { - state |= ControlMask; + state |= ControlMask; } if (modifiers & NSCommandKeyMask) { - state |= Mod1Mask; /* command key */ + state |= Mod1Mask; /* command key */ } if (modifiers & NSAlternateKeyMask) { - state |= Mod2Mask; /* option key */ + state |= Mod2Mask; /* option key */ } if (modifiers & NSNumericPadKeyMask) { - state |= Mod3Mask; + state |= Mod3Mask; } if (modifiers & NSFunctionKeyMask) { - state |= Mod4Mask; + state |= Mod4Mask; } /* - * Events are only received for the front Window on the Macintosh. - * So to build an XEvent we look up the Tk window associated to the - * Front window. If a different window has a local grab we ignore - * the event. + * Events are only received for the front Window on the Macintosh. So + * to build an XEvent we look up the Tk window associated to the Front + * window. If a different window has a local grab we ignore the event. */ TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; if (tkwin) { TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr; - if (grabWinPtr && - grabWinPtr != winPtr && - !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ - grabWinPtr->mainPtr == winPtr->mainPtr) { + + if (grabWinPtr + && grabWinPtr != winPtr + && !winPtr->dispPtr->grabFlags /* this means the grab is local. */ + && grabWinPtr->mainPtr == winPtr->mainPtr) { return theEvent; } } else { tkwin = (Tk_Window) winPtr->dispPtr->focusPtr; } if (!tkwin) { - TkMacOSXDbgMsg("tkwin == NULL"); - return theEvent; /* Give up. No window for this event. */ - } - - /* - * If it's a function key, or we have modifiers other than Shift or Alt, - * pass it straight to Tk. Otherwise we'll send for input processing. - */ - - int code = (len == 0) ? - 0 : [charactersIgnoringModifiers characterAtIndex: 0]; - if (type != NSKeyDown || isFunctionKey(code) - || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) { - - XEvent xEvent; - setupXEvent(&xEvent, w, state); - - if (type == NSFlagsChanged) { - if (savedModifiers > modifiers) { - xEvent.xany.type = KeyRelease; - } else { - xEvent.xany.type = KeyPress; - } - - /* - * Use special '-1' to signify a special keycode to our platform - * specific code in tkMacOSXKeyboard.c. This is rather like what - * happens on Windows. - */ - - xEvent.xany.send_event = -1; - - /* - * Set keycode (which was zero) to the changed modifier - */ - - xEvent.xkey.keycode = (modifiers ^ savedModifiers); - } else { - if (type == NSKeyUp || repeat) { - xEvent.xany.type = KeyRelease; - } else { - xEvent.xany.type = KeyPress; - } - - /* For command key, take input manager's word so things - like dvorak / qwerty layout work. */ - if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask - && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask - && len > 0 && !isFunctionKey(code)) { - // head off keycode-based translation in tkMacOSXKeyboard.c - xEvent.xkey.nbytes = [characters length]; //len - } - - if ([characters length] > 0) { - xEvent.xkey.keycode = - (keyCode << 16) | (UInt16) [characters characterAtIndex:0]; - if (![characters getCString:xEvent.xkey.trans_chars - maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) { - /* prevent SF bug 2907388 (crash on some composite chars) */ - //PENDING: we might not need this anymore - TkMacOSXDbgMsg("characters too long"); - return theEvent; - } - } - - if (repeat) { - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); - xEvent.xany.type = KeyPress; - xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - } - } - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); - savedModifiers = modifiers; - return theEvent; - } /* if send straight to TK */ - - } /* if not processing compose */ - - if (type == NSKeyDown) { - if (NS_KEYLOG) - fprintf (stderr, "keyDown: %s compose sequence.\n", - processingCompose == YES ? "Continue" : "Begin"); - processingCompose = YES; - [nsEvArray addObject: theEvent]; - [[w contentView] interpretKeyEvents: nsEvArray]; - [nsEvArray removeObject: theEvent]; - } - - savedModifiers = modifiers; - - return theEvent; -} -@end - - - -@implementation TKContentView + TkMacOSXDbgMsg("tkwin == NULL"); + return theEvent; /* Give up. No window for this event. */ + } + + /* + * If it's a function key, or we have modifiers other than Shift or + * Alt, pass it straight to Tk. Otherwise we'll send for input + * processing. + */ + + int code = (len == 0) ? 0 : + [charactersIgnoringModifiers characterAtIndex: 0]; + if (type != NSKeyDown || isFunctionKey(code) + || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) { + XEvent xEvent; + + setupXEvent(&xEvent, w, state); + if (type == NSFlagsChanged) { + if (savedModifiers > modifiers) { + xEvent.xany.type = KeyRelease; + } else { + xEvent.xany.type = KeyPress; + } + + /* + * Use special '-1' to signify a special keycode to our + * platform specific code in tkMacOSXKeyboard.c. This is rather + * like what happens on Windows. + */ + + xEvent.xany.send_event = -1; + + /* + * Set keycode (which was zero) to the changed modifier + */ + + xEvent.xkey.keycode = (modifiers ^ savedModifiers); + } else { + if (type == NSKeyUp || repeat) { + xEvent.xany.type = KeyRelease; + } else { + xEvent.xany.type = KeyPress; + } + + /* + * For command key, take input manager's word so things like + * dvorak / qwerty layout work. + */ + + if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask + && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask + && len > 0 && !isFunctionKey(code)) { + // head off keycode-based translation in tkMacOSXKeyboard.c + xEvent.xkey.nbytes = [characters length]; //len + } + + if ([characters length] > 0) { + xEvent.xkey.keycode = (keyCode << 16) | + (UInt16) [characters characterAtIndex:0]; + if (![characters getCString:xEvent.xkey.trans_chars + maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) { + /* prevent SF bug 2907388 (crash on some composite chars) */ + //PENDING: we might not need this anymore + TkMacOSXDbgMsg("characters too long"); + return theEvent; + } + } + + if (repeat) { + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + xEvent.xany.type = KeyPress; + xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + } + } + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + savedModifiers = modifiers; + return theEvent; + } /* if send straight to TK */ + } /* if not processing compose */ + + if (type == NSKeyDown) { + if (NS_KEYLOG) { + TKLog(@"keyDown: %s compose sequence.\n", + processingCompose == YES ? "Continue" : "Begin"); + } + processingCompose = YES; + [nsEvArray addObject: theEvent]; + [[w contentView] interpretKeyEvents: nsEvArray]; + [nsEvArray removeObject: theEvent]; + } + + savedModifiers = modifiers; + return theEvent; +} +@end + + +@implementation TKContentView + +-(id)init { + self = [super init]; + if (self) { + _needsRedisplay = NO; + } + return self; +} + /* implementation (called through interpretKeyEvents:]). */ /* : called when done composing; NOTE: also called when we delete over working text, followed immed. by doCommandBySelector: deleteBackward: */ - (void)insertText: (id)aString { - int i, len = [(NSString *)aString length]; - XEvent xEvent; - - if (NS_KEYLOG) - TKLog (@"insertText '%@'\tlen = %d", aString, len); - processingCompose = NO; - finishedCompose = YES; - - /* first, clear any working text */ - if (privateWorkingText != nil) - [self deleteWorkingText]; - - /* now insert the string as keystrokes */ - setupXEvent(&xEvent, [self window], 0); - xEvent.xany.type = KeyPress; - - for (i =0; i: inserts display of composing characters */ - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange { - NSString *str = [aString respondsToSelector: @selector (string)] ? - [aString string] : aString; - if (NS_KEYLOG) - TKLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str, - (unsigned long) [str length], (unsigned long) selRange.length, - (unsigned long) selRange.location); - - if (privateWorkingText != nil) - [self deleteWorkingText]; - if ([str length] == 0) - return; - - processingCompose = YES; - privateWorkingText = [str copy]; - - //PENDING: insert workingText underlined + NSString *str = [aString respondsToSelector: @selector (string)] ? + [aString string] : aString; + if (NS_KEYLOG) { + TKLog(@"setMarkedText '%@' len =%lu range %lu from %lu", str, + (unsigned long) [str length], (unsigned long) selRange.length, + (unsigned long) selRange.location); + } + + if (privateWorkingText != nil) { + [self deleteWorkingText]; + } + if ([str length] == 0) { + return; + } + + processingCompose = YES; + privateWorkingText = [str copy]; + + //PENDING: insert workingText underlined } - (BOOL)hasMarkedText { - return privateWorkingText != nil; + return privateWorkingText != nil; } - (NSRange)markedRange { - NSRange rng = privateWorkingText != nil - ? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0); - if (NS_KEYLOG) - TKLog (@"markedRange request"); - return rng; + NSRange rng = privateWorkingText != nil + ? NSMakeRange(0, [privateWorkingText length]) + : NSMakeRange(NSNotFound, 0); + + if (NS_KEYLOG) { + TKLog(@"markedRange request"); + } + return rng; } - (void)unmarkText { - if (NS_KEYLOG) - TKLog (@"unmark (accept) text"); - [self deleteWorkingText]; - processingCompose = NO; + if (NS_KEYLOG) { + TKLog(@"unmark (accept) text"); + } + [self deleteWorkingText]; + processingCompose = NO; } /* used to position char selection windows, etc. */ - (NSRect)firstRectForCharacterRange: (NSRange)theRange { - NSRect rect; - NSPoint pt; - - pt.x = caret_x; - pt.y = caret_y; - - pt = [self convertPoint: pt toView: nil]; - pt = [[self window] tkConvertPointToScreen: pt]; - pt.y -= caret_height; - - rect.origin = pt; - rect.size.width = caret_height; - rect.size.height = caret_height; - return rect; + NSRect rect; + NSPoint pt; + + pt.x = caret_x; + pt.y = caret_y; + + pt = [self convertPoint: pt toView: nil]; + pt = [[self window] tkConvertPointToScreen: pt]; + pt.y -= caret_height; + + rect.origin = pt; + rect.size.width = caret_height; + rect.size.height = caret_height; + return rect; } - (NSInteger)conversationIdentifier { - return (NSInteger)self; + return (NSInteger) self; } - (void)doCommandBySelector: (SEL)aSelector { - if (NS_KEYLOG) - TKLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector)); - processingCompose = NO; - if (aSelector == @selector (deleteBackward:)) - { - /* happens when user backspaces over an ongoing composition: - throw a 'delete' into the event queue */ - XEvent xEvent; - setupXEvent(&xEvent, [self window], 0); - xEvent.xany.type = KeyPress; - xEvent.xkey.nbytes = 1; - xEvent.xkey.keycode = (0x33 << 16) | 0x7F; - xEvent.xkey.trans_chars[0] = 0x7F; - xEvent.xkey.trans_chars[1] = 0x0; - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + if (NS_KEYLOG) { + TKLog(@"doCommandBySelector: %@", NSStringFromSelector(aSelector)); + } + processingCompose = NO; + if (aSelector == @selector (deleteBackward:)) { + /* + * Happens when user backspaces over an ongoing composition: + * throw a 'delete' into the event queue. + */ + + XEvent xEvent; + + setupXEvent(&xEvent, [self window], 0); + xEvent.xany.type = KeyPress; + xEvent.xkey.nbytes = 1; + xEvent.xkey.keycode = (0x33 << 16) | 0x7F; + xEvent.xkey.trans_chars[0] = 0x7F; + xEvent.xkey.trans_chars[1] = 0x0; + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } } - (NSArray *)validAttributesForMarkedText { - static NSArray *arr = nil; - if (arr == nil) arr = [NSArray new]; - /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */ - return arr; + static NSArray *arr = nil; + + if (arr == nil) { + arr = [NSArray new]; + } + /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */ + return arr; } - (NSRange)selectedRange { - if (NS_KEYLOG) - TKLog (@"selectedRange request"); - return NSMakeRange (NSNotFound, 0); + if (NS_KEYLOG) { + TKLog(@"selectedRange request"); + } + return NSMakeRange(NSNotFound, 0); } - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint { - if (NS_KEYLOG) - TKLog (@"characterIndexForPoint request"); - return 0; + if (NS_KEYLOG) { + TKLog(@"characterIndexForPoint request"); + } + return 0; } - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange { - static NSAttributedString *str = nil; - if (str == nil) str = [NSAttributedString new]; - if (NS_KEYLOG) - TKLog (@"attributedSubstringFromRange request"); - return str; + static NSAttributedString *str = nil; + if (str == nil) { + str = [NSAttributedString new]; + } + if (NS_KEYLOG) { + TKLog(@"attributedSubstringFromRange request"); + } + return str; } /* End impl. */ + +@synthesize needsRedisplay = _needsRedisplay; @end @implementation TKContentView(TKKeyEvent) /* delete display of composing characters [not in ] */ - (void)deleteWorkingText { - if (privateWorkingText == nil) - return; - if (NS_KEYLOG) - TKLog(@"deleteWorkingText len = %lu\n", - (unsigned long)[privateWorkingText length]); - [privateWorkingText release]; - privateWorkingText = nil; - processingCompose = NO; - - //PENDING: delete working text + if (privateWorkingText == nil) { + return; + } + if (NS_KEYLOG) { + TKLog(@"deleteWorkingText len = %lu\n", + (unsigned long)[privateWorkingText length]); + } + [privateWorkingText release]; + privateWorkingText = nil; + processingCompose = NO; + + //PENDING: delete working text } @end - - /* - * Set up basic fields in xevent for keyboard input. + * Set up basic fields in xevent for keyboard input. */ static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state) { TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; + if (!winPtr) { return; } memset(xEvent, 0, sizeof(XEvent)); @@ -498,15 +536,17 @@ int pointer_mode, int keyboard_mode, Time time) { keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window); - if (keyboardGrabWinPtr && grabWinPtr) { + TkWindow *captureWinPtr = (TkWindow *) TkMacOSXGetCapture(); + + if (keyboardGrabWinPtr && captureWinPtr) { NSWindow *w = TkMacOSXDrawableWindow(grab_window); MacDrawable *macWin = (MacDrawable *) grab_window; - if (w && macWin->toplevel->winPtr == (TkWindow*) grabWinPtr) { + if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) { if (modalSession) { Tcl_Panic("XGrabKeyboard: already grabbed"); } keyboardGrabNSWindow = w; [w retain]; @@ -549,30 +589,10 @@ } /* *---------------------------------------------------------------------- * - * TkMacOSXGetCapture -- - * - * Results: - * Returns the current grab window - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tk_Window -TkMacOSXGetCapture(void) -{ - return grabWinPtr; -} - -/* - *---------------------------------------------------------------------- - * * TkMacOSXGetModalSession -- * * Results: * Returns the current modal session * @@ -585,38 +605,10 @@ MODULE_SCOPE NSModalSession TkMacOSXGetModalSession(void) { return modalSession; } - -/* - *---------------------------------------------------------------------- - * - * TkpSetCapture -- - * - * This function captures the mouse so that all future events will be - * reported to this window, even if the mouse is outside the window. If - * the specified window is NULL, then the mouse is released. - * - * Results: - * None. - * - * Side effects: - * Sets the capture flag and captures the mouse. - * - *---------------------------------------------------------------------- - */ - -void -TkpSetCapture( - TkWindow *winPtr) /* Capture window, or NULL. */ -{ - while (winPtr && !Tk_IsTopLevel(winPtr)) { - winPtr = winPtr->parentPtr; - } - grabWinPtr = (Tk_Window) winPtr; -} /* *---------------------------------------------------------------------- * * Tk_SetCaretPos -- @@ -669,11 +661,14 @@ if (tkwin == NULL) { return; } } - /* But adjust for fact that NS uses flipped view. */ + /* + * But adjust for fact that NS uses flipped view. + */ + y = Tk_Height(tkwin) - y; caret_x = x; caret_y = y; caret_height = height; @@ -680,83 +675,88 @@ } static unsigned convert_ns_to_X_keysym[] = { - NSHomeFunctionKey, 0x50, - NSLeftArrowFunctionKey, 0x51, - NSUpArrowFunctionKey, 0x52, - NSRightArrowFunctionKey, 0x53, - NSDownArrowFunctionKey, 0x54, - NSPageUpFunctionKey, 0x55, - NSPageDownFunctionKey, 0x56, - NSEndFunctionKey, 0x57, - NSBeginFunctionKey, 0x58, - NSSelectFunctionKey, 0x60, - NSPrintFunctionKey, 0x61, - NSExecuteFunctionKey, 0x62, - NSInsertFunctionKey, 0x63, - NSUndoFunctionKey, 0x65, - NSRedoFunctionKey, 0x66, - NSMenuFunctionKey, 0x67, - NSFindFunctionKey, 0x68, - NSHelpFunctionKey, 0x6A, - NSBreakFunctionKey, 0x6B, - - NSF1FunctionKey, 0xBE, - NSF2FunctionKey, 0xBF, - NSF3FunctionKey, 0xC0, - NSF4FunctionKey, 0xC1, - NSF5FunctionKey, 0xC2, - NSF6FunctionKey, 0xC3, - NSF7FunctionKey, 0xC4, - NSF8FunctionKey, 0xC5, - NSF9FunctionKey, 0xC6, - NSF10FunctionKey, 0xC7, - NSF11FunctionKey, 0xC8, - NSF12FunctionKey, 0xC9, - NSF13FunctionKey, 0xCA, - NSF14FunctionKey, 0xCB, - NSF15FunctionKey, 0xCC, - NSF16FunctionKey, 0xCD, - NSF17FunctionKey, 0xCE, - NSF18FunctionKey, 0xCF, - NSF19FunctionKey, 0xD0, - NSF20FunctionKey, 0xD1, - NSF21FunctionKey, 0xD2, - NSF22FunctionKey, 0xD3, - NSF23FunctionKey, 0xD4, - NSF24FunctionKey, 0xD5, - - NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ - NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ - NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ - - NSTabCharacter, 0x09, - 0x19, 0x09, /* left tab->regular since pass shift */ - NSCarriageReturnCharacter, 0x0D, - NSNewlineCharacter, 0x0D, - NSEnterCharacter, 0x8D, - - 0x1B, 0x1B /* escape */ + NSHomeFunctionKey, 0x50, + NSLeftArrowFunctionKey, 0x51, + NSUpArrowFunctionKey, 0x52, + NSRightArrowFunctionKey, 0x53, + NSDownArrowFunctionKey, 0x54, + NSPageUpFunctionKey, 0x55, + NSPageDownFunctionKey, 0x56, + NSEndFunctionKey, 0x57, + NSBeginFunctionKey, 0x58, + NSSelectFunctionKey, 0x60, + NSPrintFunctionKey, 0x61, + NSExecuteFunctionKey, 0x62, + NSInsertFunctionKey, 0x63, + NSUndoFunctionKey, 0x65, + NSRedoFunctionKey, 0x66, + NSMenuFunctionKey, 0x67, + NSFindFunctionKey, 0x68, + NSHelpFunctionKey, 0x6A, + NSBreakFunctionKey, 0x6B, + + NSF1FunctionKey, 0xBE, + NSF2FunctionKey, 0xBF, + NSF3FunctionKey, 0xC0, + NSF4FunctionKey, 0xC1, + NSF5FunctionKey, 0xC2, + NSF6FunctionKey, 0xC3, + NSF7FunctionKey, 0xC4, + NSF8FunctionKey, 0xC5, + NSF9FunctionKey, 0xC6, + NSF10FunctionKey, 0xC7, + NSF11FunctionKey, 0xC8, + NSF12FunctionKey, 0xC9, + NSF13FunctionKey, 0xCA, + NSF14FunctionKey, 0xCB, + NSF15FunctionKey, 0xCC, + NSF16FunctionKey, 0xCD, + NSF17FunctionKey, 0xCE, + NSF18FunctionKey, 0xCF, + NSF19FunctionKey, 0xD0, + NSF20FunctionKey, 0xD1, + NSF21FunctionKey, 0xD2, + NSF22FunctionKey, 0xD3, + NSF23FunctionKey, 0xD4, + NSF24FunctionKey, 0xD5, + + NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ + NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ + NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ + + NSTabCharacter, 0x09, + 0x19, 0x09, /* left tab->regular since pass shift */ + NSCarriageReturnCharacter, 0x0D, + NSNewlineCharacter, 0x0D, + NSEnterCharacter, 0x8D, + + 0x1B, 0x1B /* escape */ }; -static unsigned isFunctionKey(unsigned code) -{ - const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) - / sizeof (convert_ns_to_X_keysym[0])); - unsigned keysym; - for (keysym = 0; keysym < last_keysym; keysym += 2) - if (code == convert_ns_to_X_keysym[keysym]) - return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; - return 0; - } +static unsigned +isFunctionKey( + unsigned code) +{ + const unsigned last_keysym = (sizeof(convert_ns_to_X_keysym) + / sizeof(convert_ns_to_X_keysym[0])); + unsigned keysym; + + for (keysym = 0; keysym < last_keysym; keysym += 2) { + if (code == convert_ns_to_X_keysym[keysym]) { + return 0xFF00 | convert_ns_to_X_keysym[keysym + 1]; + } + } + return 0; +} /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXKeyboard.c ================================================================== --- macosx/tkMacOSXKeyboard.c +++ macosx/tkMacOSXKeyboard.c @@ -178,17 +178,17 @@ Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS); for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) { hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode), &dummy); - Tcl_SetHashValue(hPtr, kPtr->keysym); + Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym)); } Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS); for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) { hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode), &dummy); - Tcl_SetHashValue(hPtr, kPtr->keysym); + Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym)); } initialized = 1; } /* Index: macosx/tkMacOSXMenu.c ================================================================== --- macosx/tkMacOSXMenu.c +++ macosx/tkMacOSXMenu.c @@ -191,26 +191,26 @@ } - (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index { if (_tkMenu && index >= 0) { - if ((NSUInteger)index <= _tkOffset) { + if ((NSUInteger) index <= _tkOffset) { _tkOffset++; } else { - NSAssert((NSUInteger)index >= _tkItemCount + _tkOffset, + NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset, @"Cannot insert in the middle of Tk menu"); } } [super insertItem:newItem atIndex:index]; } - (void) removeItemAtIndex: (NSInteger) index { if (_tkMenu && index >= 0) { - if ((NSUInteger)index < _tkOffset) { + if ((NSUInteger) index < _tkOffset) { _tkOffset--; - } else if ((NSUInteger)index < _tkItemCount + _tkOffset) { + } else if ((NSUInteger) index < _tkItemCount + _tkOffset) { _tkItemCount--; } } [super removeItemAtIndex:index]; } @@ -219,11 +219,11 @@ { NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:@selector(tkMenuItemInvoke:) keyEquivalent:@""]; [menuItem setTarget:self]; - [menuItem setTag:(NSInteger)mePtr]; + [menuItem setTag:(NSInteger) mePtr]; return menuItem; } @end @implementation TKMenu(TKMenuActions) @@ -250,19 +250,20 @@ * specific menu item. We use this to ignore key equivalents for Tk * menus (as Tk handles them directly via bindings). */ if ([sender isKindOfClass:[NSMenuItem class]]) { - NSMenuItem *menuItem = (NSMenuItem *)sender; - TkMenu *menuPtr = (TkMenu *)_tkMenu; - TkMenuEntry *mePtr = (TkMenuEntry *)[menuItem tag]; + NSMenuItem *menuItem = (NSMenuItem *) sender; + TkMenu *menuPtr = (TkMenu *) _tkMenu; + TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag]; if (menuPtr && mePtr) { Tcl_Interp *interp = menuPtr->interp; - /*Add time for errors to fire if necessary. This is sub-optimal - *but avoids issues with Tcl/Cocoa event loop integration. + /* + * Add time for errors to fire if necessary. This is sub-optimal + * but avoids issues with Tcl/Cocoa event loop integration. */ //Tcl_Sleep(100); Tcl_Preserve(interp); Tcl_Preserve(menuPtr); @@ -303,12 +304,12 @@ */ return NO; } else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) && [event keyCode] == 48) { - - /* Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used + /* + * Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used * to select window tabs. But for some even more mysterious reason the * Control-Shift-Tab event has character 0x19 = NSBackTabCharacter * rather than 0x09 = NSTabCharacter. At the same time, the * keyEquivalent must be \0x09 in order for it to be displayed * correctly in the menu. This makes it impossible for the standard @@ -315,11 +316,10 @@ * "Select Previous Tab" to work correctly, unless we intervene. */ key = @"\t"; } else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) { - /* * If the command modifier is set, use the full character string so * things like the dvorak / qwerty layout will work. */ @@ -648,11 +648,11 @@ if (gc->foreground != defaultFg || gc->background != defaultBg) { NSColor *color = TkMacOSXGetNSColor(gc, gc->foreground!=defaultFg? gc->foreground:gc->background); attributes = [[attributes mutableCopy] autorelease]; - [(NSMutableDictionary *)attributes setObject:color + [(NSMutableDictionary *) attributes setObject:color forKey:NSForegroundColorAttributeName]; } if (attributes) { attributedTitle = [[[NSAttributedString alloc] initWithString:title attributes:attributes] autorelease]; @@ -688,25 +688,35 @@ submenu = nil; } else { [submenu setTitle:title]; if ([menuItem isEnabled]) { - /* This menuItem might have been previously disabled (XXX: - track this), which would have disabled entries; we must - re-enable the entries here. */ - int i = 0; - NSArray *itemArray = [submenu itemArray]; - for (NSMenuItem *item in itemArray) { - TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; - /* Work around an apparent bug where itemArray can have - more items than the menu's entries[] array. */ - if (i >= menuRefPtr->menuPtr->numEntries) break; - [item setEnabled: !(submePtr->state == ENTRY_DISABLED)]; - i++; - } - } - + + /* + * This menuItem might have been previously disabled (XXX: + * track this), which would have disabled entries; we must + * re-enable the entries here. + */ + + int i = 0; + NSArray *itemArray = [submenu itemArray]; + + for (NSMenuItem *item in itemArray) { + TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; + + /* + * Work around an apparent bug where itemArray can have + * more items than the menu's entries[] array. + */ + + if (i >= (int) menuRefPtr->menuPtr->numEntries) { + break; + } + [item setEnabled: !(submePtr->state == ENTRY_DISABLED)]; + i++; + } + } } } } [menuItem setSubmenu:submenu]; @@ -753,14 +763,17 @@ /* *---------------------------------------------------------------------- * * TkpPostMenu -- * - * Posts a menu on the screen + * Posts a menu on the screen. If entry is < 0 then the menu is drawn so + * its top left corner is located at the point with screen coordinates + * (x,y). Otherwise the top left corner of the specified entry is located + * at that point. * * Results: - * None. + * Returns a standard Tcl result. * * Side effects: * The menu is posted and handled. * *---------------------------------------------------------------------- @@ -768,57 +781,162 @@ int TkpPostMenu( Tcl_Interp *interp, /* The interpreter this menu lives in */ TkMenu *menuPtr, /* The menu we are posting */ - int x, /* The global x-coordinate of the top, left- - * hand corner of where the menu is supposed - * to be posted. */ - int y) /* The global y-coordinate */ -{ - - - /* Get the object that holds this Tk Window.*/ - Tk_Window root; - root = Tk_MainWindow(interp); + int x, int y, /* The screen coordinates where the top left + * corner of the menu, or of the specified + * entry, will be located. */ + int index) +{ + int result; + Tk_Window root = Tk_MainWindow(interp); + if (root == NULL) { return TCL_ERROR; } - Drawable d = Tk_WindowId(root); NSView *rootview = TkMacOSXGetRootControl(d); NSWindow *win = [rootview window]; - int result; + NSView *view = [win contentView]; + NSMenu *menu = (NSMenu *) menuPtr->platformData; + NSInteger itemIndex = index; + NSInteger numItems = [menu numberOfItems]; + NSMenuItem *item = nil; + NSPoint location = NSMakePoint(x, tkMacOSXZeroScreenHeight - y); inPostMenu = 1; - result = TkPreprocessMenu(menuPtr); if (result != TCL_OK) { inPostMenu = 0; return result; } - - int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE); - NSView *view = [win contentView]; - NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1); - - frame.origin = [view convertPoint: - [win tkConvertPointFromScreen:frame.origin] fromView:nil]; - - NSMenu *menu = (NSMenu *) menuPtr->platformData; - NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc] - initTextCell:@"" pullsDown:NO]; - - [popUpButtonCell setAltersStateOfSelectedItem:NO]; - [popUpButtonCell setMenu:menu]; - [popUpButtonCell selectItem:nil]; - [popUpButtonCell performClickWithFrame:frame inView:view]; - [popUpButtonCell release]; - Tcl_SetServiceMode(oldMode); + if (itemIndex >= numItems) { + itemIndex = numItems - 1; + } + if (itemIndex >= 0) { + item = [menu itemAtIndex:itemIndex]; + } + + /* + * The post commands could have deleted the menu, which means we are dead + * and should go away. + */ + + if (menuPtr->tkwin == NULL) { + return TCL_OK; + } + + [menu popUpMenuPositioningItem:item + atLocation:[win tkConvertPointFromScreen:location] + inView:view]; inPostMenu = 0; return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * + * TkpPostTearoffMenu -- + * + * Tearoff menus are not supported on the Mac. This placeholder function, + * which is simply a copy of the unix function, posts a completely useless + * window with a black background on the screen. If entry is < 0 then the + * window is positioned so that its top left corner is located at the + * point with screen coordinates (x, y). Otherwise the window position is + * offset so that top left corner of the specified entry would be located + * at that point, if there actually were a menu. + * + * Mac menus steal all mouse or keyboard input from the application until + * the menu is dismissed, with or without a selection, by a mouse or key + * event. Posting a Mac menu in a regression test will cause the test to + * halt waiting for user input. This is why the TkpPostMenu function is + * not being used as the placeholder. + * + * Results: + * None. + * + * Side effects: + * A useless window is posted. + * + *---------------------------------------------------------------------- + */ + +int +TkpPostTearoffMenu( + Tcl_Interp *interp, /* The interpreter this menu lives in */ + TkMenu *menuPtr, /* The menu we are posting */ + int x, int y, int index) /* The screen coordinates where the top left + * corner of the menu, or of the specified + * entry, will be located. */ +{ + int vRootX, vRootY, vRootWidth, vRootHeight; + int result; + + if (index >= (int) menuPtr->numEntries) { + index = menuPtr->numEntries - 1; + } + if (index >= 0) { + y -= menuPtr->entries[index]->y; + } + + TkActivateMenuEntry(menuPtr, -1); + TkRecomputeMenu(menuPtr); + result = TkPostCommand(menuPtr); + if (result != TCL_OK) { + return result; + } + + /* + * The post commands could have deleted the menu, which means we are dead + * and should go away. + */ + + if (menuPtr->tkwin == NULL) { + return TCL_OK; + } + + /* + * Adjust the position of the menu if necessary to keep it visible on the + * screen. There are two special tricks to make this work right: + * + * 1. If a virtual root window manager is being used then the coordinates + * are in the virtual root window of menuPtr's parent; since the menu + * uses override-redirect mode it will be in the *real* root window for + * the screen, so we have to map the coordinates from the virtual root + * (if any) to the real root. Can't get the virtual root from the menu + * itself (it will never be seen by the wm) so use its parent instead + * (it would be better to have an an option that names a window to use + * for this...). + * 2. The menu may not have been mapped yet, so its current size might be + * the default 1x1. To compute how much space it needs, use its + * requested size, not its actual size. + */ + + Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY, + &vRootWidth, &vRootHeight); + vRootWidth -= Tk_ReqWidth(menuPtr->tkwin); + if (x > vRootX + vRootWidth) { + x = vRootX + vRootWidth; + } + if (x < vRootX) { + x = vRootX; + } + vRootHeight -= Tk_ReqHeight(menuPtr->tkwin); + if (y > vRootY + vRootHeight) { + y = vRootY + vRootHeight; + } + if (y < vRootY) { + y = vRootY; + } + Tk_MoveToplevelWindow(menuPtr->tkwin, x, y); + if (!Tk_IsMapped(menuPtr->tkwin)) { + Tk_MapWindow(menuPtr->tkwin); + } + TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL); + return TCL_OK; +} /* *---------------------------------------------------------------------- * * TkpSetWindowMenuBar -- @@ -850,16 +968,16 @@ /* *---------------------------------------------------------------------- * * TkpSetMainMenubar -- * - * Puts the menu associated with a window into the menubar. Should only - * be called when the window is in front. + * Puts the menu associated with a window into the menubar. Should only be + * called when the window is in front. * * This is a no-op on all other platforms. On OS X it is a no-op when - * passed a NULL menuName or a nonexistent menuName, with an exception - * for the first call in a new interpreter. In that special case, passing a + * passed a NULL menuName or a nonexistent menuName, with an exception for + * the first call in a new interpreter. In that special case, passing a * NULL menuName installs the default menu. * * Results: * None. * @@ -875,19 +993,36 @@ Tk_Window tkwin, /* The frame we are setting up */ const char *menuName) /* The name of the menu to put in front. */ { static Tcl_Interp *currentInterp = NULL; TKMenu *menu = nil; + TkWindow *winPtr = (TkWindow *) tkwin; + + /* + * We will be called when an embedded window receives an ActivationNotify + * event, but we should not change the menubar in that case. + */ + + if (Tk_IsEmbedded(winPtr)) { + return; + } if (menuName) { - TkWindow *winPtr = (TkWindow *) tkwin; + Tk_Window menubar = NULL; + + if (winPtr->wmInfoPtr && + winPtr->wmInfoPtr->menuPtr && + winPtr->wmInfoPtr->menuPtr->masterMenuPtr) { + menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin; + } + + /* + * Attempt to find the NSMenu directly. If that fails, ask Tk to find + * it. + */ - if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr && - winPtr->wmInfoPtr->menuPtr->masterMenuPtr && - winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin && - !strcmp(menuName, Tk_PathName( - winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) { + if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) { menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData; } else { TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp, menuName); @@ -895,10 +1030,16 @@ menuRefPtr->menuPtr->platformData) { menu = (TKMenu *) menuRefPtr->menuPtr->platformData; } } } + + /* + * If we couldn't find a menu, do nothing unless the window belongs to a + * different application. In that case, install the default menubar. + */ + if (menu || interp != currentInterp) { [NSApp tkSetMainMenu:menu]; } currentInterp = interp; } @@ -907,12 +1048,12 @@ *---------------------------------------------------------------------- * * CheckForSpecialMenu -- * * Given a menu, check to see whether or not it is a cascade in a menubar - * with one of the special names .apple, .help or .window If it is, the - * entry that points to this menu will be marked. + * with one of the special names ".apple", ".help" or ".window". If it is, + * the entry that points to this menu will be marked. * * Results: * None. * * Side effects: @@ -1085,56 +1226,65 @@ void TkpComputeStandardMenuGeometry( TkMenu *menuPtr) /* Structure describing menu. */ { + NSSize menuSize; Tk_Font tkfont, menuFont; Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; int modifierCharWidth, menuModifierCharWidth; int x, y, modifierWidth, labelWidth, indicatorSpace; int windowWidth, windowHeight, accelWidth; - int i, j, lastColumnBreak, maxWidth; + int i, maxWidth; int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth; - TkMenuEntry *mePtr, *columnEntryPtr; + TkMenuEntry *mePtr; int haveAccel = 0; - if (menuPtr->tkwin == NULL) { + /* + * Do nothing if this menu is a clone. + */ + + if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) { return; } + menuSize = [(NSMenu *) menuPtr->platformData size]; Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, &activeBorderWidth); x = y = borderWidth; - windowHeight = maxWidth = lastColumnBreak = 0; + windowHeight = maxWidth = 0; maxIndicatorSpace = 0; /* * On the Mac especially, getting font metrics can be quite slow, so we * want to do it intelligently. We are going to precalculate them and pass * them down to all of the measuring and drawing routines. We will measure * the font metrics of the menu once. If an entry does not have its own - * font set, then we give the geometry/drawing routines the menu's font - * and metrics. If an entry has its own font, we will measure that font - * and give all of the geometry/drawing the entry's font and metrics. + * font set, then we give the geometry/drawing routines the menu's font and + * metrics. If an entry has its own font, we will measure that font and + * give all of the geometry/drawing the entry's font and metrics. */ menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); Tk_GetFontMetrics(menuFont, &menuMetrics); menuModifierCharWidth = ModifierCharWidth(menuFont); - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int) menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) { haveAccel = 1; break; } } - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int) menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; + if (mePtr->type == TEAROFF_ENTRY) { + continue; + } if (mePtr->fontPtr == NULL) { tkfont = menuFont; fmPtr = &menuMetrics; modifierCharWidth = menuModifierCharWidth; } else { @@ -1141,30 +1291,12 @@ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); Tk_GetFontMetrics(tkfont, &entryMetrics); fmPtr = &entryMetrics; modifierCharWidth = ModifierCharWidth(tkfont); } - - if ((i > 0) && mePtr->columnBreak) { - if (maxIndicatorSpace != 0) { - maxIndicatorSpace += 2; - } - for (j = lastColumnBreak; j < i; j++) { - columnEntryPtr = menuPtr->entries[j]; - columnEntryPtr->indicatorSpace = maxIndicatorSpace; - columnEntryPtr->width = maxIndicatorSpace + maxWidth - + 2 * activeBorderWidth; - columnEntryPtr->x = x; - columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN; - } - x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth; - maxWidth = maxIndicatorSpace = 0; - lastColumnBreak = i; - y = borderWidth; - } accelWidth = modifierWidth = indicatorSpace = 0; - if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) { + if (mePtr->type == SEPARATOR_ENTRY) { mePtr->height = menuSeparatorHeight; } else { /* * For each entry, compute the height required by that particular * entry, plus three widths: the width of the label, the width to @@ -1178,16 +1310,18 @@ int haveImage = 0, width = 0, height = 0; if (mePtr->image) { Tk_SizeOfImage(mePtr->image, &width, &height); haveImage = 1; + height += 2; /* tweak */ } else if (mePtr->bitmapPtr) { Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height); haveImage = 1; + height += 2; /* tweak */ } if (!haveImage || (mePtr->compound != COMPOUND_NONE)) { NSAttributedString *attrTitle = [menuItem attributedTitle]; NSSize size; @@ -1195,15 +1329,12 @@ size = [attrTitle size]; } else { size = [[menuItem title] sizeWithAttributes: TkMacOSXNSFontAttributesForFont(tkfont)]; } - size.width += menuTextLeadingEdgeMargin + - menuTextTrailingEdgeMargin; - if (size.height < fmPtr->linespace) { - size.height = fmPtr->linespace; - } + size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin; + size.height -= 1; /* tweak */ if (haveImage && (mePtr->compound != COMPOUND_NONE)) { int margin = width + menuIconTrailingEdgeMargin; if (margin > menuTextLeadingEdgeMargin) { margin = menuTextLeadingEdgeMargin; @@ -1215,13 +1346,15 @@ } else { width = size.width; height = size.height; } } + else { + /* image only. */ + } labelWidth = width + menuItemExtraWidth; mePtr->height = height + menuItemExtraHeight; - if (mePtr->type == CASCADE_ENTRY) { modifierWidth = modifierCharWidth; } else if (mePtr->accelLength == 0) { if (haveAccel && !mePtr->hideMargin) { modifierWidth = modifierCharWidth; @@ -1248,34 +1381,22 @@ } entryWidth = labelWidth + modifierWidth + accelWidth; if (entryWidth > maxWidth) { maxWidth = entryWidth; } + menuPtr->entries[i]->width = entryWidth; mePtr->height += 2 * activeBorderWidth; } + mePtr->x = x; mePtr->y = y; y += menuPtr->entries[i]->height + borderWidth; - if (y > windowHeight) { - windowHeight = y; - } - } - - for (j = lastColumnBreak; j < menuPtr->numEntries; j++) { - columnEntryPtr = menuPtr->entries[j]; - columnEntryPtr->indicatorSpace = maxIndicatorSpace; - columnEntryPtr->width = maxIndicatorSpace + maxWidth - + 2 * activeBorderWidth; - columnEntryPtr->x = x; - columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN; - } - windowWidth = x + maxIndicatorSpace + maxWidth - + 2 * activeBorderWidth + borderWidth; - windowHeight += borderWidth; - + } + windowWidth = menuSize.width; if (windowWidth <= 0) { windowWidth = 1; } + windowHeight = menuSize.height; if (windowHeight <= 0) { windowHeight = 1; } menuPtr->totalWidth = windowWidth; menuPtr->totalHeight = windowHeight; @@ -1305,11 +1426,11 @@ TkMenu *menuPtr = [menu tkMenu]; if (menuPtr) { int index = [menu tkIndexOfItem:menuItem]; - if (index < 0 || index >= menuPtr->numEntries || + if (index < 0 || index >= (int) menuPtr->numEntries || (menuPtr->entries[index])->state == ENTRY_DISABLED) { TkActivateMenuEntry(menuPtr, -1); } else { TkActivateMenuEntry(menuPtr, index); MenuSelectEvent(menuPtr); @@ -1384,11 +1505,11 @@ TkMenu *menuPtr) /* The menu to reset. */ { int i; TkActivateMenuEntry(menuPtr, -1); - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int) menuPtr->numEntries; i++) { TkMenuEntry *mePtr = menuPtr->entries[i]; if (mePtr->type == CASCADE_ENTRY && (mePtr->childMenuRefPtr != NULL) && (mePtr->childMenuRefPtr->menuPtr != NULL)) { @@ -1673,11 +1794,11 @@ *---------------------------------------------------------------------- * * TkMacOSXUseID -- * * Take the ID out of the available list for new menus. Used by the - * default menu bar's menus so that they do not get created at the tk + * default menu bar's menus so that they do not get created at the Tk * level. See TkMacOSXGetNewMenuID for more information. * * Results: * Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the id * was in use. @@ -1698,12 +1819,11 @@ /* *---------------------------------------------------------------------- * * TkMacOSXDispatchMenuEvent -- * - * Given a menu id and an item, dispatches the command associated with - * it. + * Given a menu id and an item, dispatches the command associated with it. * * Results: * None. * * Side effects: @@ -1749,13 +1869,14 @@ /* *---------------------------------------------------------------------- * * TkMacOSXSetHelpMenuItemCount -- * - * Has to be called after the first call to InsertMenu. Sets up the - * global variable for the number of items in the unmodified help menu. - * NB. Nobody uses this any more, since you can get the number of system + * Has to be called after the first call to InsertMenu. Sets up the global + * variable for the number of items in the unmodified help menu. + * + * NB: Nobody uses this any more, since you can get the number of system * help items from HMGetHelpMenu trivially. But it is in the stubs * table... * * Results: * None. Index: macosx/tkMacOSXMenubutton.c ================================================================== --- macosx/tkMacOSXMenubutton.c +++ macosx/tkMacOSXMenubutton.c @@ -1,10 +1,10 @@ /* * tkMacOSXMenubutton.c -- * - * This file implements the Macintosh specific portion of the - * menubutton widget. + * This file implements the Macintosh specific portion of the menubutton + * widget. * * Copyright (c) 1996 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. * Copyright (c) 2006-2007 Daniel A. Steffen * Copyright 2007 Revar Desmera. @@ -30,11 +30,10 @@ int relief; GC gc; int hasImageOrBitmap; } DrawParams; - /* * Declaration of Mac specific button structure. */ typedef struct MacMenuButton { @@ -45,22 +44,31 @@ HIThemeButtonDrawInfo lastdrawinfo; DrawParams drawParams; } MacMenuButton; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for static functions defined later in this file: */ -static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr); -static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev); -static void MenuButtonContentDrawCB ( ThemeButtonKind kind, const HIThemeButtonDrawInfo * info, MacMenuButton *ptr, SInt16 depth, Boolean isColorDev); -static void MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr); -static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo* drawinfo); -static int TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr, DrawParams * dpPtr); -static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr, - GC gc, Pixmap pixmap); -static void DrawMenuButtonImageAndText(TkMenuButton* butPtr); +static void MenuButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void MenuButtonBackgroundDrawCB(MacMenuButton *ptr, + SInt16 depth, Boolean isColorDev); +static void MenuButtonContentDrawCB(ThemeButtonKind kind, + const HIThemeButtonDrawInfo *info, + MacMenuButton *ptr, SInt16 depth, + Boolean isColorDev); +static void MenuButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void TkMacOSXComputeMenuButtonParams(TkMenuButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo); +static void TkMacOSXComputeMenuButtonDrawParams( + TkMenuButton *butPtr, DrawParams *dpPtr); +static void TkMacOSXDrawMenuButton(MacMenuButton *butPtr, GC gc, + Pixmap pixmap); +static void DrawMenuButtonImageAndText(TkMenuButton *butPtr); /* * The structure below defines menubutton class behavior by means of * procedures that can be invoked from generic window code. */ @@ -68,15 +76,49 @@ Tk_ClassProcs tkpMenubuttonClass = { sizeof(Tk_ClassProcs), /* size */ TkMenuButtonWorldChanged, /* worldChangedProc */ }; +/* + * We use Apple's Pop-Up Button widget to represent the Tk Menubutton. + * However, we do not use the NSPopUpButton class for this control. Instead we + * render the Pop-Up Button using the HITheme library. This imposes some + * constraints on what can be done. The HITheme renderer allows only specific + * dimensions for the button. + * + * The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds + * rectangle. However the button is always drawn as a rounded box which is 22 + * pixels high. If the bounds rectangle is less than 22 pixels high, the + * button is drawn at the top of the rectangle and the bottom of the button is + * clipped away. So we set a minimum height of 22 pixels for a Menubutton. If + * the bounds rectangle is more than 22 pixels high, then the button is drawn + * centered vertically in the bounds rectangle. + * + * The content rectangle of the button is inset by 14 pixels on the left and 28 + * pixels on the right. The rightmost part of the button contains the blue + * double-arrow symbol which is 28 pixels wide. + * + * To maintain compatibility with code that runs on multiple operating systems, + * the width and height of the content rectangle includes the borderWidth, the + * highlightWidth and the padX and padY dimensions of the Menubutton. However, + * to be consistent with the standard Apple appearance, the content is always + * be drawn at the left side of the content rectangle. All of the excess space + * appears on the right side of the content, and the anchor property is + * ignored. The easiest way to comply with Apple's Human Interface Guidelines + * would be to set bd = highlightthickness = padx = 0 and to specify an + * explicit width for the button. Apple also recommends using the same width + * for all Pop-Up Buttons in a given window. + */ + +#define LEFT_INSET 8 +#define RIGHT_INSET 28 +#define MIN_HEIGHT 22 /* *---------------------------------------------------------------------- * - * TkpCreateMenuButton -- + * TkpCreateMenuButton -- * * Allocate a new TkMenuButton structure. * * Results: * Returns a newly allocated TkMenuButton structure. @@ -91,17 +133,15 @@ TkpCreateMenuButton( Tk_Window tkwin) { MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton)); - Tk_CreateEventHandler(tkwin, ActivateMask, - MenuButtonEventProc, (ClientData) mbPtr); + Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr); mbPtr->flags = FIRST_DRAW; mbPtr->btnkind = kThemePopupButton; bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo)); bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo)); - return (TkMenuButton *) mbPtr; } /* *---------------------------------------------------------------------- @@ -112,25 +152,24 @@ * * Results: * None. * * Side effects: - * Commands are output to X to display the menubutton in its - * current mode. + * Commands are output to X to display the menubutton in its current mode. * *---------------------------------------------------------------------- */ void TkpDisplayMenuButton( ClientData clientData) /* Information about widget. */ { - MacMenuButton *mbPtr = (MacMenuButton *)clientData; - TkMenuButton *butPtr = (TkMenuButton *) clientData; - Tk_Window tkwin = butPtr->tkwin; + MacMenuButton *mbPtr = clientData; + TkMenuButton *butPtr = clientData; + Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; - DrawParams* dpPtr = &mbPtr->drawParams; + DrawParams *dpPtr = &mbPtr->drawParams; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } @@ -138,41 +177,47 @@ pixmap = (Pixmap) Tk_WindowId(tkwin); TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr); /* - * set up clipping region. Make sure the we are using the port - * for this button, or we will set the wrong window's clip. + * Set up clipping region. Make sure the we are using the port for this + * button, or we will set the wrong window's clip. */ TkMacOSXSetUpClippingRgn(pixmap); - /* Draw the native portion of the buttons. */ + /* + * Draw the native portion of the buttons. + */ + TkMacOSXDrawMenuButton(mbPtr, dpPtr->gc, pixmap); - /* Draw highlight border, if needed. */ + /* + * Draw highlight border, if needed. + */ + if (butPtr->highlightWidth < 3) { - if ((butPtr->flags & GOT_FOCUS)) { - Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), - butPtr->highlightWidth, TK_RELIEF_SOLID); - } + if (butPtr->flags & GOT_FOCUS) { + GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); + } } } /* *---------------------------------------------------------------------- * * TkpDestroyMenuButton -- * - * Free data structures associated with the menubutton control. + * Free data structures associated with the menubutton control. This is a + * no-op on the Mac. * * Results: * None. * * Side effects: - * Restores the default control state. + * None. * *---------------------------------------------------------------------- */ void @@ -202,89 +247,81 @@ void TkpComputeMenuButtonGeometry(butPtr) register TkMenuButton *butPtr; /* Widget record for menu button. */ { int width, height, avgWidth, haveImage = 0, haveText = 0; - MacMenuButton *mbPtr = (MacMenuButton*)butPtr; int txtWidth, txtHeight; Tk_FontMetrics fm; - DrawParams drawParams; - int paddingx = 0; - int paddingy = 0; + int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0; /* - * First figure out the size of the contents of the button. + * First compute the size of the contents of the button. */ width = 0; height = 0; txtWidth = 0; txtHeight = 0; avgWidth = 0; - TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo); - if (butPtr->image != NULL) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } - if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) { + if (butPtr->text && strlen(butPtr->text) > 0) { + haveText = 1; Tk_FreeTextLayout(butPtr->textLayout); butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, butPtr->text, -1, butPtr->wrapLength, butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); - txtWidth = butPtr->textWidth; txtHeight = butPtr->textHeight; avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); Tk_GetFontMetrics(butPtr->tkfont, &fm); - haveText = (txtWidth != 0 && txtHeight != 0); - } - - /* - * If the button is compound (ie, it shows both an image and text), - * the new geometry is a combination of the image and text geometry. - * We only honor the compound bit if the button has both text and an - * image, because otherwise it is not really a compound button. - */ - - if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { - switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* - * Image is above or below text - */ - - height += txtHeight + butPtr->padY; - width = (width > txtWidth ? width : txtWidth); - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - width += txtWidth + butPtr->padX; - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - width = (width > txtWidth ? width : txtWidth); - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_NONE: {break;} + } + + /* + * If the button is compound (ie, it shows both an image and text), the new + * geometry is a combination of the image and text geometry. We only honor + * the compound bit if the button has both text and an image, because + * otherwise it is not really a compound button. + */ + + if (haveImage && haveText) { + switch ((enum compound) butPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text + */ + + width += txtWidth + butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_NONE: + break; } if (butPtr->width > 0) { width = butPtr->width; } @@ -291,80 +328,33 @@ if (butPtr->height > 0) { height = butPtr->height; } } else { - if (haveImage) { + if (haveImage) { /* Image only */ if (butPtr->width > 0) { width = butPtr->width; } if (butPtr->height > 0) { height = butPtr->height; } - } else { - width = txtWidth; - height = txtHeight; - if (butPtr->width > 0) { - width = butPtr->width * avgWidth; - } - if (butPtr->height > 0) { - height = butPtr->height * fm.linespace; - } - } - } - width += 2 * butPtr->padX - 2; - height += 2 * butPtr->padY - 2; - - /*Add padding for button arrows.*/ - width += 22; - - /* - * Now figure out the size of the border decorations for the button. - */ - - if (butPtr->highlightWidth < 0) { - butPtr->highlightWidth = 0; - } - butPtr->inset = 0; - butPtr->inset += butPtr->highlightWidth; - - TkMacOSXComputeMenuButtonDrawParams(butPtr,&drawParams); - - HIRect tmpRect; - HIRect contBounds; - - tmpRect = CGRectMake(0, 0, width, height); - - HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds); - - - - /* If the content region has a minimum height, match it. */ - if (height < contBounds.size.height) { - height = contBounds.size.height; - } - - /* If the content region has a minimum width, match it. */ - if (width < contBounds.size.width) { - width = contBounds.size.width; - } - - /* Pad to fill difference between content bounds and button bounds. */ - paddingx = tmpRect.origin.x - contBounds.origin.x; - paddingy = tmpRect.origin.y - contBounds.origin.y; - - if (paddingx > 0) { - width += paddingx; - } - if (paddingy > 0) { - height += paddingy; - } - - width += butPtr->inset*2; - height += butPtr->inset*2; - - + } else { /* Text only */ + width = txtWidth; + height = txtHeight; + if (butPtr->width > 0) { + width = butPtr->width * avgWidth + 2*butPtr->padX; + } + if (butPtr->height > 0) { + height = butPtr->height * fm.linespace + 2*butPtr->padY; + } + } + } + + butPtr->inset = highlightWidth + butPtr->borderWidth; + width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset; + height += 2*butPtr->inset; + height = height < MIN_HEIGHT ? MIN_HEIGHT : height; Tk_GeometryRequest(butPtr->tkwin, width, height); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); } /* @@ -382,125 +372,111 @@ * *---------------------------------------------------------------------- */ void DrawMenuButtonImageAndText( - TkMenuButton* butPtr) -{ - MacMenuButton *mbPtr = (MacMenuButton*)butPtr; - Tk_Window tkwin = butPtr->tkwin; - Pixmap pixmap; - int haveImage = 0; - int haveText = 0; - int imageWidth = 0; - int imageHeight = 0; - int imageXOffset = 0; - int imageYOffset = 0; - int textXOffset = 0; - int textYOffset = 0; - int width = 0; - int height = 0; - int fullWidth = 0; - int fullHeight = 0; - int pressed; + TkMenuButton *butPtr) +{ + MacMenuButton *mbPtr = (MacMenuButton *) butPtr; + Tk_Window tkwin = butPtr->tkwin; + Pixmap pixmap; + int haveImage = 0, haveText = 0; + int imageWidth = 0, imageHeight = 0; + int imageXOffset = 0, imageYOffset = 0; + int textXOffset = 0, textYOffset = 0; + int width = 0, height = 0; + int fullWidth = 0, fullHeight = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - DrawParams* dpPtr = &mbPtr->drawParams; - pixmap = (Pixmap)Tk_WindowId(tkwin); - + DrawParams *dpPtr = &mbPtr->drawParams; + pixmap = (Pixmap) Tk_WindowId(tkwin); if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } - imageWidth = width; + imageWidth = width; imageHeight = height; - if (mbPtr->drawinfo.state == kThemeStatePressed) { - /* Offset bitmaps by a bit when the button is pressed. */ - pressed = 1; - } - - haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); - if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { - int x = 0; - int y = 0; + haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); + if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { + int x = 0, y = 0; + textXOffset = 0; textYOffset = 0; fullWidth = 0; fullHeight = 0; switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - if (butPtr->compound == COMPOUND_TOP) { - textYOffset = height + butPtr->padY; - } else { - imageYOffset = butPtr->textHeight + butPtr->padY; - } - fullHeight = height + butPtr->textHeight + butPtr->padY; - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - if (butPtr->compound == COMPOUND_LEFT) { - textXOffset = width + butPtr->padX - 2; - } else { - imageXOffset = butPtr->textWidth + butPtr->padX; - } - fullWidth = butPtr->textWidth + butPtr->padX + width; - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_NONE: {break;} + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; + } + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? + width : butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX - 2; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; + } + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed + */ + + fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth) / 2; + imageXOffset = (fullWidth - width) / 2; + textYOffset = (fullHeight - butPtr->textHeight) / 2; + imageYOffset = (fullHeight - height) / 2; + break; + case COMPOUND_NONE: + break; } TkComputeAnchor(butPtr->anchor, tkwin, - butPtr->padX + butPtr->borderWidth, - butPtr->padY + butPtr->borderWidth, + butPtr->padX + butPtr->inset, butPtr->padY + butPtr->inset, fullWidth, fullHeight, &x, &y); - imageXOffset += x; + imageXOffset = LEFT_INSET; imageYOffset += y; textYOffset -= 1; if (butPtr->image != NULL) { - Tk_RedrawImage(butPtr->image, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); } else { XSetClipOrigin(butPtr->display, dpPtr->gc, imageXOffset, imageYOffset); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, 0, 0, (unsigned int) width, (unsigned int) height, @@ -510,126 +486,122 @@ Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, - butPtr->textLayout, - x + textXOffset, y + textYOffset, + butPtr->textLayout, x + textXOffset, y + textYOffset, butPtr->underline); } else { + int x, y; + if (haveImage) { - int x = 0; - int y; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX + butPtr->borderWidth, butPtr->padY + butPtr->borderWidth, width, height, &x, &y); - imageXOffset += x; - imageYOffset += y; - - if (butPtr->image != NULL) { - Tk_RedrawImage(butPtr->image, 0, 0, width, height, - pixmap, imageXOffset, imageYOffset); + imageXOffset = LEFT_INSET; + imageYOffset += y; + if (butPtr->image != NULL) { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); } else { XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); XCopyPlane(butPtr->display, butPtr->bitmap, - pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, - (unsigned int) height, - imageXOffset, imageYOffset, 1); + pixmap, dpPtr->gc, + 0, 0, (unsigned int) width, + (unsigned int) height, + imageXOffset, imageYOffset, 1); XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } } else { - /*Move x back by eight pixels to give the menubutton arrows room.*/ - int x = 0; - int y; - textXOffset = 8; - TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, - butPtr->textWidth, butPtr->textHeight, &x, &y); - Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, - butPtr->textLayout, x - textXOffset, y, 0, -1); - y += butPtr->textHeight/2; - } - } -} - - - + textXOffset = LEFT_INSET; + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, + butPtr->textWidth, butPtr->textHeight, &x, &y); + Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, textXOffset, y, 0, -1); + y += butPtr->textHeight/2; + } + } +} + /* *-------------------------------------------------------------- * * TkMacOSXDrawMenuButton -- * - * This function draws the tk menubutton using Mac controls - * In addition, this code may apply custom colors passed - * in the TkMenubutton. + * This function draws the tk menubutton using Mac controls. In + * addition, this code may apply custom colors passed in the + * TkMenubutton. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ + static void TkMacOSXDrawMenuButton( MacMenuButton *mbPtr, /* Mac menubutton. */ - GC gc, /* The GC we are drawing into - needed for - * the bevel button */ - Pixmap pixmap) /* The pixmap we are drawing into - needed - * for the bevel button */ - -{ - TkMenuButton * butPtr = ( TkMenuButton *)mbPtr; - TkWindow * winPtr; - HIRect cntrRect; - TkMacOSXDrawingContext dc; - DrawParams* dpPtr = &mbPtr->drawParams; - int useNewerHITools = 1; - - winPtr = (TkWindow *)butPtr->tkwin; + GC gc, /* The GC we are drawing into - needed for the bevel + * button */ + Pixmap pixmap) /* The pixmap we are drawing into - needed for the + * bevel button */ +{ + TkMenuButton *butPtr = (TkMenuButton *) mbPtr; + TkWindow *winPtr = (TkWindow *) butPtr->tkwin; + HIRect cntrRect; + TkMacOSXDrawingContext dc; + DrawParams *dpPtr = &mbPtr->drawParams; + int useNewerHITools = 1; TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo); - cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, Tk_Width(butPtr->tkwin),Tk_Height(butPtr->tkwin)); - - cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset); - + cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, + Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin)); if (useNewerHITools == 1) { HIRect contHIRec; static HIThemeButtonDrawInfo hiinfo; - MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true); - + MenuButtonBackgroundDrawCB(mbPtr, 32, true); if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) { return; } - hiinfo.version = 0; hiinfo.state = mbPtr->drawinfo.state; - hiinfo.kind = mbPtr->btnkind; + hiinfo.kind = mbPtr->btnkind; hiinfo.value = mbPtr->drawinfo.value; hiinfo.adornment = mbPtr->drawinfo.adornment; hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent(); if (hiinfo.animation.time.start == 0) { hiinfo.animation.time.start = hiinfo.animation.time.current; } - HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec); + /* + * To avoid menubuttons with white text on a white background, we + * always set the state to inactive in Dark Mode. It isn't perfect but + * it is usable. Using a ttk::menubutton would be a better choice, + * however. + */ + + if (TkMacOSXInDarkMode(butPtr->tkwin)) { + hiinfo.state = kThemeStateInactive; + } + HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, + kHIThemeOrientationNormal, &contHIRec); TkMacOSXRestoreDrawingContext(&dc); - - MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, (MacMenuButton *)mbPtr, 32, true); + MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo, + mbPtr, 32, true); } else { if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) { return; } - - TkMacOSXRestoreDrawingContext(&dc); } mbPtr->lastdrawinfo = mbPtr->drawinfo; } @@ -636,79 +608,80 @@ /* *-------------------------------------------------------------- * * MenuButtonBackgroundDrawCB -- * - * This function draws the background that - * lies under checkboxes and radiobuttons. + * This function draws the background that lies under checkboxes and + * radiobuttons. * * Results: - * None. + * None. * * Side effects: - * The background gets updated to the current color. + * The background gets updated to the current color. * *-------------------------------------------------------------- */ + static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev) { - TkMenuButton* butPtr = (TkMenuButton*)ptr; - Tk_Window tkwin = butPtr->tkwin; + TkMenuButton* butPtr = (TkMenuButton *) ptr; + Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; + if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - pixmap = (Pixmap)Tk_WindowId(tkwin); - + pixmap = (Pixmap) Tk_WindowId(tkwin); Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); + Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } /* *-------------------------------------------------------------- * * MenuButtonContentDrawCB -- * - * This function draws the label and image for the button. + * This function draws the label and image for the button. * * Results: - * None. + * None. * * Side effects: - * The content of the button gets updated. + * The content of the button gets updated. * *-------------------------------------------------------------- */ + static void MenuButtonContentDrawCB ( ThemeButtonKind kind, const HIThemeButtonDrawInfo *drawinfo, MacMenuButton *ptr, SInt16 depth, Boolean isColorDev) { - TkMenuButton *butPtr = (TkMenuButton *)ptr; - Tk_Window tkwin = butPtr->tkwin; + TkMenuButton *butPtr = (TkMenuButton *) ptr; + Tk_Window tkwin = butPtr->tkwin; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - - DrawMenuButtonImageAndText( butPtr); + DrawMenuButtonImageAndText(butPtr); } /* *-------------------------------------------------------------- * * MenuButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This procedure is invoked by the Tk dispatcher for various events on + * buttons. * * Results: * None. * * Side effects: @@ -720,12 +693,12 @@ static void MenuButtonEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkMenuButton *buttonPtr = (TkMenuButton *) clientData; - MacMenuButton *mbPtr = (MacMenuButton *) clientData; + TkMenuButton *buttonPtr = clientData; + MacMenuButton *mbPtr = clientData; if (eventPtr->type == ActivateNotify || eventPtr->type == DeactivateNotify) { if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) { return; @@ -745,13 +718,13 @@ /* *---------------------------------------------------------------------- * * TkMacOSXComputeMenuButtonParams -- * - * This procedure computes the various parameters used - * when creating a Carbon Appearance control. - * These are determined by the various tk button parameters + * This procedure computes the various parameters used when creating a + * Carbon Appearance control. These are determined by the various Tk + * button parameters * * Results: * None. * * Side effects: @@ -759,23 +732,22 @@ * *---------------------------------------------------------------------- */ static void -TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo *drawinfo) +TkMacOSXComputeMenuButtonParams( + TkMenuButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo) { - MacMenuButton *mbPtr = (MacMenuButton *)butPtr; + MacMenuButton *mbPtr = (MacMenuButton *) butPtr; - if (butPtr->image || butPtr->bitmap) { + if (butPtr->image || butPtr->bitmap || butPtr->text) { /* TODO: allow for Small and Mini menubuttons. */ *btnkind = kThemePopupButton; - } else { - if (!butPtr->text || !*butPtr->text) { - *btnkind = kThemeArrowButton; - } else { - *btnkind = kThemePopupButton; - } + } else { /* This should never happen. */ + *btnkind = kThemeArrowButton; } drawinfo->value = kThemeButtonOff; if ((mbPtr->flags & FIRST_DRAW) != 0) { @@ -810,44 +782,43 @@ /* *---------------------------------------------------------------------- * * TkMacOSXComputeMenuButtonDrawParams -- * - * This procedure computes the various parameters used - * when drawing a button - * These are determined by the various tk button parameters + * This procedure selects an appropriate drawing context for drawing a + * menubutton. * * Results: - * 1 if control will be used, 0 otherwise. + * None. * * Side effects: - * Sets the button draw parameters + * Sets the button draw parameters. * *---------------------------------------------------------------------- */ -static int -TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr) +static void +TkMacOSXComputeMenuButtonDrawParams( + TkMenuButton *butPtr, + DrawParams *dpPtr) { - dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) - || (butPtr->bitmap != None)); + dpPtr->hasImageOrBitmap = + ((butPtr->image != NULL) || (butPtr->bitmap != None)); dpPtr->border = butPtr->normalBorder; if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) { dpPtr->gc = butPtr->disabledGC; } else if (butPtr->state == STATE_ACTIVE) { dpPtr->gc = butPtr->activeTextGC; dpPtr->border = butPtr->activeBorder; } else { dpPtr->gc = butPtr->normalTextGC; } - - return 1; } - + /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXMenus.c ================================================================== --- macosx/tkMacOSXMenus.c +++ macosx/tkMacOSXMenus.c @@ -175,11 +175,10 @@ - (BOOL) validateUserInterfaceItem: (id ) anItem { SEL action = [anItem action]; if (sel_isEqual(action, @selector(preferences:))) { - return (_eventInterp && Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)); } else if (sel_isEqual(action, @selector(tkDemo:))) { BOOL haveDemo = NO; @@ -320,23 +319,22 @@ static Tcl_Obj * GetWidgetDemoPath( Tcl_Interp *interp) { - Tcl_Obj *libpath, *result = NULL; + Tcl_Obj *result = NULL; - libpath = Tcl_GetVar2Ex(interp, "tk_library", NULL, TCL_GLOBAL_ONLY); - if (libpath) { - Tcl_Obj *demo[2] = { Tcl_NewStringObj("demos", 5), - Tcl_NewStringObj("widget", 6) }; + if (Tcl_EvalEx(interp, "::tk::pkgconfig get demodir,runtime", + -1, TCL_EVAL_GLOBAL) == TCL_OK) { + Tcl_Obj *libpath, *demo[1] = { Tcl_NewStringObj("widget", 6) }; + libpath = Tcl_GetObjResult(interp); Tcl_IncrRefCount(libpath); - result = Tcl_FSJoinToPath(libpath, 2, demo); + result = Tcl_FSJoinToPath(libpath, 1, demo); Tcl_DecrRefCount(libpath); - } else { - Tcl_ResetResult(interp); } + Tcl_ResetResult(interp); return result; } /* *---------------------------------------------------------------------- Index: macosx/tkMacOSXMouseEvent.c ================================================================== --- macosx/tkMacOSXMouseEvent.c +++ macosx/tkMacOSXMouseEvent.c @@ -22,14 +22,16 @@ long delta; Window window; Point global; Point local; } MouseEventData; +static Tk_Window captureWinPtr = NULL; /* Current capture window; may be + * NULL. */ static int GenerateButtonEvent(MouseEventData *medPtr); static unsigned int ButtonModifiers2State(UInt32 buttonState, - UInt32 keyModifiers); + UInt32 keyModifiers); #pragma mark TKApplication(TKMouseEvent) enum { NSWindowWillMoveEventType = 20 @@ -45,19 +47,23 @@ */ @implementation TKApplication(TKMouseEvent) - (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent { + NSWindow *eventWindow = [theEvent window]; + NSEventType eventType = [theEvent type]; + TkWindow *winPtr = NULL, *grabWinPtr; + Tk_Window tkwin; + NSPoint local, global; +#if 0 + NSTrackingArea *trackingArea = nil; + NSInteger eventNumber, clickCount, buttonNumber; +#endif + #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); #endif - NSWindow* eventWindow = [theEvent window]; - NSEventType eventType = [theEvent type]; -#if 0 - NSTrackingArea *trackingArea = nil; - NSInteger eventNumber, clickCount, buttonNumber; -#endif switch (eventType) { case NSMouseEntered: case NSMouseExited: case NSCursorUpdate: case NSLeftMouseDown: @@ -71,87 +77,127 @@ case NSOtherMouseDragged: case NSMouseMoved: case NSTabletPoint: case NSTabletProximity: case NSScrollWheel: - break; + break; default: /* Unrecognized mouse event. */ return theEvent; } - /* Remember the window in case we need it next time. */ - if (eventWindow && eventWindow != _windowWithMouse) { - if (_windowWithMouse) { - [_windowWithMouse release]; - } - _windowWithMouse = eventWindow; - [_windowWithMouse retain]; - } - - /* Create an Xevent to add to the Tk queue. */ - NSPoint global, local = [theEvent locationInWindow]; - if (eventWindow) { /* local will be in window coordinates. */ - global = [eventWindow tkConvertPointToScreen: local]; - local.y = [eventWindow frame].size.height - local.y; - global.y = tkMacOSXZeroScreenHeight - global.y; - } else { /* local will be in screen coordinates. */ - if (_windowWithMouse ) { - eventWindow = _windowWithMouse; - global = local; - local = [eventWindow tkConvertPointFromScreen: local]; - local.y = [eventWindow frame].size.height - local.y; - global.y = tkMacOSXZeroScreenHeight - global.y; - } else { /* We have no window. Use the screen???*/ - local.y = tkMacOSXZeroScreenHeight - local.y; - global = local; - } - } - - TkWindow *winPtr = TkMacOSXGetTkWindow(eventWindow); - Tk_Window tkwin = (Tk_Window) winPtr; - - if (tkwin) { - TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr; - if (grabWinPtr && + /* + * Compute the mouse position in Tk screen coordinates (global) and in the + * Tk coordinates of its containing Tk Window (local). If a grab is in effect, + * the local coordinates should be relative to the grab window. + */ + + if (eventWindow) { + local = [theEvent locationInWindow]; + global = [eventWindow tkConvertPointToScreen: local]; + tkwin = TkMacOSXGetCapture(); + if (tkwin) { + winPtr = (TkWindow *) tkwin; + eventWindow = TkMacOSXDrawableWindow(winPtr->window); + if (eventWindow) { + local = [eventWindow tkConvertPointFromScreen: global]; + } else { + return theEvent; + } + } + local.y = [eventWindow frame].size.height - local.y; + global.y = tkMacOSXZeroScreenHeight - global.y; + } else { + + /* + * If the event has no NSWindow, the location is in screen coordinates. + */ + + global = [theEvent locationInWindow]; + tkwin = TkMacOSXGetCapture(); + if (tkwin) { + winPtr = (TkWindow *) tkwin; + eventWindow = TkMacOSXDrawableWindow(winPtr->window); + } else { + eventWindow = [NSApp mainWindow]; + } + if (!eventWindow) { + return theEvent; + } + local = [eventWindow tkConvertPointFromScreen: global]; + local.y = [eventWindow frame].size.height - local.y; + global.y = tkMacOSXZeroScreenHeight - global.y; + } + + /* + * Make sure tkwin is the toplevel which should receive the event. + */ + + if (!tkwin) { + winPtr = TkMacOSXGetTkWindow(eventWindow); + tkwin = (Tk_Window) winPtr; + } + if (!tkwin) { +#ifdef TK_MAC_DEBUG_EVENTS + TkMacOSXDbgMsg("tkwin == NULL"); +#endif + return theEvent; /* Give up. No window for this event. */ + } + + /* + * If another toplevel has a grab, we ignore the event. + */ + + grabWinPtr = winPtr->dispPtr->grabWinPtr; + if (grabWinPtr && grabWinPtr != winPtr && !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ grabWinPtr->mainPtr == winPtr->mainPtr) { - return theEvent; - } - } else { - tkwin = TkMacOSXGetCapture(); - } - if (!tkwin) { - TkMacOSXDbgMsg("tkwin == NULL"); - return theEvent; /* Give up. No window for this event. */ - } else { - winPtr = (TkWindow *)tkwin; - } + return theEvent; + } + + /* + * Convert local from NSWindow flipped coordinates to the toplevel's + * coordinates. + */ local.x -= winPtr->wmInfoPtr->xInParent; local.y -= winPtr->wmInfoPtr->yInParent; + /* + * Find the containing Tk window, and convert local into the coordinates + * of the Tk window. (The converted local coordinates are only needed + * for scrollwheel events.) + */ + int win_x, win_y; tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y); + local.x = win_x; + local.y = win_y; + + /* + * Generate an XEvent for this mouse event. + */ unsigned int state = 0; - NSInteger button = [theEvent buttonNumber]; + int button = [theEvent buttonNumber] + Button1; EventRef eventRef = (EventRef)[theEvent eventRef]; UInt32 buttons; OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord, - typeUInt32, NULL, sizeof(UInt32), NULL, &buttons); + typeUInt32, NULL, sizeof(UInt32), NULL, &buttons); if (err == noErr) { - state |= (buttons & ((1<<5) - 1)) << 8; - } else if (button < 5) { + state |= (buttons & 0x7F) * Button1Mask; + /* Handle buttons 8/9 */ + state |= (buttons & 0x180) * (Button8Mask >> 7); + } else if (button <= Button9) { switch (eventType) { case NSLeftMouseDown: case NSRightMouseDown: case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDown: - state |= 1 << (button + 8); + state |= TkGetButtonMask(button); break; default: break; } } @@ -179,15 +225,24 @@ if (modifiers & NSFunctionKeyMask) { state |= Mod4Mask; } if (eventType != NSScrollWheel) { + /* + * For normal mouse events, Tk_UpdatePointer will send the XEvent. + */ + #ifdef TK_MAC_DEBUG_EVENTS - TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state); + TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", + tkwin, global.x, global.y, state); #endif Tk_UpdatePointer(tkwin, global.x, global.y, state); - } else { /* handle scroll wheel event */ + } else { + /* + * For scroll wheel events we need to send the XEvent here. + */ + CGFloat delta; int coarseDelta; XEvent xEvent; xEvent.type = MouseWheelEvent; @@ -200,20 +255,20 @@ xEvent.xany.window = Tk_WindowId(tkwin); delta = [theEvent deltaY]; if (delta != 0.0) { coarseDelta = (delta > -1.0 && delta < 1.0) ? - (signbit(delta) ? -1 : 1) : lround(delta); + (signbit(delta) ? -1 : 1) : lround(delta); xEvent.xbutton.state = state; xEvent.xkey.keycode = coarseDelta; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } delta = [theEvent deltaX]; if (delta != 0.0) { coarseDelta = (delta > -1.0 && delta < 1.0) ? - (signbit(delta) ? -1 : 1) : lround(delta); + (signbit(delta) ? -1 : 1) : lround(delta); xEvent.xbutton.state = state | ShiftMask; xEvent.xkey.keycode = coarseDelta; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } @@ -306,14 +361,16 @@ UInt32 keyModifiers) { unsigned int state; /* - * Tk supports at most 5 buttons. + * Tk on OSX supports at most 9 buttons. */ - state = (buttonState & ((1<<5) - 1)) << 8; + state = (buttonState & 0x7F) * Button1Mask; + /* Handle buttons 8/9 */ + state |= (buttonState & 0x180) * (Button8Mask >> 7); if (keyModifiers & alphaLock) { state |= LockMask; } if (keyModifiers & shiftKey) { @@ -569,22 +626,68 @@ * Tell the OSX core to generate the events to make it happen. */ buttonState = [NSEvent pressedMouseButtons]; CGEventType type = kCGEventMouseMoved; - CGEventRef theEvent = CGEventCreateMouseEvent(NULL, - type, - pt, - buttonState); + CGEventRef theEvent = CGEventCreateMouseEvent(NULL, type, pt, + buttonState); CGWarpMouseCursorPosition(pt); CGEventPost(kCGHIDEventTap, theEvent); CFRelease(theEvent); } + +/* + *---------------------------------------------------------------------- + * + * TkpSetCapture -- + * + * This function captures the mouse so that all future events will be + * reported to this window, even if the mouse is outside the window. If + * the specified window is NULL, then the mouse is released. + * + * Results: + * None. + * + * Side effects: + * Sets the capture flag and captures the mouse. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetCapture( + TkWindow *winPtr) /* Capture window, or NULL. */ +{ + while (winPtr && !Tk_IsTopLevel(winPtr)) { + winPtr = winPtr->parentPtr; + } + captureWinPtr = (Tk_Window) winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetCapture -- + * + * Results: + * Returns the current grab window + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tk_Window +TkMacOSXGetCapture(void) +{ + return captureWinPtr; +} /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXNotify.c ================================================================== --- macosx/tkMacOSXNotify.c +++ macosx/tkMacOSXNotify.c @@ -31,11 +31,11 @@ static void TkMacOSXNotifyExitHandler(ClientData clientData); static void TkMacOSXEventsSetupProc(ClientData clientData, int flags); static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); #ifdef TK_MAC_DEBUG_EVENTS -static char* Tk_EventName[39] = { +static const char *Tk_EventName[39] = { "", "", "KeyPress", /*2*/ "KeyRelease", /*3*/ "ButtonPress", /*4*/ @@ -134,12 +134,12 @@ * manager. */ /* * Since the contentView is the first responder for a Tk Window, it is - * responsible for sending events up the responder chain. We also check - * the pasteboard here. + * responsible for sending events up the responder chain. We also check the + * pasteboard here. */ - (void) sendEvent: (NSEvent *) theEvent { [super sendEvent:theEvent]; [NSApp tkCheckPasteboard]; @@ -188,12 +188,12 @@ /* *---------------------------------------------------------------------- * * Tk_MacOSXSetupTkNotifier -- * - * This procedure is called during Tk initialization to create - * the event source for TkAqua events. + * This procedure is called during Tk initialization to create the event + * source for TkAqua events. * * Results: * None. * * Side effects: @@ -222,12 +222,11 @@ Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s", "first [load] of TkAqua has to occur in the main thread!"); } Tcl_CreateEventSource(TkMacOSXEventsSetupProc, - TkMacOSXEventsCheckProc, - NULL); + TkMacOSXEventsCheckProc, NULL); TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL); Tcl_SetServiceMode(TCL_SERVICE_ALL); TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode); TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode); } @@ -256,33 +255,32 @@ ClientData clientData) /* Not used. */ { TSD_INIT(); Tcl_DeleteEventSource(TkMacOSXEventsSetupProc, - TkMacOSXEventsCheckProc, - NULL); + TkMacOSXEventsCheckProc, NULL); tsdPtr->initialized = 0; } /* *---------------------------------------------------------------------- * * TkMacOSXEventsSetupProc -- * - * This procedure implements the setup part of the MacOSX event - * source. It is invoked by Tcl_DoOneEvent before calling - * TkMacOSXEventsProc to process all queued NSEvents. In our - * case, all we need to do is to set the Tcl MaxBlockTime to - * 0 before starting the loop to process all queued NSEvents. + * This procedure implements the setup part of the MacOSX event source. It + * is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to + * process all queued NSEvents. In our case, all we need to do is to set + * the Tcl MaxBlockTime to 0 before starting the loop to process all + * queued NSEvents. * * Results: * None. * * Side effects: * - * If NSEvents are queued, then the maximum block time will be set - * to 0 to ensure that control returns immediately to Tcl. + * If NSEvents are queued, then the maximum block time will be set to 0 to + * ensure that control returns immediately to Tcl. * *---------------------------------------------------------------------- */ static void @@ -289,19 +287,28 @@ TkMacOSXEventsSetupProc( ClientData clientData, int flags) { NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode]; - /* runloopMode will be nil if we are in a Tcl event loop. */ + + /* + * 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]; + + /* + * 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) { Tcl_SetMaxBlockTime(&zeroBlockTime); } } @@ -311,56 +318,70 @@ /* *---------------------------------------------------------------------- * * TkMacOSXEventsCheckProc -- * - * This procedure loops through all NSEvents waiting in the - * TKApplication event queue, generating X events from them. + * This procedure loops through all NSEvents waiting in the TKApplication + * event queue, generating X events from them. * * Results: * None. * * Side effects: - * NSevents are used to generate X events, which are added to the - * Tcl event queue. + * NSevents are used to generate X events, which are added to the Tcl + * event queue. * *---------------------------------------------------------------------- */ static void TkMacOSXEventsCheckProc( ClientData clientData, int flags) { NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode]; - /* runloopMode will be nil if we are in a Tcl event loop. */ + + /* + * 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 + + /* + * 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. */ + testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(modalSession) + dequeue:NO]; + + /* + * We must not steal any events during LiveResize. + */ + if (testEvent && [[testEvent window] inLiveResize]) { break; } currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(modalSession) - dequeue:YES]; + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(modalSession) + dequeue:YES]; if (currentEvent) { - /* Generate Xevents. */ + /* + * Generate Xevents. + */ + int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent]; Tcl_SetServiceMode(oldServiceMode); if (processedEvent) { #ifdef TK_MAC_DEBUG_EVENTS @@ -370,24 +391,26 @@ [NSApp _modalSession:modalSession sendEvent:currentEvent]; } else { [NSApp sendEvent:currentEvent]; } } - } else { break; } } while (1); - /* Now we can unlock the pool. */ + + /* + * Now we can unlock the pool. + */ + [NSApp _unlockAutoreleasePool]; } } - /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXPort.h ================================================================== --- macosx/tkMacOSXPort.h +++ macosx/tkMacOSXPort.h @@ -21,10 +21,11 @@ #include #include #include #include #include +#include #include #include #include #ifdef HAVE_SYS_SELECT_H # include @@ -125,21 +126,10 @@ #define TkpCmapStressed(tkwin,colormap) (0) #define TkpFreeColor(tkColPtr) #define TkSetPixmapColormap(p,c) {} #define TkpSync(display) -/* - * The following macro returns the pixel value that corresponds to the - * RGB values in the given XColor structure. - */ - -#define PIXEL_MAGIC ((unsigned char) 0x69) -#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \ - | (((p)->red >> 8) & 0xff)) << 8) \ - | (((p)->green >> 8) & 0xff)) << 8) \ - | (((p)->blue >> 8) & 0xff)) - /* * This macro stores a representation of the window handle in a string. */ #define TkpPrintWindowId(buf,w) \ @@ -157,21 +147,22 @@ * NOTE: values must be kept in sync with indices into the * systemColorMap array in tkMacOSXColor.c ! */ #define TRANSPARENT_PIXEL 30 -#define HIGHLIGHT_PIXEL 31 -#define HIGHLIGHT_SECONDARY_PIXEL 32 -#define HIGHLIGHT_TEXT_PIXEL 33 -#define HIGHLIGHT_ALTERNATE_PIXEL 34 -#define CONTROL_TEXT_PIXEL 35 -#define CONTROL_BODY_PIXEL 37 -#define CONTROL_FRAME_PIXEL 39 -#define WINDOW_BODY_PIXEL 41 -#define MENU_ACTIVE_PIXEL 43 -#define MENU_ACTIVE_TEXT_PIXEL 45 -#define MENU_BACKGROUND_PIXEL 47 -#define MENU_DISABLED_PIXEL 49 -#define MENU_TEXT_PIXEL 51 #define APPEARANCE_PIXEL 52 +#define PIXEL_MAGIC ((unsigned char) 0x69) + +/* + * The following macro returns the pixel value that corresponds to the + * 16-bit RGB values in the given XColor structure. + * The format is: (PIXEL_MAGIC <<< 24) | (R << 16) | (G << 8) | B + * where each of R, G and B is the high order byte of a 16-bit component. + */ + +#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \ + | (((p)->red >> 8) & 0xff)) << 8) \ + | (((p)->green >> 8) & 0xff)) << 8) \ + | (((p)->blue >> 8) & 0xff)) + #endif /* _TKMACPORT */ Index: macosx/tkMacOSXPrivate.h ================================================================== --- macosx/tkMacOSXPrivate.h +++ macosx/tkMacOSXPrivate.h @@ -113,13 +113,14 @@ /* * Macro abstracting use of TkMacOSXGetNamedSymbol to init named symbols. */ +#define UNINITIALISED_SYMBOL ((void*)(-1L)) #define TkMacOSXInitNamedSymbol(module, ret, symbol, ...) \ - static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \ - if (symbol == (void*)(-1L)) { \ + static ret (* symbol)(__VA_ARGS__) = UNINITIALISED_SYMBOL; \ + if (symbol == UNINITIALISED_SYMBOL) { \ symbol = TkMacOSXGetNamedSymbol(STRINGIFY(module), \ STRINGIFY(symbol)); \ } /* @@ -231,10 +232,16 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TkMacOSXIconBitmapObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE void TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc, + int inset, int thickness); +MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp); +MODULE_SCOPE int TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); #pragma mark Private Objective-C Classes #define VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) @@ -259,11 +266,10 @@ Tcl_Interp *_eventInterp; NSMenu *_servicesMenu; 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; int _macMinorVersion; @@ -325,17 +331,22 @@ withReplyEvent: (NSAppleEventDescriptor *)replyEvent; - (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent; - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void)handleURLEvent: (NSAppleEventDescriptor*)event + withReplyEvent: (NSAppleEventDescriptor*)replyEvent; @end VISIBILITY_HIDDEN @interface TKContentView : NSView { +@private NSString *privateWorkingText; + Bool _needsRedisplay; } +@property Bool needsRedisplay; @end @interface TKContentView(TKKeyEvent) - (void) deleteWorkingText; @end @@ -415,14 +426,14 @@ @interface NSApplication(TKMenu) - (void) setAppleMenu: (NSMenu *) menu; @end #endif /* _TKMACPRIV */ - + /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXRegion.c ================================================================== --- macosx/tkMacOSXRegion.c +++ macosx/tkMacOSXRegion.c @@ -185,12 +185,12 @@ * * Implements the equivelent of the X window function XRectInRegion. See * Xwindow documentation for more details. * * Results: - * Returns RectanglePart or RectangleOut. Note that this is not a - * complete implementation since it doesn't test for RectangleIn. + * Returns RectanglePart or RectangleOut. Note that this is not a complete + * implementation since it doesn't test for RectangleIn. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -202,17 +202,17 @@ int x, int y, unsigned int width, unsigned int height) { - if ( TkMacOSXIsEmptyRegion(region) ) { - return RectangleOut; - } - else { + if (TkMacOSXIsEmptyRegion(region)) { + return RectangleOut; + } else { const CGRect r = CGRectMake(x, y, width, height); + return HIShapeIntersectsRect((HIShapeRef) region, &r) ? - RectanglePart : RectangleOut; + RectanglePart : RectangleOut; } } /* *---------------------------------------------------------------------- @@ -232,11 +232,11 @@ */ void TkClipBox( TkRegion r, - XRectangle* rect_return) + XRectangle *rect_return) { CGRect rect; HIShapeGetBounds((HIShapeRef) r, &rect); rect_return->x = rect.origin.x; Index: macosx/tkMacOSXScale.c ================================================================== --- macosx/tkMacOSXScale.c +++ macosx/tkMacOSXScale.c @@ -49,14 +49,14 @@ /* * Forward declarations for procedures defined later in this file: */ -static void MacScaleEventProc(ClientData clientData, XEvent *eventPtr); -static pascal void ScaleActionProc(ControlRef theControl, - ControlPartCode partCode); - +static void MacScaleEventProc(ClientData clientData, + XEvent *eventPtr); +static pascal void ScaleActionProc(ControlRef theControl, + ControlPartCode partCode); /* *---------------------------------------------------------------------- * * TkpCreateScale -- @@ -82,11 +82,11 @@ if (scaleActionProc == NULL) { scaleActionProc = NewControlActionUPP(ScaleActionProc); } Tk_CreateEventHandler(tkwin, ButtonPressMask, - MacScaleEventProc, (ClientData) macScalePtr); + MacScaleEventProc, macScalePtr); return (TkScale *) macScalePtr; } /* @@ -123,12 +123,12 @@ /* *---------------------------------------------------------------------- * * TkpDisplayScale -- * - * This procedure is invoked as an idle handler to redisplay - * the contents of a scale widget. + * This procedure is invoked as an idle handler to redisplay the contents + * of a scale widget. * * Results: * None. * * Side effects: @@ -139,16 +139,16 @@ void TkpDisplayScale( ClientData clientData) /* Widget record for scale. */ { - TkScale *scalePtr = (TkScale *) clientData; + TkScale *scalePtr = clientData; Tk_Window tkwin = scalePtr->tkwin; Tcl_Interp *interp = scalePtr->interp; int result; char string[TCL_DOUBLE_SPACE]; - MacScale *macScalePtr = (MacScale *) clientData; + MacScale *macScalePtr = clientData; Rect r; WindowRef windowRef; CGrafPtr destPort, savePort; Boolean portChanged; MacDrawable *macDraw; @@ -166,13 +166,13 @@ /* * Invoke the scale's command if needed. */ - Tcl_Preserve((ClientData) scalePtr); + Tcl_Preserve(scalePtr); if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { - Tcl_Preserve((ClientData) interp); + Tcl_Preserve(interp); if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; } Tcl_DStringInit(&buf); @@ -183,23 +183,22 @@ Tcl_DStringFree(&buf); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (command executed by scale)"); Tcl_BackgroundException(interp, result); } - Tcl_Release((ClientData) interp); + Tcl_Release(interp); } scalePtr->flags &= ~INVOKE_COMMAND; if (scalePtr->flags & SCALE_DELETED) { - Tcl_Release((ClientData) scalePtr); + Tcl_Release(scalePtr); return; } - Tcl_Release((ClientData) scalePtr); + Tcl_Release(scalePtr); /* - * Now handle the part of redisplay that is the same for - * horizontal and vertical scales: border and traversal - * highlight. + * Now handle the part of redisplay that is the same for horizontal and + * vertical scales: border and traversal highlight. */ if (scalePtr->highlightWidth != 0) { GC gc = Tk_GCForColor(scalePtr->highlightColorPtr, Tk_WindowId(tkwin)); @@ -227,11 +226,11 @@ */ #define MAC_OSX_SCROLL_WIDTH 10 if (scalePtr->orient == ORIENT_HORIZONTAL) { - int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH)/2; + int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2; if (offset < 0) { offset = 0; } @@ -238,20 +237,20 @@ r.left = macDraw->xOff + scalePtr->inset; r.top = macDraw->yOff + offset; r.right = macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset; r.bottom = macDraw->yOff + offset + MAC_OSX_SCROLL_WIDTH/2; } else { - int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH)/2; + int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2; if (offset < 0) { offset = 0; } r.left = macDraw->xOff + offset; r.top = macDraw->yOff + scalePtr->inset; r.right = macDraw->xOff + offset + MAC_OSX_SCROLL_WIDTH/2; - r.bottom = macDraw->yOff+Tk_Height(tkwin) - scalePtr->inset; + r.bottom = macDraw->yOff + Tk_Height(tkwin) - scalePtr->inset; } if (macScalePtr->scaleHandle == NULL) { #ifdef TK_MAC_DEBUG_SCALE TkMacOSXDbgMsg("Initialising scale"); @@ -271,11 +270,11 @@ numTicks = (maxValue - minValue)/scalePtr->tickInterval; } CreateSliderControl(windowRef, &r, initialValue, minValue, maxValue, kControlSliderPointsDownOrRight, numTicks, 1, scaleActionProc, - &(macScalePtr->scaleHandle)); + &macScalePtr->scaleHandle); SetControlReference(macScalePtr->scaleHandle, (UInt32) scalePtr); if (IsWindowActive(windowRef)) { macScalePtr->flags |= ACTIVE; } @@ -288,12 +287,12 @@ /* * Finally draw the control. */ - SetControlVisibility(macScalePtr->scaleHandle,true,true); - HiliteControl(macScalePtr->scaleHandle,0); + SetControlVisibility(macScalePtr->scaleHandle, true, true); + HiliteControl(macScalePtr->scaleHandle, 0); Draw1Control(macScalePtr->scaleHandle); if (portChanged) { QDSwapPort(savePort, NULL); } @@ -304,17 +303,16 @@ /* *---------------------------------------------------------------------- * * TkpScaleElement -- * - * Determine which part of a scale widget lies under a given - * point. + * Determine which part of a scale widget lies under a given point. * * Results: - * The return value is either TROUGH1, SLIDER, TROUGH2, or - * OTHER, depending on which of the scale's active elements - * (if any) is under the point at (x,y). + * The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER, + * depending on which of the scale's active elements (if any) is under the + * point at (x,y). * * Side effects: * None. * *---------------------------------------------------------------------- @@ -355,43 +353,43 @@ #ifdef TK_MAC_DEBUG_SCALE fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v ); #endif switch (part) { - case inSlider: - return SLIDER; - case inInc: - if (scalePtr->orient == ORIENT_VERTICAL) { - return TROUGH1; - } else { - return TROUGH2; - } - case inDecr: - if (scalePtr->orient == ORIENT_VERTICAL) { - return TROUGH2; - } else { - return TROUGH1; - } - default: - return OTHER; + case inSlider: + return SLIDER; + case inInc: + if (scalePtr->orient == ORIENT_VERTICAL) { + return TROUGH1; + } else { + return TROUGH2; + } + case inDecr: + if (scalePtr->orient == ORIENT_VERTICAL) { + return TROUGH2; + } else { + return TROUGH1; + } + default: + return OTHER; } } /* *-------------------------------------------------------------- * * MacScaleEventProc -- * - * This procedure is invoked by the Tk dispatcher for - * ButtonPress events on scales. + * This procedure is invoked by the Tk dispatcher for ButtonPress events + * on scales. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void @@ -409,13 +407,13 @@ #ifdef TK_MAC_DEBUG_SCALE fprintf(stderr,"MacScaleEventProc\n" ); #endif /* - * To call Macintosh control routines we must have the port - * set to the window containing the control. We will then test - * which part of the control was hit and act accordingly. + * To call Macintosh control routines we must have the port set to the + * window containing the control. We will then test which part of the + * control was hit and act accordingly. */ destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin)); portChanged = QDSwapPort(destPort, &savePort); TkMacOSXSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin)); @@ -459,12 +457,12 @@ *-------------------------------------------------------------- * * ScaleActionProc -- * * Callback procedure used by the Macintosh toolbox call - * HandleControlClick. This call will update the display - * while the scrollbar is being manipulated by the user. + * HandleControlClick. This call will update the display while the + * scrollbar is being manipulated by the user. * * Results: * None. * * Side effects: @@ -484,13 +482,13 @@ #ifdef TK_MAC_DEBUG_SCALE TkMacOSXDbgMsg("ScaleActionProc"); #endif value = GetControlValue(theControl); TkScaleSetValue(scalePtr, value, 1, 1); - Tcl_Preserve((ClientData) scalePtr); + Tcl_Preserve(scalePtr); TkMacOSXRunTclEventLoop(); - Tcl_Release((ClientData) scalePtr); + Tcl_Release(scalePtr); } #endif /* * Local Variables: Index: macosx/tkMacOSXScrlbr.c ================================================================== --- macosx/tkMacOSXScrlbr.c +++ macosx/tkMacOSXScrlbr.c @@ -6,41 +6,43 @@ * * Copyright (c) 1996 by Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC. - * Copyright (c) 2018 Marc Culler + * Copyright (c) 2018-2019 Marc Culler + * * 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 "tkScrollbar.h" #include "tkMacOSXPrivate.h" - -#define MIN_SCROLLBAR_VALUE 0 - /* * Minimum slider length, in pixels (designed to make sure that the slider is * always easy to grab with the mouse). */ -#define MIN_SLIDER_LENGTH 5 +#define MIN_SLIDER_LENGTH 18 +#define MIN_GAP 4 -/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.*/ +/* + * Borrowed from ttkMacOSXTheme.c to provide appropriate scaling. + */ + #ifdef __LP64__ -#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) +#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) #else -#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) +#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) #endif /* __LP64__ */ /* * Apple reversed the scroll direction with the release of OSX 10.7 Lion. */ -#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138) +#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138) /* * Declaration of an extended scrollbar structure with Mac specific additions. */ @@ -48,11 +50,11 @@ TkScrollbar information; /* Generic scrollbar info. */ GC troughGC; /* For drawing trough. */ GC copyGC; /* Used for copying from pixmap onto screen. */ Bool buttonDown; /* Is the mouse button down? */ Bool mouseOver; /* Is the pointer over the scrollbar. */ - HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */ + HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */ } MacScrollbar; /* Used to initialize a MacScrollbar's info field. */ HIThemeTrackDrawInfo defaultInfo = { .version = 0, @@ -67,37 +69,40 @@ * variable is declared at this scope. */ const Tk_ClassProcs tkpScrollbarProcs = { sizeof(Tk_ClassProcs), /* size */ - NULL, /* worldChangedProc */ - NULL, /* createProc */ - NULL /* modalProc */ + NULL, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ }; +/* + * Information on scrollbar layout, metrics, and draw info. + */ -/* Information on scrollbar layout, metrics, and draw info.*/ typedef struct ScrollbarMetrics { SInt32 width, minThumbHeight; int minHeight, topArrowHeight, bottomArrowHeight; NSControlSize controlSize; } ScrollbarMetrics; - static ScrollbarMetrics metrics = { - 15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */ + /* kThemeScrollBarMedium */ + 15, MIN_SLIDER_LENGTH, 26, 14, 14, kControlSizeNormal }; - /* * Declarations of static functions defined later in this file: */ -static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr); -static int ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr); -static void UpdateControlValues(TkScrollbar *scrollPtr); - +static void ScrollbarEventProc(ClientData clientData, + XEvent *eventPtr); +static int ScrollbarEvent(TkScrollbar *scrollPtr, + XEvent *eventPtr); +static void UpdateControlValues(TkScrollbar *scrollPtr); + /* *---------------------------------------------------------------------- * * TkpCreateScrollbar -- * @@ -112,30 +117,29 @@ *---------------------------------------------------------------------- */ TkScrollbar * TkpCreateScrollbar( - Tk_Window tkwin) + Tk_Window tkwin) { - - MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar)); + MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar)); scrollPtr->troughGC = NULL; scrollPtr->copyGC = NULL; scrollPtr->info = defaultInfo; scrollPtr->buttonDown = false; Tk_CreateEventHandler(tkwin, - ExposureMask | - StructureNotifyMask | - FocusChangeMask | - ButtonPressMask | - ButtonReleaseMask | - EnterWindowMask | - LeaveWindowMask | - VisibilityChangeMask, - ScrollbarEventProc, scrollPtr); + ExposureMask | + StructureNotifyMask | + FocusChangeMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + VisibilityChangeMask, + ScrollbarEventProc, scrollPtr); return (TkScrollbar *) scrollPtr; } /* @@ -142,12 +146,12 @@ *-------------------------------------------------------------- * * TkpDisplayScrollbar -- * * This procedure redraws the contents of a scrollbar window. It is - * invoked as a do-when-idle handler, so it only runs when there's - * nothing else for the application to do. + * invoked as a do-when-idle handler, so it only runs when there's nothing + * else for the application to do. * * Results: * None. * * Side effects: @@ -154,40 +158,126 @@ * Draws a scrollbar on the screen. * *-------------------------------------------------------------- */ +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 + +/* + * This stand-alone drawing function is used on macOS 10.9 and newer because + * the HIToolbox does not draw the scrollbar thumb at the expected size on + * those systems. The thumb is drawn too large, causing a mouse click on the + * thumb to be interpreted as a mouse click in the trough. + */ + +static void drawMacScrollbar( + TkScrollbar *scrollPtr, + MacScrollbar *msPtr, + CGContextRef context) +{ + MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin); + NSView *view = TkMacOSXDrawableView(macWin); + CGPathRef path; + CGPoint inner[2], outer[2], thumbOrigin; + CGSize thumbSize; + CGRect troughBounds = msPtr->info.bounds; + troughBounds.origin.y = [view bounds].size.height - + (troughBounds.origin.y + troughBounds.size.height); + if (scrollPtr->vertical) { + thumbOrigin.x = troughBounds.origin.x + MIN_GAP; + thumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst; + thumbSize.width = troughBounds.size.width - 2*MIN_GAP + 1; + thumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst; + inner[0] = troughBounds.origin; + inner[1] = CGPointMake(inner[0].x, + inner[0].y + troughBounds.size.height); + outer[0] = CGPointMake(inner[0].x + troughBounds.size.width - 1, + inner[0].y); + outer[1] = CGPointMake(outer[0].x, inner[1].y); + } else { + thumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst; + thumbOrigin.y = troughBounds.origin.y + MIN_GAP; + thumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst; + thumbSize.height = troughBounds.size.height - 2*MIN_GAP + 1; + inner[0] = troughBounds.origin; + inner[1] = CGPointMake(inner[0].x + troughBounds.size.width, + inner[0].y + 1); + outer[0] = CGPointMake(inner[0].x, + inner[0].y + troughBounds.size.height); + outer[1] = CGPointMake(inner[1].x, outer[0].y); + } + CGContextSetShouldAntialias(context, false); + CGContextSetGrayFillColor(context, 250.0 / 255, 1.0); + CGContextFillRect(context, troughBounds); + CGContextSetGrayStrokeColor(context, 232.0 / 255, 1.0); + CGContextStrokeLineSegments(context, inner, 2); + CGContextSetGrayStrokeColor(context, 238.0 / 255, 1.0); + CGContextStrokeLineSegments(context, outer, 2); + + /* + * Do not display the thumb unless scrolling is possible. + */ + + if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) { + CGRect thumbBounds = {thumbOrigin, thumbSize}; + path = CGPathCreateWithRoundedRect(thumbBounds, 4, 4, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + if (msPtr->info.trackInfo.scrollbar.pressState != 0) { + CGContextSetGrayFillColor(context, 133.0 / 255, 1.0); + } else { + CGContextSetGrayFillColor(context, 200.0 / 255, 1.0); + } + CGContextSetShouldAntialias(context, true); + CGContextFillPath(context); + CFRelease(path); + } +} +#endif + void TkpDisplayScrollbar( - ClientData clientData) /* Information about window. */ + ClientData clientData) /* Information about window. */ { - register TkScrollbar *scrollPtr = (TkScrollbar *) clientData; + register TkScrollbar *scrollPtr = clientData; MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; register Tk_Window tkwin = scrollPtr->tkwin; TkWindow *winPtr = (TkWindow *) tkwin; TkMacOSXDrawingContext dc; scrollPtr->flags &= ~REDRAW_PENDING; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { - return; + return; } - MacDrawable *macWin = (MacDrawable *) winPtr->window; + MacDrawable *macWin = (MacDrawable *) winPtr->window; NSView *view = TkMacOSXDrawableView(macWin); - if (!view || - macWin->flags & TK_DO_NOT_DRAW || - !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) { - return; + + if ((view == NULL) + || (macWin->flags & TK_DO_NOT_DRAW) + || !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) { + return; } + /* + * Transform NSView coordinates to CoreGraphics coordinates. + */ + CGFloat viewHeight = [view bounds].size.height; - CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = viewHeight}; + CGAffineTransform t = { + .a = 1, .b = 0, + .c = 0, .d = -1, + .tx = 0, .ty = viewHeight + }; + CGContextConcatCTM(dc.context, t); - /*Draw a 3D rectangle to provide a base for the native scrollbar.*/ + /* + * Draw a 3D rectangle to provide a base for the native scrollbar. + */ + if (scrollPtr->highlightWidth != 0) { GC fgGC, bgGC; bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin); if (scrollPtr->flags & GOT_FOCUS) { @@ -194,36 +284,50 @@ fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin); } else { fgGC = bgGC; } TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth, - (Pixmap) macWin); + (Pixmap) macWin); } Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder, - scrollPtr->highlightWidth, scrollPtr->highlightWidth, - Tk_Width(tkwin) - 2*scrollPtr->highlightWidth, - Tk_Height(tkwin) - 2*scrollPtr->highlightWidth, - scrollPtr->borderWidth, scrollPtr->relief); + scrollPtr->highlightWidth, scrollPtr->highlightWidth, + Tk_Width(tkwin) - 2*scrollPtr->highlightWidth, + Tk_Height(tkwin) - 2*scrollPtr->highlightWidth, + scrollPtr->borderWidth, scrollPtr->relief); Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder, - scrollPtr->inset, scrollPtr->inset, - Tk_Width(tkwin) - 2*scrollPtr->inset, - Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT); + scrollPtr->inset, scrollPtr->inset, + Tk_Width(tkwin) - 2*scrollPtr->inset, + Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT); - /* Update values and then draw the native scrollbar over the rectangle.*/ + /* + * Update values and then draw the native scrollbar over the rectangle. + */ + UpdateControlValues(scrollPtr); if (SNOW_LEOPARD_STYLE) { - HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationInverted); + HIThemeDrawTrack(&msPtr->info, 0, dc.context, + kHIThemeOrientationInverted); + } else if ([NSApp macMinorVersion] <= 8) { + HIThemeDrawTrack(&msPtr->info, 0, dc.context, + kHIThemeOrientationNormal); } else { - HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationNormal); +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 + + /* + * Switch back to NSView coordinates and draw a modern scrollbar. + */ + + CGContextConcatCTM(dc.context, t); + drawMacScrollbar(scrollPtr, msPtr, dc.context); +#endif } TkMacOSXRestoreDrawingContext(&dc); - scrollPtr->flags &= ~REDRAW_PENDING; } - + /* *---------------------------------------------------------------------- * * TkpComputeScrollbarGeometry -- * @@ -238,69 +342,67 @@ * The scrollbar will be displayed differently. * *---------------------------------------------------------------------- */ - - extern void TkpComputeScrollbarGeometry( register TkScrollbar *scrollPtr) - /* Scrollbar whose geometry may have - * changed. */ -{ - - /* - * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to - * account for some differences between macOS and X11. The Unix scrollbar - * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the - * scrollbars by default have both arrow buttons at the bottom or right. - * (There is a preferences setting to use the Unix layout, but we are not - * supporting that!) On more recent versions of macOS there are no arrow - * buttons at all. The case of no arrow buttons can be handled as a special - * case of having both buttons at the end, but where scrollPtr->arrowLength - * happens to be zero. To adjust for having both arrows at the same end we - * shift the scrollbar up by the arrowLength. - */ + /* Scrollbar whose geometry may have + * changed. */ +{ + /* + * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to + * account for some differences between macOS and X11. The Unix scrollbar + * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the + * scrollbars by default have both arrow buttons at the bottom or right. + * (There is a preferences setting to use the Unix layout, but we are not + * supporting that!) On more recent versions of macOS there are no arrow + * buttons at all. The case of no arrow buttons can be handled as a special + * case of having both buttons at the end, but where scrollPtr->arrowLength + * happens to be zero. To adjust for having both arrows at the same end we + * shift the scrollbar up by the arrowLength. + */ int fieldLength; if (scrollPtr->highlightWidth < 0) { - scrollPtr->highlightWidth = 0; + scrollPtr->highlightWidth = 0; } scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth; if ([NSApp macMinorVersion] == 6) { - scrollPtr->arrowLength = scrollPtr->width; + scrollPtr->arrowLength = scrollPtr->width; } else { - scrollPtr->arrowLength = 0; + scrollPtr->arrowLength = 0; } fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) - : Tk_Width(scrollPtr->tkwin)) - - 2*(scrollPtr->arrowLength + scrollPtr->inset); + : Tk_Width(scrollPtr->tkwin)) + - 2*(scrollPtr->arrowLength + scrollPtr->inset); if (fieldLength < 0) { - fieldLength = 0; + fieldLength = 0; } scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction; scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction; /* - * Adjust the slider so that some piece of it is always displayed in the - * scrollbar and so that it has at least a minimal width (so it can be - * grabbed with the mouse). + * Adjust the slider so that it has at least a minimal size and so there + * is a small gap on either end which can be used to scroll by one page. */ + if (scrollPtr->sliderFirst < MIN_GAP) { + scrollPtr->sliderFirst = MIN_GAP; + scrollPtr->sliderLast += MIN_GAP; + } + if (scrollPtr->sliderLast > fieldLength - MIN_GAP) { + scrollPtr->sliderLast = fieldLength - MIN_GAP; + scrollPtr->sliderFirst -= MIN_GAP; + } if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) { - scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH; - } - if (scrollPtr->sliderFirst < 0) { - scrollPtr->sliderFirst = 0; + scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH; } if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) { - scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; - } - if (scrollPtr->sliderLast > fieldLength) { - scrollPtr->sliderLast = fieldLength; + scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; } scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset; scrollPtr->sliderLast += scrollPtr->inset; /* @@ -308,24 +410,24 @@ * two arrows, if there are any arrows, plus a minimum-size slider, plus * border around the whole window, if any. Then arrange for the window to * be redisplayed. */ - if (scrollPtr->vertical) { - Tk_GeometryRequest(scrollPtr->tkwin, - scrollPtr->width + 2*scrollPtr->inset, - 2*(scrollPtr->arrowLength + scrollPtr->borderWidth - + scrollPtr->inset) + metrics.minThumbHeight); + if (scrollPtr->vertical) { + Tk_GeometryRequest(scrollPtr->tkwin, + scrollPtr->width + 2*scrollPtr->inset, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset) + metrics.minThumbHeight); } else { - Tk_GeometryRequest(scrollPtr->tkwin, - 2*(scrollPtr->arrowLength + scrollPtr->borderWidth - + scrollPtr->inset) + metrics.minThumbHeight, - scrollPtr->width + 2*scrollPtr->inset); + Tk_GeometryRequest(scrollPtr->tkwin, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset) + metrics.minThumbHeight, + scrollPtr->width + 2*scrollPtr->inset); } Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset); } - + /* *---------------------------------------------------------------------- * * TkpDestroyScrollbar -- * @@ -340,30 +442,30 @@ *---------------------------------------------------------------------- */ void TkpDestroyScrollbar( - TkScrollbar *scrollPtr) + TkScrollbar *scrollPtr) { - MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr; + MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; if (macScrollPtr->troughGC != None) { Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC); } if (macScrollPtr->copyGC != None) { Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC); } } - + /* *---------------------------------------------------------------------- * * TkpConfigureScrollbar -- * - * This procedure is called after the generic code has finished - * processing configuration options, in order to configure platform - * specific options. There are no such option on the Mac, however. + * This procedure is called after the generic code has finished processing + * configuration options, in order to configure platform specific options. + * There are no such option on the Mac, however. * * Results: * None. * * Side effects: @@ -372,15 +474,15 @@ *---------------------------------------------------------------------- */ void TkpConfigureScrollbar( - register TkScrollbar *scrollPtr) + register TkScrollbar *scrollPtr) { - + /* empty */ } - + /* *-------------------------------------------------------------- * * TkpScrollbarPosition -- * @@ -401,33 +503,32 @@ TkpScrollbarPosition( register TkScrollbar *scrollPtr, /* Scrollbar widget record. */ int x, int y) /* Coordinates within scrollPtr's window. */ { - - /* - * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment - * since it does not involve the arrow buttons. - */ + /* + * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment + * since it does not involve the arrow buttons. + */ int length, width, tmp; register const int inset = scrollPtr->inset; if (scrollPtr->vertical) { - length = Tk_Height(scrollPtr->tkwin); - width = Tk_Width(scrollPtr->tkwin); + length = Tk_Height(scrollPtr->tkwin); + width = Tk_Width(scrollPtr->tkwin); } else { - tmp = x; - x = y; - y = tmp; - length = Tk_Width(scrollPtr->tkwin); - width = Tk_Height(scrollPtr->tkwin); + tmp = x; + x = y; + y = tmp; + length = Tk_Width(scrollPtr->tkwin); + width = Tk_Height(scrollPtr->tkwin); } if (x < inset || x >= width - inset || - y < inset || y >= length - inset) { - return OUTSIDE; + y < inset || y >= length - inset) { + return OUTSIDE; } /* * Here we assume that the scrollbar is layed out with both arrow buttons * at the bottom (or right). Except on 10.6, however, the arrows do not @@ -434,35 +535,38 @@ * actually exist, i.e. the arrowLength is 0. These are the same * assumptions which are being made in TkpComputeScrollbarGeometry. */ if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) { - return TOP_GAP; - } - if (y < scrollPtr->sliderLast) { - return SLIDER; - } - if (y < length - (2*scrollPtr->arrowLength + inset)) { - return BOTTOM_GAP; - } - /* On systems newer than 10.6 we have already returned. */ - if (y < length - (scrollPtr->arrowLength + inset)) { - return TOP_ARROW; - } - return BOTTOM_ARROW; -} - + return TOP_GAP; + } + if (y < scrollPtr->sliderLast) { + return SLIDER; + } + if (y < length - (2*scrollPtr->arrowLength + inset)) { + return BOTTOM_GAP; + } + + /* + * On systems newer than 10.6 we have already returned. + */ + + if (y < length - (scrollPtr->arrowLength + inset)) { + return TOP_ARROW; + } + return BOTTOM_ARROW; +} + /* *-------------------------------------------------------------- * * UpdateControlValues -- * - * This procedure updates the Macintosh scrollbar control to - * display the values defined by the Tk scrollbar. This is the - * key interface to the Mac-native scrollbar; the Unix bindings - * drive scrolling in the Tk window and all the Mac scrollbar has - * to do is redraw itself. + * This procedure updates the Macintosh scrollbar control to display the + * values defined by the Tk scrollbar. This is the key interface to the + * Mac-native scrollbar; the Unix bindings drive scrolling in the Tk + * window and all the Mac scrollbar has to do is redraw itself. * * Results: * None. * * Side effects: @@ -471,43 +575,44 @@ *-------------------------------------------------------------- */ static void UpdateControlValues( - TkScrollbar *scrollPtr) /* Scrollbar data struct. */ + TkScrollbar *scrollPtr) /* Scrollbar data struct. */ { - MacScrollbar *msPtr = (MacScrollbar *)scrollPtr; + MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; Tk_Window tkwin = scrollPtr->tkwin; MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin); double dViewSize; - HIRect contrlRect; + HIRect contrlRect; short width, height; NSView *view = TkMacOSXDrawableView(macWin); CGFloat viewHeight = [view bounds].size.height; NSRect frame; + frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin), - Tk_Height(tkwin)); + Tk_Height(tkwin)); frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset); frame.origin.y = viewHeight - (frame.origin.y + frame.size.height); contrlRect = NSRectToCGRect(frame); msPtr->info.bounds = contrlRect; width = contrlRect.size.width; - height = contrlRect.size.height; + height = contrlRect.size.height - scrollPtr->arrowLength; /* * Ensure we set scrollbar control bounds only once all size adjustments * have been computed. */ msPtr->info.bounds = contrlRect; if (scrollPtr->vertical) { - msPtr->info.attributes &= ~kThemeTrackHorizontal; + msPtr->info.attributes &= ~kThemeTrackHorizontal; } else { - msPtr->info.attributes |= kThemeTrackHorizontal; + msPtr->info.attributes |= kThemeTrackHorizontal; } /* * Given the Tk parameters for the fractions of the start and end of the * thumb, the following calculation determines the location for the @@ -516,73 +621,75 @@ * area in the content area being scrolled. The maximum value of the * control is therefore the dimension of the content area less the size of * the view area. */ - double maximum = 100, factor; - factor = RangeToFactor(maximum); - dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) - * factor; - msPtr->info.max = MIN_SCROLLBAR_VALUE + - factor - dViewSize; + double factor = RangeToFactor(100.0); + dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor; + msPtr->info.max = factor - dViewSize; msPtr->info.trackInfo.scrollbar.viewsize = dViewSize; if (scrollPtr->vertical) { - if (SNOW_LEOPARD_STYLE) { - msPtr->info.value = factor * scrollPtr->firstFraction; - } else { - msPtr->info.value = msPtr->info.max - factor * scrollPtr->firstFraction; - } - } else { - msPtr->info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction; - } - - if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) - || height <= metrics.minHeight) { + if (SNOW_LEOPARD_STYLE) { + msPtr->info.value = factor * scrollPtr->firstFraction; + } else { + msPtr->info.value = msPtr->info.max - + factor * scrollPtr->firstFraction; + } + } else { + msPtr->info.value = factor * scrollPtr->firstFraction; + } + + if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) + || height <= metrics.minHeight) { msPtr->info.enableState = kThemeTrackHideTrack; } else { msPtr->info.enableState = kThemeTrackActive; - msPtr->info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost; + msPtr->info.attributes = + kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost; } - } - + /* *-------------------------------------------------------------- * * ScrollbarEvent -- * - * This procedure is invoked in response to , , - * , and events. The Scrollbar appearance is - * modified for each event. + * This procedure is invoked in response to , + * , , and events. The + * Scrollbar appearance is modified for each event. * *-------------------------------------------------------------- */ static int -ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr) -{ - MacScrollbar *msPtr = (MacScrollbar *)scrollPtr; - - /* The pressState does not indicate whether the moused button was - * pressed at some location in the Scrollbar. Rather, it indicates - * that the scrollbar should appear as if it were pressed in that - * location. The standard Mac behavior is that once the button is - * pressed inside the Scrollbar the appearance should not change until - * the button is released, even if the mouse moves outside of the - * scrollbar. However, if the mouse lies over the scrollbar but the - * button is not pressed then the appearance should be the same as if - * the button had been pressed on the slider, i.e. kThemeThumbPressed. - * See the file Appearance.r, or HIToolbox.bridgesupport on 10.14. +ScrollbarEvent( + TkScrollbar *scrollPtr, + XEvent *eventPtr) +{ + MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; + + /* + * The pressState does not indicate whether the moused button was pressed + * at some location in the Scrollbar. Rather, it indicates that the + * scrollbar should appear as if it were pressed in that location. The + * standard Mac behavior is that once the button is pressed inside the + * Scrollbar the appearance should not change until the button is released, + * even if the mouse moves outside of the scrollbar. However, if the mouse + * lies over the scrollbar but the button is not pressed then the + * appearance should be the same as if the button had been pressed on the + * slider, i.e. kThemeThumbPressed. See the file Appearance.r, or + * HIToolbox.bridgesupport on 10.14. */ if (eventPtr->type == ButtonPress) { msPtr->buttonDown = true; UpdateControlValues(scrollPtr); + int where = TkpScrollbarPosition(scrollPtr, - eventPtr->xbutton.x, - eventPtr->xbutton.y); - switch(where) { + eventPtr->xbutton.x, eventPtr->xbutton.y); + + switch (where) { case OUTSIDE: msPtr->info.trackInfo.scrollbar.pressState = 0; break; case TOP_GAP: msPtr->info.trackInfo.scrollbar.pressState = kThemeTopTrackPressed; @@ -589,18 +696,25 @@ break; case SLIDER: msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed; break; case BOTTOM_GAP: - msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomTrackPressed; + msPtr->info.trackInfo.scrollbar.pressState = + kThemeBottomTrackPressed; break; case TOP_ARROW: - /* This looks wrong and the docs say it is wrong but it works. */ - msPtr->info.trackInfo.scrollbar.pressState = kThemeTopInsideArrowPressed; + + /* + * This looks wrong and the docs say it is wrong but it works. + */ + + msPtr->info.trackInfo.scrollbar.pressState = + kThemeTopInsideArrowPressed; break; case BOTTOM_ARROW: - msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomOutsideArrowPressed; + msPtr->info.trackInfo.scrollbar.pressState = + kThemeBottomOutsideArrowPressed; break; } } if (eventPtr->type == ButtonRelease) { msPtr->buttonDown = false; @@ -618,15 +732,14 @@ msPtr->mouseOver = false; if (!msPtr->buttonDown) { msPtr->info.trackInfo.scrollbar.pressState = 0; } } + TkScrollbarEventuallyRedraw(scrollPtr); return TCL_OK; } - - - + /* *-------------------------------------------------------------- * * ScrollbarEventProc -- * @@ -643,12 +756,12 @@ *-------------------------------------------------------------- */ static void ScrollbarEventProc( - ClientData clientData, /* Information about window. */ - XEvent *eventPtr) /* Information about event. */ + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkScrollbar *scrollPtr = clientData; switch (eventPtr->type) { case UnmapNotify: @@ -666,14 +779,14 @@ break; default: TkScrollbarEventProc(clientData, eventPtr); } } - + /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXSend.c ================================================================== --- macosx/tkMacOSXSend.c +++ macosx/tkMacOSXSend.c @@ -49,11 +49,11 @@ /* * A registry of all interpreters for a display is kept in a property * "InterpRegistry" on the root window of the display. It is organized as a * series of zero or more concatenated strings (in no particular order), each - * of the form + * of the form: * window space name '\0' * where "window" is the hex id of the comm. window to use to talk to an * interpreter named "name". * * When the registry is being manipulated by an application (e.g. to add or @@ -76,11 +76,11 @@ * character. Dynamically allocated. */ int allocedByX; /* Non-zero means must free property with * XFree; zero means use ckfree. */ } NameRegistry; -static int initialized = 0; /* A flag to denote if we have initialized +static int initialized = 0; /* A flag to denote if we have initialized * yet. */ static RegisteredInterp *interpListPtr = NULL; /* List of all interpreters registered by this * process. */ @@ -323,11 +323,11 @@ ClientData clientData, /* Used only for deletion */ Tcl_Interp *interp, /* The interp we are sending from */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* The arguments */ { - const char *const sendOptions[] = {"-async", "-displayof", "-", NULL}; + const char *const sendOptions[] = {"-async", "-displayof", "--", NULL}; char *stringRep, *destName; /*int async = 0;*/ int i, index, firstArg; RegisteredInterp *riPtr; Tcl_Obj *listObjPtr; ADDED macosx/tkMacOSXServices.c Index: macosx/tkMacOSXServices.c ================================================================== --- /dev/null +++ macosx/tkMacOSXServices.c @@ -0,0 +1,240 @@ +/* + * tkMacOSXServices.c -- + *\ + * This file allows the integration of Tk and the Cocoa NSServices API. + * + * Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC. + * Copyright (c) 2010 Adrian Robert. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include +#include +#include + +static Tcl_Interp *ServicesInterp; + +/* + * Event proc which calls the PerformService procedure + */ + +static int +ServicesEventProc( + Tcl_Event *event, + int flags) +{ + Tcl_GlobalEval(ServicesInterp, "::tk::mac::PerformService"); + return 1; +} + +/* + * Class declarations for TkService class. + */ + +@interface TkService : NSView { + +} + ++ (void) initialize; +- (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error; +- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType; +- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types; + +@end + +/* + * Class methods. + */ + +@implementation TkService + ++ (void) initialize { + NSArray *sendTypes = [NSArray arrayWithObjects:@"NSStringPboardType", + @"NSPasteboardTypeString", nil]; + [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes]; + return; +} + + +- (id)validRequestorForSendType:(NSString *)sendType + returnType:(NSString *)returnType +{ + if ([sendType isEqualToString:@"NSStringPboardType"] || + [sendType isEqualToString:@"NSPasteboardTypeString"]) { + return self; + } + return [super validRequestorForSendType:sendType returnType:returnType]; +} + +/* + * Make sure the view accepts events. + */ + +- (BOOL)acceptsFirstResponder +{ + return YES; +} +- (BOOL)becomeFirstResponder +{ + return YES; +} + +/* + * Get selected text, copy to pasteboard. + */ + +- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard + types:(NSArray *)types +{ + NSArray *typesDeclared = nil; + NSString *pboardType = nil; + + for (NSString *typeString in types) { + if ([typeString isEqualToString:@"NSStringPboardType"] || + [typeString isEqualToString:@"NSPasteboardTypeString"]) { + typesDeclared = [NSArray arrayWithObject:typeString]; + pboardType = typeString; + break; + } + } + if (!typesDeclared) { + return NO; + } + Tcl_Eval(ServicesInterp, "selection get"); + + char *copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp)); + NSString *writestring = [NSString stringWithUTF8String:copystring]; + + [pboard declareTypes:typesDeclared owner:nil]; + return [pboard setString:writestring forType:pboardType]; +} + +/* + * This is the method that actually calls the Tk service; this is the method + * that must be defined in info.plist. + */ + +- (void)provideService:(NSPasteboard *)pboard + userData:(NSString *)data + error:(NSString **)error +{ + NSString *pboardString = nil, *pboardType = nil; + NSArray *types = [pboard types]; + Tcl_Event *event; + + /* + * Get string from private pasteboard, write to general pasteboard to make + * available to Tcl service. + */ + + for (NSString *typeString in types) { + if ([typeString isEqualToString:@"NSStringPboardType"] || + [typeString isEqualToString:@"NSPasteboardTypeString"]) { + pboardString = [pboard stringForType:typeString]; + pboardType = typeString; + break; + } + } + if (pboardString) { + NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard]; + [generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil] + owner:nil]; + [generalpasteboard setString:pboardString forType:pboardType]; + event = ckalloc(sizeof(Tcl_Event)); + event->proc = ServicesEventProc; + Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL); + } +} +@end + +/* + * Register a specific widget to access the Services menu. + */ + +int +TkMacOSXRegisterServiceWidgetObjCmd( + ClientData cd, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + /* + * Need proper number of args. + */ + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "path?"); + return TCL_ERROR; + } + + /* + * Get the object that holds this Tk Window... + */ + + Rect bounds; + NSRect frame; + Tk_Window path = Tk_NameToWindow(interp, + Tcl_GetString(objv[1]), Tk_MainWindow(interp)); + + if (path == NULL) { + return TCL_ERROR; + } + + Tk_MakeWindowExist(path); + Tk_MapWindow(path); + Drawable d = Tk_WindowId(path); + + /* + * Get NSView from Tk window and add subview. + */ + + TkService *serviceview = [[TkService alloc] init]; + NSView *view = TkMacOSXGetRootControl(d); + + if ([serviceview superview] != view) { + [view addSubview:serviceview]; + } + TkMacOSXWinBounds((TkWindow*)path, &bounds); + + /* + * Hack to make sure subview is set to take up entire geometry of window. + */ + + frame = NSMakeRect(bounds.left, bounds.top, 100000, 100000); + frame.origin.y = 0; + if (!NSEqualRects(frame, [serviceview frame])) { + [serviceview setFrame:frame]; + } + [serviceview release]; + return TCL_OK; +} + +/* + * Initalize the package in the Tcl interpreter, create Tcl commands. + */ + +int +TkMacOSXServices_Init( + Tcl_Interp *interp) +{ + /* + * Initialize instance of TclServices to provide service functionality. + */ + + TkService *service = [[TkService alloc] init]; + + ServicesInterp = interp; + [NSApp setServicesProvider:service]; + return TCL_OK; +} + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ Index: macosx/tkMacOSXSubwindows.c ================================================================== --- macosx/tkMacOSXSubwindows.c +++ macosx/tkMacOSXSubwindows.c @@ -63,23 +63,26 @@ TkPointerDeadWindow(macWin->winPtr); TkMacOSXSelDeadWindow(macWin->winPtr); macWin->toplevel->referenceCount--; - if (!Tk_IsTopLevel(macWin->winPtr) ) { + if (!Tk_IsTopLevel(macWin->winPtr)) { TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); if (macWin->winPtr->parentPtr != NULL) { TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); } if (macWin->visRgn) { CFRelease(macWin->visRgn); + macWin->visRgn = NULL; } if (macWin->aboveVisRgn) { CFRelease(macWin->aboveVisRgn); + macWin->aboveVisRgn = NULL; } if (macWin->drawRgn) { CFRelease(macWin->drawRgn); + macWin->drawRgn = NULL; } if (macWin->toplevel->referenceCount == 0) { ckfree(macWin->toplevel); } @@ -86,16 +89,19 @@ ckfree(macWin); return; } if (macWin->visRgn) { CFRelease(macWin->visRgn); + macWin->visRgn = NULL; } if (macWin->aboveVisRgn) { CFRelease(macWin->aboveVisRgn); + macWin->aboveVisRgn = NULL; } if (macWin->drawRgn) { CFRelease(macWin->drawRgn); + macWin->drawRgn = NULL; } macWin->view = nil; /* * Delay deletion of a toplevel data structure untill all children have @@ -128,10 +134,12 @@ XMapWindow( Display *display, /* Display. */ Window window) /* Window. */ { MacDrawable *macWin = (MacDrawable *) window; + TkWindow *winPtr = macWin->winPtr; + NSWindow *win = TkMacOSXDrawableWindow(window); XEvent event; /* * Under certain situations it's possible for this function to be called * before the toplevel window it's associated with has actually been @@ -143,41 +151,44 @@ if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) { TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr); } display->request++; - macWin->winPtr->flags |= TK_MAPPED; - if (Tk_IsTopLevel(macWin->winPtr)) { - if (!Tk_IsEmbedded(macWin->winPtr)) { - NSWindow *win = TkMacOSXDrawableWindow(window); + winPtr->flags |= TK_MAPPED; + if (Tk_IsTopLevel(winPtr)) { + if (!Tk_IsEmbedded(winPtr)) { + /* - * We want to activate Tk when a toplevel is mapped - * but we must not supply YES here. This is because - * during Tk initialization the root window is mapped - * before applicationDidFinishLaunching returns. Forcing - * the app to activate too early can make the menu bar - * unresponsive. + * We want to activate Tk when a toplevel is mapped but we must not + * supply YES here. This is because during Tk initialization the + * root window is mapped before applicationDidFinishLaunching + * returns. Forcing the app to activate too early can make the menu + * bar unresponsive. */ - TkMacOSXApplyWindowAttributes(macWin->winPtr, win); + + TkMacOSXApplyWindowAttributes(winPtr, win); [win setExcludedFromWindowsMenu:NO]; [NSApp activateIgnoringOtherApps:NO]; [[win contentView] setNeedsDisplay:YES]; - if ( [win canBecomeKeyWindow] ) { + if ([win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; } else { [win orderFrontRegardless]; } } else { + TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); + /* * Rebuild the container's clipping region and display * the window. */ - TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr); - TkMacOSXInvalClipRgns((Tk_Window)contWinPtr); + + TkMacOSXInvalClipRgns((Tk_Window) contWinPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } - TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr); + + TkMacOSXInvalClipRgns((Tk_Window) winPtr); /* * We only need to send the MapNotify event for toplevel windows. */ @@ -186,20 +197,26 @@ event.xany.display = display; event.xmap.window = window; event.xmap.type = MapNotify; event.xmap.event = window; - event.xmap.override_redirect = macWin->winPtr->atts.override_redirect; + event.xmap.override_redirect = winPtr->atts.override_redirect; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } else { + /* - * Rebuild the parent's clipping region and display the window. - * + * For non-toplevel windows, rebuild the parent's clipping region + * and redisplay the window. */ - TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr); + } + + if ([NSApp isDrawing]) { + [[win contentView] setNeedsRedisplay:YES]; + } else { + [[win contentView] setNeedsDisplay:YES]; } /* * Generate VisibilityNotify events for window and all mapped children. */ @@ -206,18 +223,11 @@ event.xany.send_event = False; event.xany.display = display; event.xvisibility.type = VisibilityNotify; event.xvisibility.state = VisibilityUnobscured; - NotifyVisibility(macWin->winPtr, &event); - - /* - * Make sure that subwindows get displayed. - */ - - GenerateConfigureNotify(macWin->winPtr, 1); - + NotifyVisibility(winPtr, &event); } /* *---------------------------------------------------------------------- * @@ -275,22 +285,18 @@ Window window) /* Window. */ { MacDrawable *macWin = (MacDrawable *) window; TkWindow *winPtr = macWin->winPtr; TkWindow *parentPtr = winPtr->parentPtr; + NSWindow *win = TkMacOSXDrawableWindow(window); 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]; - } + [win orderOut:nil]; } TkMacOSXInvalClipRgns((Tk_Window) winPtr); /* * We only need to send the UnmapNotify event for toplevel windows. @@ -304,24 +310,30 @@ 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. + * to draw in the space from which this subwindow was removed and then + * redraw the window. */ if (parentPtr && parentPtr->privatePtr->visRgn) { - TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr), - parentPtr->privatePtr->visRgn); + TkMacOSXInvalidateViewRegion( + TkMacOSXDrawableView(parentPtr->privatePtr), + parentPtr->privatePtr->visRgn); } TkMacOSXInvalClipRgns((Tk_Window) parentPtr); TkMacOSXUpdateClipRgn(parentPtr); } winPtr->flags &= ~TK_MAPPED; + if ([NSApp isDrawing]) { + [[win contentView] setNeedsRedisplay:YES]; + } else { + [[win contentView] setNeedsDisplay:YES]; + } } /* *---------------------------------------------------------------------- * @@ -345,15 +357,18 @@ Window window, /* Window. */ unsigned int width, unsigned int height) { MacDrawable *macWin = (MacDrawable *) window; + display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; + if (w) { NSRect r = [w contentRectForFrameRect:[w frame]]; + r.origin.y += r.size.height - height; r.size.width = width; r.size.height = height; [w setFrame:[w frameRectForContentRect:r] display:YES]; } @@ -365,12 +380,12 @@ /* *---------------------------------------------------------------------- * * XMoveResizeWindow -- * - * Move or resize a given X window. See X windows documentation - * for further details. + * Move or resize a given X window. See X windows documentation for + * further details. * * Results: * None. * * Side effects: @@ -390,26 +405,28 @@ MacDrawable *macWin = (MacDrawable *) window; display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; + if (w) { - - /* We explicitly convert everything to doubles so we don't get + /* + * We explicitly convert everything to doubles so we don't get * surprised (again) by what happens when you do arithmetic with * unsigned ints. */ - CGFloat X = (CGFloat)x; - CGFloat Y = (CGFloat)y; - CGFloat Width = (CGFloat)width; - CGFloat Height = (CGFloat)height; - CGFloat XOff = (CGFloat)macWin->winPtr->wmInfoPtr->xInParent; - CGFloat YOff = (CGFloat)macWin->winPtr->wmInfoPtr->yInParent; - NSRect r = NSMakeRect(X + XOff, - tkMacOSXZeroScreenHeight - Y - YOff - Height, - Width, Height); + CGFloat X = (CGFloat) x; + CGFloat Y = (CGFloat) y; + CGFloat Width = (CGFloat) width; + CGFloat Height = (CGFloat) height; + CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent; + CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent; + NSRect r = NSMakeRect( + X + XOff, tkMacOSXZeroScreenHeight - Y - YOff - Height, + Width, Height); + [w setFrame:[w frameRectForContentRect:r] display:YES]; } } else { MoveResizeWindow(macWin); } @@ -418,12 +435,11 @@ /* *---------------------------------------------------------------------- * * XMoveWindow -- * - * Move a given X window. See X windows documentation for further - * details. + * Move a given X window. See X windows documentation for further details. * * Results: * None. * * Side effects: @@ -441,12 +457,14 @@ MacDrawable *macWin = (MacDrawable *) window; display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; + if (w) { - [w setFrameTopLeftPoint:NSMakePoint(x, tkMacOSXZeroScreenHeight - y)]; + [w setFrameTopLeftPoint: NSMakePoint( + x, tkMacOSXZeroScreenHeight - y)]; } } else { MoveResizeWindow(macWin); } } @@ -483,20 +501,18 @@ TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr); if (contWinPtr) { macParent = contWinPtr->privatePtr; } else { - /* * Here we should handle out of process embedding. At this point, * we are assuming that the changes.x,y is not maintained, if you * need the info get it from Tk_GetRootCoords, and that the * toplevel sits at 0,0 when it is drawn. */ } } else { - /* * TODO: update all xOff & yOffs */ macParent = macWin->winPtr->parentPtr->privatePtr; @@ -584,11 +600,10 @@ display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { TkWmRestackToplevel(macWin->winPtr, Above, NULL); } else { - /* * TODO: this should generate damage */ } } @@ -619,11 +634,10 @@ display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { TkWmRestackToplevel(macWin->winPtr, Below, NULL); } else { - /* * TODO: this should generate damage */ } } @@ -682,18 +696,20 @@ if (view) { TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr); TkMacOSXWinBounds(winPtr, &bounds); r = NSMakeRect(bounds.left, - [view bounds].size.height - bounds.bottom, - bounds.right - bounds.left, bounds.bottom - bounds.top); + [view bounds].size.height - bounds.bottom, + bounds.right - bounds.left, bounds.bottom - bounds.top); [view setNeedsDisplayInRect:r]; } } - /* TkGenWMMoveRequestEvent(macWin->winPtr, - macWin->winPtr->changes.x, macWin->winPtr->changes.y); */ +#if 0 + TkGenWMMoveRequestEvent(macWin->winPtr, + macWin->winPtr->changes.x, macWin->winPtr->changes.y); +#endif } /* *---------------------------------------------------------------------- * @@ -711,27 +727,27 @@ *---------------------------------------------------------------------- */ void TkMacOSXSetDrawingEnabled( - TkWindow *winPtr, - int flag) + TkWindow *winPtr, + int flag) { TkWindow *childPtr; MacDrawable *macWin = winPtr->privatePtr; if (macWin) { - if (flag ) { + if (flag) { macWin->flags &= ~TK_DO_NOT_DRAW; } else { macWin->flags |= TK_DO_NOT_DRAW; } } /* - * Set the flag for all children & their descendants, excluding - * Toplevels. (??? Do we need to exclude Toplevels?) + * Set the flag for all children & their descendants, excluding Toplevels. + * (??? Do we need to exclude Toplevels?) */ childPtr = winPtr->childList; while (childPtr) { if (!Tk_IsTopLevel(childPtr)) { @@ -891,11 +907,10 @@ } CFRelease(diffRgn); } CFRelease(rgn); } else { - /* * An unmapped window has empty clip regions to prevent any * (erroneous) drawing into it or its children from becoming * visible. [Bug 940117] */ @@ -921,12 +936,12 @@ *---------------------------------------------------------------------- * * TkMacOSXVisableClipRgn -- * * This function returns the Macintosh clipping region for the given - * window. The caller is responsible for disposing of the returned - * region via TkDestroyRegion(). + * window. The caller is responsible for disposing of the returned region + * via TkDestroyRegion(). * * Results: * The region. * * Side effects: @@ -940,11 +955,11 @@ TkWindow *winPtr) { if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(winPtr); } - return (TkRegion)HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn); + return (TkRegion) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn); } /* *---------------------------------------------------------------------- * @@ -960,11 +975,16 @@ * *---------------------------------------------------------------------- */ static OSStatus -InvalViewRect(int msg, HIShapeRef rgn, const CGRect *rect, void *ref) { +InvalViewRect( + int msg, + HIShapeRef rgn, + const CGRect *rect, + void *ref) +{ static CGAffineTransform t; NSView *view = ref; if (!view) { return paramErr; @@ -1040,11 +1060,11 @@ * None. * *---------------------------------------------------------------------- */ -NSWindow* +NSWindow * TkMacOSXDrawableWindow( Drawable drawable) { MacDrawable *macWin = (MacDrawable *) drawable; NSWindow *result = nil; @@ -1058,10 +1078,11 @@ } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr && macWin->winPtr->wmInfoPtr->window) { result = macWin->winPtr->wmInfoPtr->window; } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) { TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr); + if (contWinPtr) { result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr); } } return result; @@ -1111,11 +1132,11 @@ * None. * *---------------------------------------------------------------------- */ -NSView* +NSView * TkMacOSXDrawableView( MacDrawable *macWin) { NSView *result = nil; @@ -1125,10 +1146,11 @@ result = macWin->view; } else if (!(macWin->toplevel->flags & TK_EMBEDDED)) { result = macWin->toplevel->view; } else { TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr); + if (contWinPtr) { result = TkMacOSXDrawableView(contWinPtr->privatePtr); } } return result; @@ -1152,11 +1174,10 @@ void * TkMacOSXGetRootControl( Drawable drawable) { - /* * will probably need to fix this up for embedding */ return TkMacOSXDrawableView((MacDrawable *) drawable); @@ -1269,11 +1290,12 @@ void TkMacOSXWinBounds( TkWindow *winPtr, void *bounds) { - Rect *b = (Rect *)bounds; + Rect *b = (Rect *) bounds; + b->left = winPtr->privatePtr->xOff; b->top = winPtr->privatePtr->yOff; b->right = b->left + winPtr->changes.width; b->bottom = b->top + winPtr->changes.height; } @@ -1312,11 +1334,11 @@ *---------------------------------------------------------------------- * * UpdateOffsets -- * * Updates the X & Y offsets of the given TkWindow from the TopLevel it is - * a decendant of. + * a descendant of. * * Results: * None. * * Side effects: @@ -1333,11 +1355,10 @@ int deltaY) { TkWindow *childPtr; if (winPtr->privatePtr == NULL) { - /* * We haven't called Tk_MakeWindowExist for this window yet. The offset * information will be postponed and calulated at that time. (This will * usually only happen when a mapped parent is being moved but has * child windows that have yet to be mapped.) Index: macosx/tkMacOSXTest.c ================================================================== --- macosx/tkMacOSXTest.c +++ macosx/tkMacOSXTest.c @@ -16,12 +16,15 @@ /* * Forward declarations of procedures defined later in this file: */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080 static int DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); + int objc, Tcl_Obj *const objv[]); +#endif + /* *---------------------------------------------------------------------- * * TkplatformtestInit -- @@ -44,22 +47,24 @@ { /* * Add commands for platform specific tests on MacOS here. */ - Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, - (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080 + Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL); +#endif return TCL_OK; } /* *---------------------------------------------------------------------- * * DebuggerObjCmd -- * - * This procedure simply calls the low level debugger. + * This procedure simply calls the low level debugger, which was + * deprecated in OSX 10.8. * * Results: * A standard Tcl result. * * Side effects: @@ -66,10 +71,11 @@ * None. * *---------------------------------------------------------------------- */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080 static int DebuggerObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Not used. */ int objc, /* Not used. */ @@ -76,35 +82,43 @@ Tcl_Obj *const objv[]) /* Not used. */ { Debugger(); return TCL_OK; } +#endif /* *---------------------------------------------------------------------- * - * TkTestAppIsDrawing -- - * - * A test widget display procedure which records calls can use this to - * detect whether it is being called from within [NSView drawRect]. - * If so, it probably should not be recording the call since it was - * probably generated spontaneously by the window manager rather than - * by an explicit call to update. This is just a wrapper for the NSApp - * property. - * + * TkTestLogDisplay -- + * + * The test image display procedure calls this to determine whether it + * should write a log message recording that it has being run. On OSX + * 10.14 and later, only calls to the display procedure which occur inside + * of the drawRect method should be logged, since those are the only ones + * which actually draw anything. On earlier systems the opposite is true. + * The calls from within the drawRect method are redundant, since the + * first time the display procedure is run it will do the drawing and that + * first call will usually not occur inside of drawRect. * * Results: - * Returns true if and only if called from within [NSView drawRect]. + * On OSX 10.14 and later, returns true if and only if called from + * within [NSView drawRect]. On earlier systems returns false if + * and only if called from with [NSView drawRect]. * * Side effects: * None * *---------------------------------------------------------------------- */ MODULE_SCOPE Bool -TkTestAppIsDrawing(void) { - return [NSApp isDrawing]; +TkTestLogDisplay(void) { + if ([NSApp macMinorVersion] >= 14) { + return [NSApp isDrawing]; + } else { + return ![NSApp isDrawing]; + } } /* * Local Variables: Index: macosx/tkMacOSXWindowEvent.c ================================================================== --- macosx/tkMacOSXWindowEvent.c +++ macosx/tkMacOSXWindowEvent.c @@ -66,23 +66,21 @@ { #ifdef TK_MAC_DEBUG_NOTIFICATIONS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); #endif BOOL movedOnly = [[notification name] - isEqualToString:NSWindowDidMoveNotification]; + isEqualToString:NSWindowDidMoveNotification]; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect bounds = [w frame]; - NSRect screenRect = [[w screen] frame]; int x, y, width = -1, height = -1, flags = 0; - int minY = 1 + [[NSApp mainMenu] menuBarHeight]; x = bounds.origin.x; - y = screenRect.size.height - (bounds.origin.y + bounds.size.height); + y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height); if (winPtr->changes.x != x || winPtr->changes.y != y) { flags |= TK_LOCATION_CHANGED; } else { x = y = -1; } @@ -91,32 +89,17 @@ width = bounds.size.width - wmPtr->xInParent; height = bounds.size.height - wmPtr->yInParent; flags |= TK_SIZE_CHANGED; } if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) { - /* * Propagate geometry changes immediately. */ flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY; } - /* - * Mac windows cannot go higher than the bottom of the menu bar. The - * Tk window manager can request that a window be drawn so that it - * overlaps the menu bar, but it will actually be drawn immediately - * below the menu bar. In such a case it saves a lot of trouble and - * causes no harm if we let Tk think that the window is located at the - * requested point. (Many of the the tests assume that this is the - * case, especially for windows with upper left corner at (0,0).) So - * we just tell a harmless white lie here. - */ - - if (y == minY && wmPtr->y < minY) { - y = wmPtr->y; - } TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags); } } @@ -154,30 +137,28 @@ } - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)newFrame { - /* - * This method needs to be implemented in order for [NSWindow isZoomed] - * to give the correct answer. But it suffices to always validate - * every request. + * This method needs to be implemented in order for [NSWindow isZoomed] to + * give the correct answer. But it suffices to always validate every + * request. */ return newFrame; } - (NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize { - /* - * We don't need to change the proposed size, but we do need to - * implement this method. Otherwise the full screen window will - * be sized to the screen's visibleFrame, leaving black bands at - * the top and bottom. + * We don't need to change the proposed size, but we do need to implement + * this method. Otherwise the full screen window will be sized to the + * screen's visibleFrame, leaving black bands at the top and bottom. */ + return proposedSize; } - (void) windowEnteredFullScreen: (NSNotification *) notification { @@ -215,24 +196,19 @@ #endif TkWindow *winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { TkGenWMDestroyEvent((Tk_Window) winPtr); - if (_windowWithMouse == w) { - _windowWithMouse = nil; - [w release]; - } } /* - * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, - * so can always return NO from -windowShouldClose: for a Tk window. + * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so + * can always return NO from -windowShouldClose: for a Tk window. */ return (winPtr ? NO : YES); } - #ifdef TK_MAC_DEBUG_NOTIFICATIONS - (void) windowDragStart: (NSNotification *) notification { @@ -269,11 +245,10 @@ if (winPtr) { //Tk_UnmapWindow((Tk_Window) winPtr); } } - #endif /* TK_MAC_DEBUG_NOTIFICATIONS */ - (void) _setupWindowNotifications { @@ -315,10 +290,26 @@ { #ifdef TK_MAC_DEBUG_NOTIFICATIONS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); #endif [NSApp tkCheckPasteboard]; + + /* + * When the application is activated with Command-Tab it will create a + * zombie window for every Tk window which has been withdrawn. So iterate + * through the list of windows and order out any withdrawn window. + */ + + for (NSWindow *win in [NSApp windows]) { + TkWindow *winPtr = TkMacOSXGetTkWindow(win); + if (!winPtr || !winPtr->wmInfoPtr) { + continue; + } + if (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) { + [win orderOut:nil]; + } + } } - (void) applicationDeactivate: (NSNotification *) notification { #ifdef TK_MAC_DEBUG_NOTIFICATIONS @@ -377,29 +368,29 @@ /* *---------------------------------------------------------------------- * * TkpAppIsDrawing -- * - * A widget display procedure can call this to determine whether it - * is being run inside of the drawRect method. This is needed for - * some tests, especially of the Text widget, which record data in - * a global Tcl variable and assume that display procedures will be - * run in a predictable sequence as Tcl idle tasks. + * A widget display procedure can call this to determine whether it is + * being run inside of the drawRect method. This is needed for some tests, + * especially of the Text widget, which record data in a global Tcl + * variable and assume that display procedures will be run in a + * predictable sequence as Tcl idle tasks. * * Results: * True only while running the drawRect method of a TKContentView; * * Side effects: * None * *---------------------------------------------------------------------- */ + MODULE_SCOPE Bool TkpAppIsDrawing(void) { return [NSApp isDrawing]; } - /* *---------------------------------------------------------------------- * * GenerateUpdates -- @@ -521,11 +512,13 @@ GenerateActivateEvents( TkWindow *winPtr, int activeFlag) { TkGenerateActivateEvents(winPtr, activeFlag); - TkMacOSXGenerateFocusEvent(winPtr, activeFlag); + if (activeFlag || ![NSApp isActive]) { + TkMacOSXGenerateFocusEvent(winPtr, activeFlag); + } return true; } /* *---------------------------------------------------------------------- @@ -678,21 +671,18 @@ if (Tk_IsTopLevel(winPtr)) { wmPtr = winPtr->wmInfoPtr; if (flags & TK_LOCATION_CHANGED) { wmPtr->x = x; wmPtr->y = y; - //wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); } if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) && ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) { if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) { - /* * Don't set external width, since the user didn't change it * from what the widgets asked for. */ - } else if (wmPtr->gridWin != NULL) { wmPtr->width = wmPtr->reqGridWidth + (width - winPtr->reqWidth)/wmPtr->widthInc; if (wmPtr->width < 0) { wmPtr->width = 0; @@ -700,16 +690,14 @@ } else { wmPtr->width = width; } if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) { - /* * Don't set external height, since the user didn't change it * from what the widgets asked for. */ - } else if (wmPtr->gridWin != NULL) { wmPtr->height = wmPtr->reqGridHeight + (height - winPtr->reqHeight)/wmPtr->heightInc; if (wmPtr->height < 0) { wmPtr->height = 0; @@ -720,11 +708,10 @@ wmPtr->configWidth = width; wmPtr->configHeight = height; } } - /* * Now set up the changes structure. Under X we wait for the * ConfigureNotify to set these values. On the Mac we know imediatly that * this is what we want - so we just set them. However, we need to make @@ -879,28 +866,58 @@ * normal Tk widgets which draw themselves as native widgets by using the * HITheme API. * */ -/*Restrict event processing to Expose events.*/ +/* + * Restrict event processing to Expose events. + */ + static Tk_RestrictAction ExposeRestrictProc( ClientData arg, XEvent *eventPtr) { return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg) ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } -/*Restrict event processing to ConfigureNotify events.*/ +/* + * Restrict event processing to ConfigureNotify events. + */ + static Tk_RestrictAction ConfigureRestrictProc( ClientData arg, XEvent *eventPtr) { return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } + +/* + * If a window gets mapped inside the drawRect method, this will be run as an + * idle task, after drawRect returns, to clean up the mess. + */ + +static void +RedisplayView( + ClientData clientdata) +{ + NSView *view = (NSView *) clientdata; + + /* + * Make sure that we are not trying to displaying a view that no longer + * exists. + */ + + for (NSWindow *w in [NSApp orderedWindows]) { + if ([w contentView] == view) { + [view setNeedsDisplay:YES]; + break; + } + } +} @implementation TKContentView(TKWindowEvent) - (void) drawRect: (NSRect) rect { @@ -912,12 +929,12 @@ if (winPtr) fprintf(stderr, "drawRect: drawing %s\n", Tk_PathName(winPtr)); #endif /* - * We do not allow recursive calls to drawRect, but we only log - * them on OSX > 10.13, where they should never happen. + * We do not allow recursive calls to drawRect, but we only log them on OSX + * > 10.13, where they should never happen. */ if ([NSApp isDrawing]) { if ([NSApp macMinorVersion] > 13) { TKLog(@"WARNING: a recursive call to drawRect was aborted."); @@ -943,10 +960,15 @@ HIShapeUnionWithRect(drawShape, &r); } [self generateExposeEvents:(HIShapeRef)drawShape]; CFRelease(drawShape); [NSApp setIsDrawing: NO]; + + if ([self needsRedisplay]) { + [self setNeedsRedisplay:NO]; + Tcl_DoWhenIdle(RedisplayView, self); + } #ifdef TK_MAC_DEBUG_DRAWING fprintf(stderr, "drawRect: done.\n"); #endif } @@ -968,13 +990,13 @@ unsigned int height=(unsigned int)newsize.height; 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. + * 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]; /* @@ -986,11 +1008,11 @@ /* * Generate and handle a ConfigureNotify event for the new size. */ TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height, - TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY); + TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY); oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg); Tk_RestrictEvents(oldProc, oldArg, &oldArg); /* * Now that Tk has configured all subwindows, create the clip regions. @@ -1074,20 +1096,19 @@ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} } } /* - * This method is called when a user changes between light and dark mode. - * The implementation here generates a Tk virtual event which can be bound - * to a function that redraws the window in an appropriate style. + * This method is called when a user changes between light and dark mode. The + * implementation here generates a Tk virtual event which can be bound to a + * function that redraws the window in an appropriate style. */ - (void) viewDidChangeEffectiveAppearance { XVirtualEvent event; int x, y; - NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]; NSWindow *w = [self window]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; if (!winPtr) { @@ -1104,25 +1125,21 @@ event.time = TkpGetMS(); XQueryPointer(NULL, winPtr->window, NULL, NULL, &event.x_root, &event.y_root, &x, &y, &event.state); Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y); event.same_screen = true; - if (osxMode == nil) { - event.name = Tk_GetUid("LightAqua"); - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); - return; - } - if ([osxMode isEqual:@"Dark"]) { - event.name = Tk_GetUid("DarkAqua"); - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); - return; - } + if (TkMacOSXInDarkMode(tkwin)) { + event.name = Tk_GetUid("DarkAqua"); + } else { + event.name = Tk_GetUid("LightAqua"); + } + Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); } /* - * This is no-op on 10.7 and up because Apple has removed this widget, - * but we are leaving it here for backwards compatibility. + * This is no-op on 10.7 and up because Apple has removed this widget, but we + * are leaving it here for backwards compatibility. */ - (void) tkToolbarButton: (id) sender { #ifdef TK_MAC_DEBUG_EVENTS Index: macosx/tkMacOSXWm.c ================================================================== --- macosx/tkMacOSXWm.c +++ macosx/tkMacOSXWm.c @@ -1,18 +1,17 @@ /* * tkMacOSXWm.c -- * * This module takes care of the interactions between a Tk-based * application and the window manager. Among other things, it implements - * the "wm" command and passes geometry information to the window - * manager. + * the "wm" command and passes geometry information to the window manager. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright (c) 2010 Kevin Walzer/WordTech Communications LLC. - * Copyright (c) 2017-2018 Marc Culler. + * Copyright (c) 2017-2019 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -52,11 +51,10 @@ | kWindowNoShadowAttribute | kWindowLiveResizeAttribute \ | kWindowOpaqueForEventsAttribute | kWindowIgnoreClicksAttribute \ | kWindowDoesNotCycleAttribute | tkWindowDoesNotHideAttribute \ | tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute \ | tkNonactivatingPanelAttribute | tkHUDWindowAttribute) - static const struct { const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs; int flags; NSUInteger styleMask; } macClassAttrs[] = { @@ -309,10 +307,12 @@ static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr); static int WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr, int objc, Tcl_Obj *const objv[]); static int WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr, int objc, Tcl_Obj *const objv[]); +static int WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr, + int objc, Tcl_Obj *const objv[]); static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr, NSWindow *macWindow, UInt64 oldAttributes, int oldFlags, int create, int initial); static void ApplyMasterOverrideChanges(TkWindow *winPtr, NSWindow *macWindow); @@ -320,10 +320,11 @@ int *minHeightPtr); static void GetMaxSize(TkWindow *winPtr, int *maxWidthPtr, int *maxHeightPtr); static void RemapWindows(TkWindow *winPtr, MacDrawable *parentWin); +static void RemoveTransient(TkWindow *winPtr); #pragma mark NSWindow(TKWm) @implementation NSWindow(TKWm) @@ -337,22 +338,16 @@ return [self convertScreenToBase:point]; } #else - (NSPoint) tkConvertPointToScreen: (NSPoint) point { - NSRect pointrect; - pointrect.origin = point; - pointrect.size.width = 0; - pointrect.size.height = 0; + NSRect pointrect = {point, {0,0}}; return [self convertRectToScreen:pointrect].origin; } - (NSPoint) tkConvertPointFromScreen: (NSPoint)point { - NSRect pointrect; - pointrect.origin = point; - pointrect.size.width = 0; - pointrect.size.height = 0; + NSRect pointrect = {point, {0,0}}; return [self convertRectFromScreen:pointrect].origin; } #endif @end @@ -388,15 +383,17 @@ * but does include it for normal windows. */ if ([self styleMask] & NSFullScreenWindowMask) { frameRect = [NSWindow frameRectForContentRect:NSZeroRect - styleMask:[self styleMask]]; + styleMask:[self styleMask]]; } else { frameRect = [self frameRectForContentRect:NSZeroRect]; } + WmInfo *wmPtr = winPtr->wmInfoPtr; + wmPtr->xInParent = -frameRect.origin.x; wmPtr->yInParent = frameRect.origin.y + frameRect.size.height; wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width; wmPtr->parentHeight = winPtr->changes.height + frameRect.size.height; } @@ -448,11 +445,11 @@ id result = [super retain]; const char *title = [[self title] UTF8String]; if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 1){ + if (DEBUG_ZOMBIES > 1) { fprintf(stderr, "Retained <%s>. Count is: %lu\n", title, [self retainCount]); } return result; } @@ -462,11 +459,11 @@ id result = [super autorelease]; const char *title = [[self title] UTF8String]; if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 1){ + if (DEBUG_ZOMBIES > 1) { fprintf(stderr, "Autoreleased <%s>. Count is %lu\n", title, [self retainCount]); } return result; } @@ -474,11 +471,11 @@ - (oneway void) release { const char *title = [[self title] UTF8String]; if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 1){ + if (DEBUG_ZOMBIES > 1) { fprintf(stderr, "Releasing <%s>. Count is %lu\n", title, [self retainCount]); } [super release]; } @@ -486,17 +483,16 @@ - (void) dealloc { const char *title = [[self title] UTF8String]; if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 0){ + if (DEBUG_ZOMBIES > 0) { fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]); } [super dealloc]; } - #endif @end #pragma mark - @@ -619,19 +615,20 @@ winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect windowFrame = [w frame]; NSRect contentFrame = [w frame]; - contentFrame.size.height = [[w contentView] frame].size.height; + + contentFrame.size.height = [[w contentView] frame].size.height; /* * For consistency with other platforms, points in the * title bar are not considered to be contained in the * window. */ if ((wmPtr->hints.initial_state == NormalState || - wmPtr->hints.initial_state == ZoomState)) { + wmPtr->hints.initial_state == ZoomState)) { if (NSMouseInRect(p, contentFrame, NO)) { return winPtr; } else if (NSMouseInRect(p, windowFrame, NO)) { return NULL; } @@ -666,23 +663,23 @@ wmPtr->winPtr = winPtr; wmPtr->reparent = None; wmPtr->titleUid = NULL; wmPtr->iconName = NULL; - wmPtr->master = None; + wmPtr->master = NULL; wmPtr->hints.flags = InputHint | StateHint; wmPtr->hints.input = True; wmPtr->hints.initial_state = NormalState; wmPtr->hints.icon_pixmap = None; wmPtr->hints.icon_window = None; wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0; wmPtr->hints.icon_mask = None; wmPtr->hints.window_group = None; wmPtr->leaderName = NULL; - wmPtr->masterWindowName = NULL; wmPtr->icon = NULL; wmPtr->iconFor = NULL; + wmPtr->transientPtr = NULL; wmPtr->sizeHintsFlags = 0; wmPtr->minWidth = wmPtr->minHeight = 1; wmPtr->maxWidth = 0; wmPtr->maxHeight = 0; wmPtr->gridWin = NULL; @@ -884,10 +881,16 @@ WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; if (wmPtr == NULL) { return; } + + /* + *If the dead window is a transient, remove it from the master's list. + */ + + RemoveTransient(winPtr); Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL); Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask, TopLevelEventProc, winPtr); if (wmPtr->hints.flags & IconPixmapHint) { Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); @@ -899,13 +902,10 @@ ckfree(wmPtr->iconName); } if (wmPtr->leaderName != NULL) { ckfree(wmPtr->leaderName); } - if (wmPtr->masterWindowName != NULL) { - ckfree(wmPtr->masterWindowName); - } if (wmPtr->icon != NULL) { wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; wmPtr2->iconFor = NULL; } if (wmPtr->iconFor != NULL) { @@ -913,11 +913,10 @@ wmPtr2->icon = NULL; wmPtr2->hints.flags &= ~IconWindowHint; } while (wmPtr->protPtr != NULL) { ProtocolHandler *protPtr = wmPtr->protPtr; - wmPtr->protPtr = protPtr->nextPtr; Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); } if (wmPtr->commandObj != NULL) { Tcl_DecrRefCount(wmPtr->commandObj); @@ -926,10 +925,33 @@ ckfree(wmPtr->clientMachine); } if (wmPtr->flags & WM_UPDATE_PENDING) { Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr); } + + /* + * If the dead window has a transient, remove references to it from + * the transient. + */ + + for (Transient *transientPtr = wmPtr->transientPtr; + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + TkWindow *winPtr2 = transientPtr->winPtr; + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + + if (masterPtr == winPtr) { + wmPtr2 = winPtr2->wmInfoPtr; + wmPtr2->master = NULL; + } + } + + while (wmPtr->transientPtr != NULL) { + Transient *transientPtr = wmPtr->transientPtr; + + wmPtr->transientPtr = transientPtr->nextPtr; + ckfree(transientPtr); + } /* * Delete the Mac window and remove it from the windowTable. The window * could be nil if the window was never mapped. However, we don't do this * for embedded windows, they don't go in the window list, and they do not @@ -936,12 +958,13 @@ * own their portPtr's. */ NSWindow *window = wmPtr->window; - if (window && !Tk_IsEmbedded(winPtr) ) { + if (window && !Tk_IsEmbedded(winPtr)) { NSWindow *parent = [window parentWindow]; + if (parent) { [parent removeChildWindow:window]; } #if DEBUG_ZOMBIES > 0 { @@ -963,36 +986,40 @@ /* Activate the highest window left on the screen. */ NSArray *windows = [NSApp orderedWindows]; for (id nswindow in windows) { TkWindow *winPtr2 = TkMacOSXGetTkWindow(nswindow); + if (winPtr2 && nswindow != window) { WmInfo *wmPtr = winPtr2->wmInfoPtr; - BOOL minimized = (wmPtr->hints.initial_state == IconicState || - wmPtr->hints.initial_state == WithdrawnState); + BOOL minimized = (wmPtr->hints.initial_state == IconicState + || wmPtr->hints.initial_state == WithdrawnState); + /* - * If no windows are left on the screen and the next - * window is iconified or withdrawn, we don't want to - * make it be the KeyWindow because that would cause - * it to be displayed on the screen. + * If no windows are left on the screen and the next window is + * iconified or withdrawn, we don't want to make it be the + * KeyWindow because that would cause it to be displayed on the + * screen. */ + if ([nswindow canBecomeKeyWindow] && !minimized) { [nswindow makeKeyAndOrderFront:NSApp]; break; } } } + /* * Process all window events immediately to force the closed window to * be deallocated. But don't do this for the root window as that is * unnecessary and can lead to segfaults. */ + if (winPtr->parentPtr) { - while (Tk_DoOneEvent(TK_WINDOW_EVENTS|TK_DONT_WAIT)) {} + while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {} } [NSApp _resetAutoreleasePool]; - #if DEBUG_ZOMBIES > 0 fprintf(stderr, "================= Pool dump ===================\n"); [NSAutoreleasePool showPools]; #endif } @@ -1088,11 +1115,11 @@ if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); return TCL_ERROR; } if (objc == 2) { - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(wmTracing)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wmTracing != 0)); return TCL_OK; } return Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing); } @@ -1224,14 +1251,14 @@ } if (objc == 3) { if (wmPtr->sizeHintsFlags & PAspect) { Tcl_Obj *results[4]; - results[0] = Tcl_NewIntObj(wmPtr->minAspect.x); - results[1] = Tcl_NewIntObj(wmPtr->minAspect.y); - results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x); - results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y); + results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x); + results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y); + results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x); + results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y); Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); } return TCL_OK; } if (*Tcl_GetString(objv[3]) == '\0') { @@ -1427,27 +1454,27 @@ switch (attribute) { case WMATT_ALPHA: result = Tcl_NewDoubleObj([macWindow alphaValue]); break; case WMATT_FULLSCREEN: - result = Tcl_NewBooleanObj(wmPtr->flags & WM_FULLSCREEN); + result = Tcl_NewWideIntObj((wmPtr->flags & WM_FULLSCREEN) != 0); break; case WMATT_MODIFIED: - result = Tcl_NewBooleanObj([macWindow isDocumentEdited]); + result = Tcl_NewWideIntObj([macWindow isDocumentEdited] != 0); break; case WMATT_NOTIFY: - result = Tcl_NewBooleanObj(tkMacOSXWmAttrNotifyVal); + result = Tcl_NewWideIntObj(tkMacOSXWmAttrNotifyVal != 0); break; case WMATT_TITLEPATH: result = Tcl_NewStringObj([[macWindow representedFilename] UTF8String], -1); break; case WMATT_TOPMOST: - result = Tcl_NewBooleanObj(wmPtr->flags & WM_TOPMOST); + result = Tcl_NewWideIntObj((wmPtr->flags & WM_TOPMOST) != 0); break; case WMATT_TRANSPARENT: - result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT); + result = Tcl_NewWideIntObj((wmPtr->flags & WM_TRANSPARENT) != 0); break; case WMATT_TYPE: result = Tcl_NewStringObj("unsupported", -1); break; case _WMATT_LAST_ATTRIBUTE: @@ -1501,11 +1528,11 @@ Tcl_NewStringObj(WmAttributeNames[attribute], -1)); Tcl_ListObjAppendElement(NULL, result, WmGetAttribute(winPtr, macWindow, attribute)); } Tcl_SetObjResult(interp, result); - } else if (objc == 4) { /* wm attributes $win -attribute */ + } else if (objc == 4) { /* wm attributes $win -attribute */ if (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames, sizeof(char *), "attribute", 0, &attribute) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, attribute)); @@ -1710,11 +1737,11 @@ if (wmPtr->commandObj != NULL) { Tcl_SetObjResult(interp, wmPtr->commandObj); } return TCL_OK; } - if (Tcl_GetString(objv[3])[0] == 0) { + if (*Tcl_GetString(objv[3]) == '\0') { if (wmPtr->commandObj != NULL) { Tcl_DecrRefCount(wmPtr->commandObj); wmPtr->commandObj = NULL; } return TCL_OK; @@ -1784,10 +1811,31 @@ TkMacOSXApplyWindowAttributes(winPtr, win); [win orderFront:nil]; if (wmPtr->icon) { Tk_UnmapWindow((Tk_Window)wmPtr->icon); } + + /* + * If this window has a transient, the transient must also be deiconified if + * it was withdrawn by the master. + */ + + for (Transient *transientPtr = wmPtr->transientPtr; + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + TkWindow *winPtr2 = transientPtr->winPtr; + WmInfo *wmPtr2 = winPtr2->wmInfoPtr; + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + + if (masterPtr == winPtr) { + if ((wmPtr2->hints.initial_state == WithdrawnState) && + ((transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) { + TkpWmSetState(winPtr2, NormalState); + transientPtr->flags &= ~WITHDRAWN_BY_MASTER; + } + } + } + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2056,14 +2104,14 @@ } if (objc == 3) { if (wmPtr->sizeHintsFlags & PBaseSize) { Tcl_Obj *results[4]; - results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth); - results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight); - results[2] = Tcl_NewIntObj(wmPtr->widthInc); - results[3] = Tcl_NewIntObj(wmPtr->heightInc); + results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth); + results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight); + results[2] = Tcl_NewWideIntObj(wmPtr->widthInc); + results[3] = Tcl_NewWideIntObj(wmPtr->heightInc); Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); } return TCL_OK; } if (*Tcl_GetString(objv[3]) == '\0') { @@ -2283,11 +2331,11 @@ "can't iconify \"%s\": override-redirect flag is set", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT", NULL); return TCL_ERROR; - } else if (wmPtr->master != None) { + } else if (wmPtr->master != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't iconify \"%s\": it is a transient", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL); return TCL_ERROR; } else if (wmPtr->iconFor != NULL) { @@ -2306,10 +2354,27 @@ TkpWmSetState(winPtr, IconicState); if (wmPtr->icon) { Tk_MapWindow((Tk_Window)wmPtr->icon); } + + /* + * If this window has a transient the transient must be withdrawn when + * the master is iconified. + */ + + for (Transient *transientPtr = wmPtr->transientPtr; + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + TkWindow *winPtr2 = transientPtr->winPtr; + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + if (masterPtr == winPtr && + winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { + TkpWmSetState(winPtr2, WithdrawnState); + transientPtr->flags |= WITHDRAWN_BY_MASTER; + } + } + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2456,30 +2521,39 @@ Tcl_WrongNumArgs(interp, 2, objv, "window ?-default? image1 ?image2 ...?"); return TCL_ERROR; } - /*Parse args.*/ + /* + * Parse args. + */ + if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) { isDefault = 1; if (objc == 4) { Tcl_WrongNumArgs(interp, 2, objv, - "window ?-default? image1 ?image2 ...?"); + "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.*/ + /* + * 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 { + } else { icon = Tcl_GetString(objv[3]); } - /*Get image and convert to NSImage that can be displayed as icon.*/ + /* + * Get image and convert to NSImage that can be displayed as icon. + */ + tk_icon = Tk_GetImage(interp, tkwin, icon, NULL, NULL); if (tk_icon == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use \"%s\" as iconphoto: not a photo image", icon)); @@ -2487,11 +2561,12 @@ return TCL_ERROR; } NSImage *newIcon; Tk_SizeOfImage(tk_icon, &width, &height); - newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, width, height); + newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, + width, height); Tk_FreeImage(tk_icon); if (newIcon == NULL) { return TCL_ERROR; } [NSApp setApplicationIconImage: newIcon]; @@ -2533,22 +2608,22 @@ if (objc == 3) { if (wmPtr->hints.flags & IconPositionHint) { Tcl_Obj *results[2]; - results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x); - results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y); + results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x); + results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); } return TCL_OK; } if (*Tcl_GetString(objv[3]) == '\0') { wmPtr->hints.flags &= ~IconPositionHint; } else { if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){ + || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) { return TCL_ERROR; } wmPtr->hints.icon_x = x; wmPtr->hints.icon_y = y; wmPtr->hints.flags |= IconPositionHint; @@ -2643,18 +2718,17 @@ wmPtr->hints.icon_window = Tk_WindowId(tkwin2); wmPtr->hints.flags |= IconWindowHint; wmPtr->icon = tkwin2; wmPtr2->iconFor = (Tk_Window) winPtr; if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { - /* * If the window is in normal or zoomed state, the icon should be * unmapped. */ if (wmPtr->hints.initial_state == NormalState || - wmPtr->hints.initial_state == ZoomState) { + wmPtr->hints.initial_state == ZoomState) { Tk_UnmapWindow(tkwin2); } } } return TCL_OK; @@ -2705,12 +2779,10 @@ TkWmNewWindow(winPtr); if (winPtr->window == None) { Tk_MakeWindowExist((Tk_Window) winPtr); macWin = (MacDrawable *) winPtr->window; } - TkWmMapWindow(winPtr); - Tk_UnmapWindow(frameWin); } wmPtr = winPtr->wmInfoPtr; winPtr->flags &= ~TK_MAPPED; macWin->toplevel->referenceCount--; macWin->toplevel = macWin; @@ -2717,10 +2789,11 @@ macWin->toplevel->referenceCount++; RemapWindows(winPtr, macWin); winPtr->flags |= (TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); TkMapTopFrame(frameWin); + TkWmMapWindow(winPtr); } else if (Tk_IsTopLevel(frameWin)) { /* Already managed by wm - ignore it */ } return TCL_OK; } @@ -2760,12 +2833,12 @@ if (objc == 3) { Tcl_Obj *results[2]; GetMaxSize(winPtr, &width, &height); - results[0] = Tcl_NewIntObj(width); - results[1] = Tcl_NewIntObj(height); + results[0] = Tcl_NewWideIntObj(width); + results[1] = Tcl_NewWideIntObj(height); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); return TCL_OK; } if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) @@ -2814,12 +2887,12 @@ if (objc == 3) { Tcl_Obj *results[2]; GetMinSize(winPtr, &width, &height); - results[0] = Tcl_NewIntObj(width); - results[1] = Tcl_NewIntObj(height); + results[0] = Tcl_NewWideIntObj(width); + results[1] = Tcl_NewWideIntObj(height); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); return TCL_OK; } if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) @@ -2866,12 +2939,12 @@ Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); return TCL_ERROR; } if (objc == 3) { - Tcl_SetObjResult(interp, Tcl_NewBooleanObj( - Tk_Attributes((Tk_Window) winPtr)->override_redirect)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( + Tk_Attributes((Tk_Window) winPtr)->override_redirect != 0)); return TCL_OK; } if (Tcl_GetBooleanFromObj(interp, objv[3], &flag) != TCL_OK) { return TCL_ERROR; @@ -3021,11 +3094,11 @@ * Delete any current protocol handler, then create a new one with the * specified command, unless the command is empty. */ for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; - prevPtr = protPtr, protPtr = protPtr->nextPtr) { + prevPtr = protPtr, protPtr = protPtr->nextPtr) { if (protPtr->protocol == protocol) { if (prevPtr == NULL) { wmPtr->protPtr = protPtr->nextPtr; } else { prevPtr->nextPtr = protPtr->nextPtr; @@ -3085,12 +3158,14 @@ } if (objc == 3) { Tcl_Obj *results[2]; - results[0] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)); - results[1] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)); + results[0] = Tcl_NewWideIntObj( + (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) == 0); + results[1] = Tcl_NewWideIntObj( + (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) == 0); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); return TCL_OK; } if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK) @@ -3311,11 +3386,11 @@ if (index == OPT_ISABOVE) { result = index1 > index2; } else { /* OPT_ISBELOW */ result = index1 < index2; } - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result != 0)); return TCL_OK; } } /* @@ -3374,39 +3449,45 @@ if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings, sizeof(char *), "argument", 0, &index) != TCL_OK) { return TCL_ERROR; } - if (index == OPT_NORMAL) { + switch (index) { + case OPT_NORMAL: TkpWmSetState(winPtr, NormalState); /* * This varies from 'wm deiconify' because it does not force the * window to be raised and receive focus */ - } else if (index == OPT_ICONIC) { + + break; + case OPT_ICONIC: if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't iconify \"%s\": override-redirect flag is set", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "OVERRIDE_REDIRECT", NULL); return TCL_ERROR; } - if (wmPtr->master != None) { + if (wmPtr->master != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't iconify \"%s\": it is a transient", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT", NULL); return TCL_ERROR; } TkpWmSetState(winPtr, IconicState); - } else if (index == OPT_WITHDRAWN) { + break; + case OPT_WITHDRAWN: TkpWmSetState(winPtr, WithdrawnState); - } else { /* OPT_ZOOMED */ + break; + default: /* OPT_ZOOMED */ TkpWmSetState(winPtr, ZoomState); + break; } } else if (wmPtr->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("icon", -1)); } else { if (wmPtr->hints.initial_state == NormalState || @@ -3505,38 +3586,33 @@ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; Tk_Window master; + TkWindow *masterPtr, *w; WmInfo *wmPtr2; - char *masterWindowName; - int length; + Transient *transient; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); return TCL_ERROR; } if (objc == 3) { - if (wmPtr->master != None) { + if (wmPtr->master != NULL) { Tcl_SetObjResult(interp, - Tcl_NewStringObj(wmPtr->masterWindowName, -1)); + Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1)); } return TCL_OK; } - if (Tcl_GetString(objv[3])[0] == '\0') { - wmPtr->master = None; - if (wmPtr->masterWindowName != NULL) { - ckfree(wmPtr->masterWindowName); - } - wmPtr->masterWindowName = NULL; + if (*Tcl_GetString(objv[3]) == '\0') { + RemoveTransient(winPtr); } else { if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) { return TCL_ERROR; } - TkWindow* masterPtr = (TkWindow*) master; + masterPtr = (TkWindow*) master; while (!Tk_TopWinHierarchy(masterPtr)) { - /* * Ensure that the master window is actually a Tk toplevel. */ masterPtr = masterPtr->parentPtr; @@ -3550,38 +3626,122 @@ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL); return TCL_ERROR; } wmPtr2 = masterPtr->wmInfoPtr; - /* Under some circumstances, wmPtr2 is NULL here */ + + /* + * Under some circumstances, wmPtr2 is NULL here. + */ + if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't make \"%s\" a master: it is an icon for %s", Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor))); Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL); return TCL_ERROR; } - if (masterPtr == winPtr) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't make \"%s\" its own master", Tk_PathName(winPtr))); - Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); - return TCL_ERROR; - } - - wmPtr->master = Tk_WindowId(masterPtr); - masterWindowName = masterPtr->pathName; - length = strlen(masterWindowName); - if (wmPtr->masterWindowName != NULL) { - ckfree(wmPtr->masterWindowName); - } - wmPtr->masterWindowName = ckalloc(length+1); - strcpy(wmPtr->masterWindowName, masterWindowName); + for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL; + w = (TkWindow *)w->wmInfoPtr->master) { + if (w == winPtr) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "setting \"%s\" as master creates a transient/master cycle", + Tk_PathName(masterPtr))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); + return TCL_ERROR; + } + } + + /* + * Add the transient to the master's list, if it not already there. + */ + + for (transient = wmPtr2->transientPtr; + transient != NULL && transient->winPtr != winPtr; + transient = transient->nextPtr) {} + if (transient == NULL) { + transient = ckalloc(sizeof(Transient)); + transient->winPtr = winPtr; + transient->flags = 0; + transient->nextPtr = wmPtr2->transientPtr; + wmPtr2->transientPtr = transient; + } + + /* + * If the master is withdrawn or iconic then withdraw the transient. + */ + + if ((wmPtr2->hints.initial_state == WithdrawnState || + wmPtr2->hints.initial_state == IconicState) && + wmPtr->hints.initial_state != WithdrawnState) { + TkpWmSetState(winPtr, WithdrawnState); + transient->flags |= WITHDRAWN_BY_MASTER; + } + + wmPtr->master = (Tk_Window) masterPtr; } ApplyMasterOverrideChanges(winPtr, NULL); return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * + * RemoveTransient -- + * + * Clears the transient's master record and removes the transient from the + * master's list. + * + * Results: + * None + * + * Side effects: + * References to a master are removed from the transient's wmInfo + * structure and references to the transient are removed from its master's + * wmInfo. + * + *---------------------------------------------------------------------- + */ + +static void +RemoveTransient( + TkWindow *winPtr) +{ + WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; + TkWindow *masterPtr; + Transient *transPtr, *temp; + + if (wmPtr == NULL || wmPtr->master == NULL) { + return; + } + masterPtr = (TkWindow *) wmPtr->master; + wmPtr2 = masterPtr->wmInfoPtr; + if (wmPtr2 == NULL) { + return; + } + wmPtr->master = NULL; + transPtr = wmPtr2->transientPtr; + while (transPtr != NULL) { + if (transPtr->winPtr != winPtr) { + break; + } + temp = transPtr->nextPtr; + ckfree(transPtr); + transPtr = temp; + } + wmPtr2->transientPtr = transPtr; + while (transPtr != NULL) { + if (transPtr->nextPtr && transPtr->nextPtr->winPtr == winPtr) { + temp = transPtr->nextPtr; + transPtr->nextPtr = temp->nextPtr; + ckfree(temp); + } else { + transPtr = transPtr->nextPtr; + } + } +} /* *---------------------------------------------------------------------- * * WmWithdrawCmd -- @@ -3618,21 +3778,39 @@ "can't withdraw %s: it is an icon for %s", Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor))); Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL); return TCL_ERROR; } + TkpWmSetState(winPtr, WithdrawnState); + NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); [win orderOut:nil]; [win setExcludedFromWindowsMenu:YES]; + + /* + * If this window has a transient, the transient must also be withdrawn. + */ + + for (Transient *transientPtr = wmPtr->transientPtr; + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + TkWindow *winPtr2 = transientPtr->winPtr; + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + + if (masterPtr == winPtr && + winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { + TkpWmSetState(winPtr2, WithdrawnState); + transientPtr->flags |= WITHDRAWN_BY_MASTER; + } + } return TCL_OK; } - + /* - * Invoked by those wm subcommands that affect geometry. - * Schedules a geometry update. + * Invoked by those wm subcommands that affect geometry. Schedules a geometry + * update. */ static void WmUpdateGeom( WmInfo *wmPtr, @@ -3715,18 +3893,17 @@ return; } /* * If gridding was previously off, then forget about any window size - * requests made by the user or via "wm geometry": these are in pixel - * units and there's no easy way to translate them to grid units since the - * new requested size of the top-level window in pixels may not yet have - * been registered yet (it may filter up the hierarchy in DoWhenIdle - * handlers). However, if the window has never been mapped yet then just - * leave the window size alone: assume that it is intended to be in grid - * units but just happened to have been specified before this procedure - * was called. + * requests made by the user or via "wm geometry": these are in pixel units + * and there's no easy way to translate them to grid units since the new + * requested size of the top-level window in pixels may not yet have been + * registered yet (it may filter up the hierarchy in DoWhenIdle handlers). + * However, if the window has never been mapped yet then just leave the + * window size alone: assume that it is intended to be in grid units but + * just happened to have been specified before this procedure was called. */ if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) { wmPtr->width = -1; wmPtr->height = -1; @@ -4243,23 +4420,25 @@ wmPtr->width = width; wmPtr->height = height; if (flags & WM_NEGATIVE_X) { int borderwidth = wmPtr->parentWidth - winPtr->changes.width; int newWidth = width == -1 ? winPtr->changes.width : width; + x = (x == -1) ? - wmPtr->x + winPtr->changes.width - newWidth : - wmPtr->vRootWidth - x - newWidth - borderwidth; + wmPtr->x + winPtr->changes.width - newWidth : + wmPtr->vRootWidth - x - newWidth - borderwidth; } if (x == -1) { x = wmPtr->x; } if (flags & WM_NEGATIVE_Y) { int borderheight = wmPtr->parentHeight - winPtr->changes.height; int newHeight = height == -1 ? winPtr->changes.height : height; + y = (y == -1) ? - wmPtr->y + winPtr->changes.height - newHeight : - wmPtr->vRootHeight - y - newHeight - borderheight; + wmPtr->y + winPtr->changes.height - newHeight : + wmPtr->vRootHeight - y - newHeight - borderheight; } if (y == -1) { y = wmPtr->y; } if (wmPtr->flags & WM_FULLSCREEN) { @@ -4382,12 +4561,11 @@ * the top-most window covering that point, if there exists such a window * in this application. * * Results: * The return result is either a token for the window corresponding to - * rootX and rootY, or else NULL to indicate that there is no such - * window. + * rootX and rootY, or else NULL to indicate that there is no such window. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -4732,11 +4910,10 @@ Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window"); } wmPtr->x = x; wmPtr->y = y; wmPtr->flags |= WM_MOVE_PENDING; - // wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) { wmPtr->sizeHintsFlags |= USPosition; wmPtr->flags |= WM_UPDATE_SIZE_HINTS; } @@ -4788,45 +4965,49 @@ int otherNumber = 0; /* 0 will be used when otherPtr is NULL. */ /* * If the Tk windows has no drawable, or is withdrawn do nothing. */ + if (winPtr->window == None || - wmPtr == NULL || - wmPtr->hints.initial_state == WithdrawnState) { + wmPtr == NULL || + wmPtr->hints.initial_state == WithdrawnState) { return; } macWindow = TkMacOSXDrawableWindow(winPtr->window); if (macWindow == nil) { return; } if (otherPtr) { /* - * When otherPtr is non-NULL, if the other window has no - * drawable or is withdrawn, do nothing. + * When otherPtr is non-NULL, if the other window has no drawable or is + * withdrawn, do nothing. */ + WmInfo *otherWmPtr = otherPtr->wmInfoPtr; if (winPtr->window == None || - otherWmPtr == NULL || - otherWmPtr->hints.initial_state == WithdrawnState) { - return; + otherWmPtr == NULL || + otherWmPtr->hints.initial_state == WithdrawnState) { + return; } otherMacWindow = TkMacOSXDrawableWindow(otherPtr->window); if (otherMacWindow == nil) { return; - } else { - /* - * If the other window is OK, get its number. - */ - otherNumber = [otherMacWindow windowNumber]; } + + /* + * If the other window is OK, get its number. + */ + + otherNumber = [otherMacWindow windowNumber]; } /* - * Just let the Mac window manager deal with all the subtleties - * of keeping track of off-screen windows, etc. + * Just let the Mac window manager deal with all the subtleties of keeping + * track of off-screen windows, etc. */ + [macWindow orderWindow:macAboveBelow relativeTo:otherNumber]; } /* *---------------------------------------------------------------------- @@ -5021,12 +5202,12 @@ * * InitialWindowBounds -- * * This function calculates the initial bounds for a new Mac toplevel * window. Unless the geometry is specified by the user this code will - * auto place the windows in a cascade diagonially across the main - * monitor of the Mac. + * auto place the windows in a cascade diagonially across the main monitor + * of the Mac. * * Results: * Window bounds. * * Side effects: @@ -5169,18 +5350,18 @@ * None. * *---------------------------------------------------------------------- */ -Window +Tk_Window TkGetTransientMaster( TkWindow *winPtr) { if (winPtr->wmInfoPtr != NULL) { - return winPtr->wmInfoPtr->master; + return (Tk_Window)winPtr->wmInfoPtr->master; } - return None; + return NULL; } /* *---------------------------------------------------------------------- * @@ -5263,11 +5444,10 @@ TkWindow *winPtr) { NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window); return [macWindow isZoomed]; } - /* *---------------------------------------------------------------------- * * TkMacOSXZoomToplevel -- @@ -5343,24 +5523,23 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const subcmds[] = { - "style", "tabbingid", NULL + "style", "tabbingid", "appearance", "isdark", NULL }; enum SubCmds { - TKMWS_STYLE, TKMWS_TABID + TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE, TKMWS_ISDARK }; Tk_Window tkwin = clientData; TkWindow *winPtr; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); return TCL_ERROR; } - winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); if (winPtr == NULL) { return TCL_ERROR; @@ -5374,30 +5553,58 @@ if (Tcl_GetIndexFromObjStruct(interp, objv[1], subcmds, sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - if (((enum SubCmds) index) == TKMWS_STYLE) { + switch((enum SubCmds) index) { + case TKMWS_STYLE: if ((objc < 3) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?"); return TCL_ERROR; } return WmWinStyle(interp, winPtr, objc, objv); - } else if (((enum SubCmds) index) == TKMWS_TABID) { + case TKMWS_TABID: if ([NSApp macMinorVersion] < 12) { - Tcl_AddErrorInfo(interp, - "\n (TabbingIdentifiers only exist on OSX 10.12 or later)"); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Tabbing identifiers did not exist until OSX 10.12.", -1)); + Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL); return TCL_ERROR; } if ((objc < 3) || (objc > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "tabbingid window ?newid?"); return TCL_ERROR; } return WmWinTabbingId(interp, winPtr, objc, objv); + case TKMWS_APPEARANCE: + if ([NSApp macMinorVersion] < 9) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Window appearances did not exist until OSX 10.9.", -1)); + Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL); + return TCL_ERROR; + } + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?appearancename?"); + return TCL_ERROR; + } + if (objc == 4 && [NSApp macMinorVersion] < 14) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Window appearances cannot be changed before OSX 10.14.", + -1)); + Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL); + return TCL_ERROR; + } + return WmWinAppearance(interp, winPtr, objc, objv); + case TKMWS_ISDARK: + if ((objc != 3)) { + Tcl_WrongNumArgs(interp, 2, objv, "isdark window"); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TkMacOSXInDarkMode(tkwin))); + return TCL_OK; + default: + return TCL_ERROR; } - /* won't be reached */ - return TCL_ERROR; } /* *---------------------------------------------------------------------- * @@ -5587,12 +5794,13 @@ * WmWinTabbingId -- * * This procedure is invoked to process the * "::tk::unsupported::MacWindowStyle tabbingid" subcommand. The command * allows you to get or set the tabbingIdentifier for the NSWindow - * associated with a Tk Window. The syntax is: - * tk::unsupported::MacWindowStyle tabbingid window ?newId? + * associated with a Tk Window. The syntax is: + * + * tk::unsupported::MacWindowStyle tabbingid window ?newId? * * Results: * Returns the tabbingIdentifier of the window prior to calling this * function. If the optional newId argument is omitted, the window's * tabbingIdentifier is not changed. @@ -5601,11 +5809,10 @@ * Windows may only be grouped together as tabs if they all have the same * tabbingIdentifier. In particular, by giving a window a unique * tabbingIdentifier one can prevent it from becoming a tab in any other * window. Note, however, that changing the tabbingIdentifier of a window * which is already a tab does not cause it to become a separate window. - * * *---------------------------------------------------------------------- */ static int @@ -5639,18 +5846,123 @@ * If the tabbingIdentifier of a tab is changed we also turn it into a * separate window so we don't violate the rule that all tabs in the * same frame must have the same tabbingIdentifier. */ - if ([idString compare:newIdString] != NSOrderedSame && [win tab]) { + if ([idString compare:newIdString] != NSOrderedSame +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101200 + && [win tab] +#endif + ) { [win moveTabToNewWindow:nil]; } return TCL_OK; } #endif return TCL_ERROR; } + +/* + *---------------------------------------------------------------------- + * + * WmWinAppearance -- + * + * This procedure is invoked to process the + * "::tk::unsupported::MacWindowStyle appearance" subcommand. The command + * allows you to get or set the appearance for the NSWindow associated + * with a Tk Window. The syntax is: + * + * tk::unsupported::MacWindowStyle tabbingid window ?newAppearance? + * + * Allowed appearance names are "aqua", "darkaqua", and "auto". + * + * Results: + * Returns the appearance setting of the window prior to calling this + * function. + * + * Side effects: + * The underlying NSWindow's appearance property is set to the specified + * value if the optional newAppearance argument is supplied. Otherwise the + * window's appearance property is not changed. If the appearance is set + * to aqua or darkaqua then the window will use the associated + * NSAppearance even if the user has selected a different appearance with + * the system preferences. If it is set to auto then the appearance + * property is set to nil, meaning that the preferences will determine the + * appearance. + * + *---------------------------------------------------------------------- + */ + +static int +WmWinAppearance( + Tcl_Interp *interp, /* Current interpreter. */ + TkWindow *winPtr, /* Window to be manipulated. */ + int objc, /* Number of arguments. */ + Tcl_Obj * const objv[]) /* Argument objects. */ +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 + static const char *const appearanceStrings[] = { + "aqua", "darkaqua", "auto", NULL + }; + enum appearances { + APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO + }; + Tcl_Obj *result = NULL; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + NSAppearanceName appearance; +#else + NSString *appearance; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + const char *resultString = "unrecognized"; + NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); + if (win) { + appearance = win.appearance.name; + if (appearance == nil) { + resultString = appearanceStrings[APPEARANCE_AUTO]; + } else if (appearance == NSAppearanceNameAqua) { + resultString = appearanceStrings[APPEARANCE_AQUA]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } else if (@available(macOS 10.14, *)) { + if (appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } + result = Tcl_NewStringObj(resultString, strlen(resultString)); + } + if (result == NULL) { + Tcl_Panic("Failed to read appearance name."); + } + if (objc == 4) { + int index; + if (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings, + sizeof(char *), "appearancename", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum appearances) index) { + case APPEARANCE_AQUA: + win.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameAqua]; + break; + case APPEARANCE_DARKAQUA: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if (@available(macOS 10.14, *)) { + win.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameDarkAqua]; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + break; + default: + win.appearance = nil; + } + } + Tcl_SetObjResult(interp, result); + return TCL_OK; +#else // MAC_OS_X_VERSION_MAX_ALLOWED > 1090 + return TCL_ERROR; +#endif +} /* *---------------------------------------------------------------------- * * TkpMakeMenuWindow -- @@ -5719,12 +6031,12 @@ } macWin = (MacDrawable *) winPtr->window; /* - * If this is embedded, make sure its container's toplevel exists, - * then return... + * If this is embedded, make sure its container's toplevel exists, then + * return... */ if (Tk_IsEmbedded(winPtr)) { TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); @@ -5749,12 +6061,12 @@ * TODO: Here we should handle out of process embedding. */ } /* - * If this is an override-redirect window, the NSWindow is created - * first as a document window then converted to a simple window. + * If this is an override-redirect window, the NSWindow is created first as + * a document window then converted to a simple window. */ if (overrideRedirect) { wmPtr->macClass = kDocumentWindowClass; } @@ -5804,30 +6116,31 @@ [(NSPanel*)window setFloatingPanel:YES]; } if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) && !(styleMask & NSDocModalWindowMask)) { /* - * Workaround for [Bug 2824538]: Textured windows are draggable - * from opaque content. + * Workaround for [Bug 2824538]: Textured windows are draggable from + * opaque content. */ [window setMovableByWindowBackground:NO]; } [window setDocumentEdited:NO]; wmPtr->window = window; macWin->view = window.contentView; TkMacOSXApplyWindowAttributes(winPtr, window); NSRect geometry = InitialWindowBounds(winPtr, window); - geometry.size.width += structureRect.size.width; + geometry.size.width += structureRect.size.width; geometry.size.height += structureRect.size.height; geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y + geometry.size.height); [window setFrame:geometry display:YES]; TkMacOSXRegisterOffScreenWindow((Window) macWin, window); macWin->flags |= TK_HOST_EXISTS; if (overrideRedirect) { XSetWindowAttributes atts; + atts.override_redirect = True; Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts); ApplyMasterOverrideChanges(winPtr, NULL); } } @@ -5835,13 +6148,13 @@ /* *---------------------------------------------------------------------- * * TkpDisplayWindow -- * - * Mark the contentView of this window as needing display so the - * window will be drawn by the window manager. If this is called - * within the drawRect method, do nothing. + * Mark the contentView of this window as needing display so the window + * will be drawn by the window manager. If this is called within the + * drawRect method, do nothing. * * Results: * None. * * Side effects: @@ -5851,23 +6164,24 @@ */ MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin) { if (![NSApp isDrawing]) { - TkWindow *winPtr = (TkWindow*)tkwin; + TkWindow *winPtr = (TkWindow *) tkwin; NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); + [[w contentView] setNeedsDisplay: YES]; } } /* *---------------------------------------------------------------------- * * TkMacOSXRegisterOffScreenWindow -- * - * This function adds the passed in Off Screen Port to the hash table - * that maps Mac windows to root X windows. + * This function adds the passed in Off Screen Port to the hash table that + * maps Mac windows to root X windows. * * Results: * None. * * Side effects: @@ -6219,12 +6533,14 @@ /* *---------------------------------------------------------------------- * * TkpChangeFocus -- * - * This procedure is a stub on the Mac because we always own the focus if - * we are a front most application. + * This function is called when Tk moves focus from one window to another. + * It should be passed a non-embedded TopLevel. That toplevel gets raised + * to the top of the Tk stacking order and the associated NSWindow is + * ordered Front. * * Results: * The return value is the serial number of the command that changed the * focus. It may be needed by the caller to filter out focus change * events that were queued before the command. If the procedure doesn't @@ -6245,17 +6561,18 @@ { if (winPtr->atts.override_redirect) { return 0; } - if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) ){ + if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) { NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); + TkWmRestackToplevel(winPtr, Above, NULL); - if (force ) { + if (force) { [NSApp activateIgnoringOtherApps:YES]; } - if ( win && [win canBecomeKeyWindow] ) { + if (win && [win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; } } /* @@ -6410,12 +6727,13 @@ TkMacOSXApplyWindowAttributes( TkWindow *winPtr, NSWindow *macWindow) { WmInfo *wmPtr = winPtr->wmInfoPtr; + ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1); - if (wmPtr->master != None || winPtr->atts.override_redirect) { + if (wmPtr->master != NULL || winPtr->atts.override_redirect) { ApplyMasterOverrideChanges(winPtr, macWindow); } } /* @@ -6449,22 +6767,20 @@ wmPtr->macClass); if (changedAttributes || wmPtr->flags != oldFlags || initial) { if (!macWindow) { if (winPtr->window == None) { - if (create) { - Tk_MakeWindowExist((Tk_Window) winPtr); - } else { + if (!create) { return; } + Tk_MakeWindowExist((Tk_Window) winPtr); } if (!TkMacOSXHostToplevelExists(winPtr)) { - if (create) { - TkMacOSXMakeRealWindowExist(winPtr); - } else { + if (!create) { return; } + TkMacOSXMakeRealWindowExist(winPtr); } macWindow = TkMacOSXDrawableWindow(winPtr->window); } if ((changedAttributes & kWindowCloseBoxAttribute) || initial) { [[macWindow standardWindowButton:NSWindowCloseButton] @@ -6497,10 +6813,11 @@ [macWindow setShowsToolbarButton: !!(newAttributes & kWindowToolbarButtonAttribute)]; if ((newAttributes & kWindowToolbarButtonAttribute) && ![macWindow toolbar]) { NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""]; + [toolbar setVisible:NO]; [macWindow setToolbar:toolbar]; [toolbar release]; NSCell *toolbarButtonCell = [[macWindow standardWindowButton: NSWindowToolbarButton] cell]; @@ -6540,33 +6857,34 @@ * after 10.10. */ #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000) if (!(macWindow.styleMask & NSUtilityWindowMask)) { - /* * Exclude overrideredirect, transient, and "help"-styled * windows from moving into their own fullscreen space. - * */ if ((winPtr->atts.override_redirect) || - (wmPtr->master != None) || - (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) { + (wmPtr->master != NULL) || + (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) { b |= (NSWindowCollectionBehaviorCanJoinAllSpaces | - NSWindowCollectionBehaviorFullScreenAuxiliary); + NSWindowCollectionBehaviorFullScreenAuxiliary); } else { - NSSize screenSize = [[macWindow screen]frame].size; + NSSize screenSize = [[macWindow screen] frame].size; b |= NSWindowCollectionBehaviorFullScreenPrimary; - /* The default max size has height less than the screen height. - * This causes the window manager to refuse to allow the window - * to be resized when it is a split window. To work around - * this we make the max size equal to the screen size. + /* + * The default max size has height less than the screen + * height. This causes the window manager to refuse to + * allow the window to be resized when it is a split + * window. To work around this we make the max size equal + * to the screen size. (For 10.11 and up, only) */ - - [macWindow setMaxFullScreenContentSize:screenSize]; + if ([NSApp macMinorVersion] > 10) { + [macWindow setMaxFullScreenContentSize:screenSize]; + } } } #endif if (newAttributes & tkCanJoinAllSpacesAttribute) { @@ -6592,10 +6910,11 @@ * The change of window class/attributes might have changed the window * frame geometry: */ NSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect]; + wmPtr->xInParent = -structureRect.origin.x; wmPtr->yInParent = structureRect.origin.y + structureRect.size.height; wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width; wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height; } @@ -6625,10 +6944,11 @@ WmInfo *wmPtr = winPtr->wmInfoPtr; UInt64 oldAttributes = wmPtr->attributes; int oldFlags = wmPtr->flags; unsigned long styleMask; NSRect structureRect; + NSWindow *parentWindow; if (!macWindow && winPtr->window != None && TkMacOSXHostToplevelExists(winPtr)) { macWindow = TkMacOSXDrawableWindow(winPtr->window); } @@ -6665,13 +6985,12 @@ } else { styleMask |= NSTitledWindowMask; } } if (macWindow) { - NSWindow *parentWindow = [macWindow parentWindow]; structureRect = [NSWindow frameRectForContentRect:NSZeroRect - styleMask:styleMask]; + styleMask:styleMask]; /* * Synchronize the wmInfoPtr to match the new window configuration * so windowBoundsChanged won't corrupt the window manager info. */ @@ -6684,49 +7003,67 @@ [macWindow setExcludedFromWindowsMenu:YES]; [macWindow setStyleMask:styleMask]; if (wmPtr->hints.initial_state == NormalState) { [macWindow orderFront:nil]; } - if (wmPtr->master != None) { + if (wmPtr->master != NULL) { wmPtr->flags |= WM_TOPMOST; } else { wmPtr->flags &= ~WM_TOPMOST; } } else { const char *title = winPtr->wmInfoPtr->titleUid; + if (!title) { title = winPtr->nameUid; } [macWindow setStyleMask:styleMask]; [macWindow setTitle:[NSString stringWithUTF8String:title]]; [macWindow setExcludedFromWindowsMenu:NO]; wmPtr->flags &= ~WM_TOPMOST; } if (wmPtr->master != None) { - TkDisplay *dispPtr = TkGetDisplayList(); - TkWindow *masterWinPtr = (TkWindow *) - Tk_IdToWindow(dispPtr->display, wmPtr->master); - - if (masterWinPtr && masterWinPtr->window != None && - TkMacOSXHostToplevelExists(masterWinPtr)) { - NSWindow *masterMacWin = - TkMacOSXDrawableWindow(masterWinPtr->window); - - if (masterMacWin && masterMacWin != parentWindow && - (winPtr->flags & TK_MAPPED)) { - if (parentWindow) { - [parentWindow removeChildWindow:macWindow]; - } - [masterMacWin addChildWindow:macWindow - ordered:NSWindowAbove]; - if (wmPtr->flags & WM_TOPMOST) { - [macWindow setLevel:kCGUtilityWindowLevel]; - } - } - } - } else if (parentWindow) { - [parentWindow removeChildWindow:macWindow]; + TkWindow *masterWinPtr = (TkWindow *) wmPtr->master; + + if (masterWinPtr && (masterWinPtr->window != None) + && TkMacOSXHostToplevelExists(masterWinPtr)) { + NSWindow *masterMacWin = TkMacOSXDrawableWindow( + masterWinPtr->window); + + /* + * Try to add the transient window as a child window of the + * master. A child NSWindow retains its relative position with + * respect to the parent when the parent is moved. This is + * pointless if the parent is offscreen, and adding a child to + * an offscreen window causes the parent to be displayed as a + * zombie. So we only do this if the parent is visible. + */ + + if (masterMacWin && [masterMacWin isVisible] + && (winPtr->flags & TK_MAPPED)) { + /* + * If the transient is already a child of some other window, + * remove it. + */ + + parentWindow = [macWindow parentWindow]; + if (parentWindow && parentWindow != masterMacWin) { + [parentWindow removeChildWindow:macWindow]; + } + + [masterMacWin addChildWindow:macWindow + ordered:NSWindowAbove]; + } + } + } else { + parentWindow = [macWindow parentWindow]; + if (parentWindow) { + [parentWindow removeChildWindow:macWindow]; + } + } + if (wmPtr->flags & WM_TOPMOST) { + [macWindow setLevel:kCGUtilityWindowLevel]; } ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes, oldFlags, 0, 0); } } @@ -6904,10 +7241,11 @@ RemapWindows( TkWindow *winPtr, MacDrawable *parentWin) { TkWindow *childPtr; + /* * Remove the OS specific window. It will get rebuilt when the window gets * Mapped. */ @@ -6921,11 +7259,14 @@ #ifdef TK_REBUILD_TOPLEVEL winPtr->flags |= TK_REBUILD_TOPLEVEL; #endif } - /* Repeat for all the children */ + /* + * Repeat for all the children. + */ + for (childPtr = winPtr->childList; childPtr != NULL; childPtr = childPtr->nextPtr) { RemapWindows(childPtr, (MacDrawable *) winPtr->window); } } Index: macosx/tkMacOSXWm.h ================================================================== --- macosx/tkMacOSXWm.h +++ macosx/tkMacOSXWm.h @@ -34,10 +34,21 @@ * of the structure varies to accommodate the * needs of the actual command. THIS MUST BE * THE LAST FIELD OF THE STRUCTURE. */ } ProtocolHandler; +/* The following data structure is used in the TkWmInfo to maintain a list of all of the + * transient windows belonging to a given master. + */ + +typedef struct Transient { + TkWindow *winPtr; + int flags; + struct Transient *nextPtr; +} Transient; + +#define WITHDRAWN_BY_MASTER 0x1 /* * A data structure of the following type holds window-manager-related * information for each top-level window in an application. */ @@ -52,26 +63,25 @@ * isn't reparented, this has the value * None. */ Tk_Uid titleUid; /* Title to display in window caption. If NULL, * use name of widget. */ char *iconName; /* Name to display in icon. */ - Window master; /* Master window for TRANSIENT_FOR property, or + Tk_Window master; /* Master window for TRANSIENT_FOR property, or * None. */ XWMHints hints; /* Various pieces of information for window * manager. */ char *leaderName; /* Path name of leader of window group * (corresponds to hints.window_group). * Malloc-ed. Note: this field doesn't get * updated if leader is destroyed. */ - char *masterWindowName; /* Path name of window specified as master in - * "wm transient" command, or NULL. Malloc-ed. - * Note: this field doesn't get updated if - * masterWindowName is destroyed. */ Tk_Window icon; /* Window to use as icon for this window, or * NULL. */ Tk_Window iconFor; /* Window for which this window is icon, or * NULL if this isn't an icon for anyone. */ + Transient *transientPtr; /* First item in a list of all transient windows + * belonging to this window, or NULL if there + * are no transients. */ /* * Information used to construct an XSizeHints structure for the window * manager: */ Index: macosx/tkMacOSXXStubs.c ================================================================== --- macosx/tkMacOSXXStubs.c +++ macosx/tkMacOSXXStubs.c @@ -176,11 +176,11 @@ } display->vendor = vendor; { int major, minor, patch; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); #else NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; @@ -673,18 +673,10 @@ */ display->request++; } -void -Tk_FreeXId( - Display *display, - XID xid) -{ - /* no-op function needed for stubs implementation. */ -} - int XSync( Display *display, Bool flag) { Index: macosx/ttkMacOSXTheme.c ================================================================== --- macosx/ttkMacOSXTheme.c +++ macosx/ttkMacOSXTheme.c @@ -1,75 +1,150 @@ /* * ttkMacOSXTheme.c -- * - * Tk theme engine for Mac OSX, using the Appearance Manager API. + * Tk theme engine for Mac OSX, using the Appearance Manager API. * * Copyright (c) 2004 Joe English * Copyright (c) 2005 Neil Madden * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright 2008-2009, Apple Inc. * Copyright 2009 Kevin Walzer/WordTech Communications LLC. + * Copyright 2019 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * See also: * * + * Appearance_Manager/appearance_manager/APIIndex.html > * * Notes: - * "Active" means different things in Mac and Tk terminology -- - * On Aqua, widgets are "Active" if they belong to the foreground window, - * "Inactive" if they are in a background window. - * Tk uses the term "active" to mean that the mouse cursor - * is over a widget; aka "hover", "prelight", or "hot-tracked". - * Aqua doesn't use this kind of feedback. - * - * The QuickDraw/Carbon coordinate system is relative to the - * top-level window, not to the Tk_Window. BoxToRect() - * accounts for this. + * "Active" means different things in Mac and Tk terminology -- + * On Aqua, widgets are "Active" if they belong to the foreground window, + * "Inactive" if they are in a background window. Tk uses the term + * "active" to mean that the mouse cursor is over a widget; aka "hover", + * "prelight", or "hot-tracked". Aqua doesn't use this kind of feedback. + * + * The QuickDraw/Carbon coordinate system is relative to the top-level + * window, not to the Tk_Window. BoxToRect() accounts for this. */ #include "tkMacOSXPrivate.h" #include "ttk/ttkTheme.h" +#include /* - * Use this version in the core: + * Macros for handling drawing contexts. */ -#define BEGIN_DRAWING(d) { \ + +#define BEGIN_DRAWING(d) { \ TkMacOSXDrawingContext dc; \ if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;} #define END_DRAWING \ - TkMacOSXRestoreDrawingContext(&dc); } + TkMacOSXRestoreDrawingContext(&dc);} #define HIOrientation kHIThemeOrientationNormal +#define NoThemeMetric 0xFFFFFFFF #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) #else #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) #endif /* __LP64__ */ + +#define TTK_STATE_FIRST_TAB TTK_STATE_USER1 +#define TTK_STATE_LAST_TAB TTK_STATE_USER2 +#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 + +/* + * Colors and gradients used in Dark Mode. + */ + +static CGFloat darkButtonFace[4] = { + 112.0 / 255, 113.0 / 255, 115.0 / 255, 1.0 +}; +static CGFloat darkPressedBevelFace[4] = { + 135.0 / 255, 136.0 / 255, 138.0 / 255, 1.0 +}; +static CGFloat darkSelectedBevelFace[4] = { + 162.0 / 255, 163.0 / 255, 165.0 / 255, 1.0 +}; +static CGFloat darkDisabledButtonFace[4] = { + 86.0 / 255, 87.0 / 255, 89.0 / 255, 1.0 +}; +static CGFloat darkInactiveSelectedTab[4] = { + 159.0 / 255, 160.0 / 255, 161.0 / 255, 1.0 +}; +static CGFloat darkFocusRing[4] = { + 38.0 / 255, 113.0 / 255, 159.0 / 255, 1.0 +}; +static CGFloat darkFocusRingTop[4] = { + 50.0 / 255, 124.0 / 255, 171.0 / 255, 1.0 +}; +static CGFloat darkFocusRingBottom[4] = { + 57.0 / 255, 130.0 / 255, 176.0 / 255, 1.0 +}; +static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; +static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25}; +static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625}; +static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125}; +static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625}; +static CGFloat darkTopGradient[8] = { + 1.0, 1.0, 1.0, 0.3, + 1.0, 1.0, 1.0, 0.0 +}; +static CGFloat darkBackgroundGradient[8] = { + 0.0, 0.0, 0.0, 0.1, + 0.0, 0.0, 0.0, 0.25 +}; +static CGFloat darkInactiveGradient[8] = { + 89.0 / 255, 90.0 / 255, 93.0 / 255, 1.0, + 119.0 / 255, 120.0 / 255, 122.0 / 255, 1.0 +}; +static CGFloat darkSelectedGradient[8] = { + 23.0 / 255, 111.0 / 255, 232.0 / 255, 1.0, + 20.0 / 255, 94.0 / 255, 206.0 / 255, 1.0 +}; + +/* + * When building on systems earlier than 10.8 there is no reasonable way to + * convert an NSColor to a CGColor. We do run-time checking of the OS version, + * and never need the CGColor property on older systems, so we can use this + * CGCOLOR macro, which evaluates to NULL without raising compiler warnings. + * Similarly, we never draw rounded rectangles on older systems which did not + * have CGPathCreateWithRoundedRect, so we just redefine it to return NULL. + */ + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +#define CGCOLOR(nscolor) nscolor.CGColor +#else +#define CGCOLOR(nscolor) (0 ? (CGColorRef) nscolor : NULL) +#define CGPathCreateWithRoundedRect(w, x, y, z) NULL +#endif /*---------------------------------------------------------------------- * +++ Utilities. */ /* * BoxToRect -- - * Convert a Ttk_Box in Tk coordinates relative to the given Drawable - * to a native Rect relative to the containing port. + * Convert a Ttk_Box in Tk coordinates relative to the given Drawable + * to a native Rect relative to the containing port. */ -static inline CGRect BoxToRect(Drawable d, Ttk_Box b) + +static inline CGRect BoxToRect( + Drawable d, + Ttk_Box b) { - MacDrawable *md = (MacDrawable*)d; + MacDrawable *md = (MacDrawable *) d; CGRect rect; - rect.origin.y = b.y + md->yOff; - rect.origin.x = b.x + md->xOff; - rect.size.height = b.height; - rect.size.width = b.width; + rect.origin.y = b.y + md->yOff; + rect.origin.x = b.x + md->xOff; + rect.size.height = b.height; + rect.size.width = b.width; return rect; } /* @@ -79,139 +154,1260 @@ static Ttk_StateTable ThemeStateTable[] = { {kThemeStateUnavailable, TTK_STATE_DISABLED, 0}, {kThemeStatePressed, TTK_STATE_PRESSED, 0}, {kThemeStateInactive, TTK_STATE_BACKGROUND, 0}, {kThemeStateActive, 0, 0} -/* Others: Not sure what these are supposed to mean. - Up/Down have something to do with "little arrow" increment controls... - Dunno what a "Rollover" is. - NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by the - looks of things - {kThemeStateRollover, 0, 0}, - {kThemeStateUnavailableInactive, 0, 0} - {kThemeStatePressedUp, 0, 0}, - {kThemeStatePressedDown, 0, 0} -*/ + + /* Others: Not sure what these are supposed to mean. Up/Down have + * something to do with "little arrow" increment controls... Dunno what + * a "Rollover" is. + * NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by + * the looks of things + * + * {kThemeStateRollover, 0, 0}, + * {kThemeStateUnavailableInactive, 0, 0} + * {kThemeStatePressedUp, 0, 0}, + * {kThemeStatePressedDown, 0, 0} + */ +}; + +/*---------------------------------------------------------------------- + * NormalizeButtonBounds -- + * + * Apple's Human Interface Guidelines only allow three specific heights + * for most buttons: Regular, small and mini. We always use the regular + * size. However, Ttk may provide an arbitrary bounding rectangle. We + * always draw the button centered vertically on the rectangle, and + * having the same width as the rectangle. This function returns the + * actual bounding rectangle that will be used in drawing the button. + * + * The BevelButton is allowed to have arbitrary size, and also has + * external padding. This is handled separately here. + */ + +static CGRect NormalizeButtonBounds( + SInt32 heightMetric, + CGRect bounds) +{ + SInt32 height; + + if (heightMetric != (SInt32) NoThemeMetric) { + ChkErr(GetThemeMetric, heightMetric, &height); + bounds.origin.y += (bounds.size.height - height) / 2; + bounds.size.height = height; + } + return bounds; +} + +/*---------------------------------------------------------------------- + * +++ Backgrounds + * + * Support for contrasting background colors when GroupBoxes or Tabbed + * panes are nested inside each other. Early versions of macOS used ridged + * borders, so do not need contrasting backgrounds. + */ + +/* + * For systems older than 10.14, [NSColor windowBackGroundColor] generates + * garbage when called from this function. In 10.14 it works correctly, and + * must be used in order to have a background color which responds to Dark + * Mode. So we use this hard-wired RGBA color on the older systems which don't + * support Dark Mode anyway. + */ + +static CGFloat windowBackground[4] = { + 235.0 / 255, 235.0 / 255, 235.0 / 255, 1.0 }; +static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0}; +static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0}; + +/*---------------------------------------------------------------------- + * GetBackgroundColor -- + * + * Fills the array rgba with the color coordinates for a background color. + * Start with the background color of a window's geometry master, or the + * standard ttk window background if there is no master. If the contrast + * parameter is nonzero, modify this color to be darker, for the aqua + * appearance, or lighter for the DarkAqua appearance. This is primarily + * used by the Fill and Background elements. + */ + +static void GetBackgroundColor( + CGContextRef context, + Tk_Window tkwin, + int contrast, + CGFloat *rgba) +{ + TkWindow *winPtr = (TkWindow *) tkwin; + TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin); + + while (masterPtr != NULL) { + if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) { + break; + } + masterPtr = (TkWindow *) TkGetGeomMaster(masterPtr); + } + if (masterPtr) { + for (int i = 0; i < 4; i++) { + rgba[i] = masterPtr->privatePtr->fillRGBA[i]; + } + } else { + if ([NSApp macMinorVersion] > 13) { + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *windowColor = [[NSColor windowBackgroundColor] + colorUsingColorSpace: deviceRGB]; + [windowColor getComponents: rgba]; + } else { + for (int i = 0; i < 4; i++) { + rgba[i] = windowBackground[i]; + } + } + } + if (contrast) { + int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5); + + if (isDark) { + for (int i = 0; i < 3; i++) { + rgba[i] += 8.0 / 255.0; + } + } else { + for (int i = 0; i < 3; i++) { + rgba[i] -= 8.0 / 255.0; + } + } + winPtr->privatePtr->flags |= TTK_HAS_CONTRASTING_BG; + for (int i = 0; i < 4; i++) { + winPtr->privatePtr->fillRGBA[i] = rgba[i]; + } + } +} + + +/*---------------------------------------------------------------------- + * +++ Single Arrow Buttons -- + * + * Used in ListHeaders and Comboboxes. + */ + +static void DrawDownArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint arrow[3] = { + {x, y - size / 4}, {x + size / 2, y + size / 4}, + {x + size, y - size / 4} + }; + CGContextAddLines(context, arrow, 3); + CGContextStrokePath(context); +} + +static void DrawUpArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint arrow[3] = { + {x, y + size / 4}, {x + size / 2, y - size / 4}, + {x + size, y + size / 4} + }; + CGContextAddLines(context, arrow, 3); + CGContextStrokePath(context); +} + +/*---------------------------------------------------------------------- + * +++ Double Arrow Buttons -- + * + * Used in MenuButtons and SpinButtons. + */ + +static void DrawUpDownArrows( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = + {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = + {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); +} + + +/*---------------------------------------------------------------------- + * +++ FillButtonBackground -- + * + * Fills a rounded rectangle with a transparent black gradient. + * This is a no-op if building on 10.8 or older. + */ + +static void FillButtonBackground( + CGContextRef context, + CGRect bounds, + CGFloat radius) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + CGPoint backgroundEnd = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; + + CGContextBeginPath(context); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, backgroundGradient, + bounds.origin, backgroundEnd, 0); + CFRelease(path); + CFRelease(backgroundGradient); +} + +/*---------------------------------------------------------------------- + * +++ HighlightButtonBorder -- + * + * Accent the top border of a rounded rectangle with a transparent + * white gradient. + */ + +static void HighlightButtonBorder( + CGContextRef context, + CGRect bounds) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; + CGGradientRef topGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + + CGContextSaveGState(context); + CGContextBeginPath(context); + CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, + 4, PI, 3 * PI / 2, 0); + CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, + bounds.origin.y + 4, 4, 3 * PI / 2, 0, 0); + CGContextReplacePathWithStrokedPath(context); + CGContextClip(context); + CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, + 0.0); + CGContextRestoreGState(context); + CFRelease(topGradient); +} + +/*---------------------------------------------------------------------- + * DrawGroupBox -- + * + * This is a standalone drawing procedure which draws the contrasting + * rounded rectangular box for LabelFrames and Notebook panes used in + * more recent versions of macOS. + */ + +static void DrawGroupBox( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *borderColor, *bgColor; + static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; + CGFloat fill[4]; + + GetBackgroundColor(context, tkwin, 1, fill); + bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill + count: 4]; + CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); + CGContextSetFillColorWithColor(context, CGCOLOR(bgColor)); + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextClipToRect(context, bounds); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + borderColor = [NSColor colorWithColorSpace: deviceRGB components: border + count: 4]; + CGContextSetFillColorWithColor(context, CGCOLOR(borderColor)); + [borderColor getComponents: fill]; + CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]); + + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextReplacePathWithStrokedPath(context); + CGContextFillPath(context); + CFRelease(path); +} + +/*---------------------------------------------------------------------- + * SolidFillRoundedRectangle -- + * + * Fill a rounded rectangle with a specified solid color. + */ + +static void SolidFillRoundedRectangle( + CGContextRef context, + CGRect bounds, + CGFloat radius, + NSColor *color) +{ + CGPathRef path; + + CGContextSetFillColorWithColor(context, CGCOLOR(color)); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + CFRelease(path); +} + +/*---------------------------------------------------------------------- + * +++ DrawListHeader -- + * + * This is a standalone drawing procedure which draws column headers for + * a Treeview in the Aqua appearance. The HITheme headers have not + * matched the native ones since OSX 10.8. Note that the header image is + * ignored, but we draw arrows according to the state. + */ + +static void DrawListHeader( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin, + int state) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *strokeColor, *bgColor; + static CGFloat borderRGBA[4] = { + 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0 + }; + static CGFloat separatorRGBA[4] = { + 220.0 / 255, 220.0 / 255, 220.0 / 255, 1.0 + }; + static CGFloat activeBgRGBA[4] = { + 238.0 / 255, 238.0 / 255, 238.0 / 255, 1.0 + }; + static CGFloat inactiveBgRGBA[4] = { + 246.0 / 255, 246.0 / 255, 246.0 / 255, 1.0 + }; + + /* + * Apple changes the background of a list header when the window is not + * active. But Ttk does not indicate that in the state of a TreeHeader. + * So we have to query the Apple window manager. + */ + + NSWindow *win = TkMacOSXDrawableWindow(Tk_WindowId(tkwin)); + CGFloat *bgRGBA = [win isKeyWindow] ? activeBgRGBA : inactiveBgRGBA; + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}}; + + bgColor = [NSColor colorWithColorSpace: deviceRGB + components: bgRGBA + count: 4]; + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + CGContextBeginPath(context); + CGContextSetFillColorWithColor(context, CGCOLOR(bgColor)); + CGContextAddRect(context, bounds); + CGContextFillPath(context); + strokeColor = [NSColor colorWithColorSpace: deviceRGB + components: separatorRGBA + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor)); + CGContextAddLines(context, separator, 2); + CGContextStrokePath(context); + strokeColor = [NSColor colorWithColorSpace: deviceRGB + components: borderRGBA + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor)); + CGContextAddLines(context, top, 2); + CGContextStrokePath(context); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + CGContextRestoreGState(context); + + if (state & TTK_TREEVIEW_STATE_SORTARROW) { + CGRect arrowBounds = bounds; + arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; + arrowBounds.size.width = 16; + if (state & TTK_STATE_ALTERNATE) { + DrawUpArrow(context, arrowBounds, 3, 8, blackRGBA); + } else if (state & TTK_STATE_SELECTED) { + DrawDownArrow(context, arrowBounds, 3, 8, blackRGBA); + } + } +} + +/*---------------------------------------------------------------------- + * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up). + * + * The HIToolbox does not support Dark Mode, and apparently never will, + * so to make widgets look "native" we have to provide analogues of the + * HITheme drawing functions to be used in DarkAqua. We continue to use + * HITheme in Aqua, since it understands earlier versions of the OS. + * + * Drawing the dark widgets requires NSColors that were introduced in OSX + * 10.14, so we make some of these functions be no-ops when building on + * systems older than 10.14. + */ + +/*---------------------------------------------------------------------- + * GradientFillRoundedRectangle -- + * + * Fill a rounded rectangle with a specified gradient. + */ + +static void GradientFillRoundedRectangle( + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat *colors, + int numColors) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPathRef path; + CGPoint end = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; + CGGradientRef gradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, colors, NULL, numColors); + + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); + CFRelease(path); + CFRelease(gradient); +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkButton -- + * + * This is a standalone drawing procedure which draws PushButtons and + * PopupButtons in the Dark Mode style. + */ + +static void DrawDarkButton( + CGRect bounds, + ThemeButtonKind kind, + Ttk_State state, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *faceColor; + + /* + * To match the appearance of Apple's buttons we need to increase the + * height by 1 pixel. + */ + + bounds.size.height += 1; + + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 5); + + /* + * Fill the button face with the appropriate color. + */ + + bounds = CGRectInset(bounds, 1, 1); + if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) { + GradientFillRoundedRectangle(context, bounds, 4, + darkSelectedGradient, 2); + } else { + if (state & TTK_STATE_DISABLED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + } + + /* + * If this is a popup, draw the arrow button. + */ + + if ((kind == kThemePopupButton) | (kind == kThemeComboBox)) { + CGRect arrowBounds = bounds; + arrowBounds.size.width = 16; + arrowBounds.origin.x += bounds.size.width - 16; + + /* + * If the toplevel is front, paint the button blue. + */ + + if (!(state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { + GradientFillRoundedRectangle(context, arrowBounds, 4, + darkSelectedGradient, 2); + } + if (kind == kThemePopupButton) { + DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA); + } else { + DrawDownArrow(context, arrowBounds, 4, 8, whiteRGBA); + } + } + + HighlightButtonBorder(context, bounds); +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkIncDecButton -- + * + * This is a standalone drawing procedure which draws an IncDecButton + * (as used in a Spinbox) in the Dark Mode style. + */ + +static void DrawDarkIncDecButton( + CGRect bounds, + ThemeDrawState drawState, + Ttk_State state, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *faceColor; + + bounds = CGRectInset(bounds, 0, -1); + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 6); + + /* + * Fill the button face with the appropriate color. + */ + + bounds = CGRectInset(bounds, 1, 1); + if (state & TTK_STATE_DISABLED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + + /* + * If pressed, paint the appropriate half blue. + */ + + if (state & TTK_STATE_PRESSED) { + CGRect clip = bounds; + clip.size.height /= 2; + CGContextSaveGState(context); + if (drawState == kThemeStatePressedDown) { + clip.origin.y += clip.size.height; + } + CGContextClipToRect(context, clip); + GradientFillRoundedRectangle(context, bounds, 5, + darkSelectedGradient, 2); + CGContextRestoreGState(context); + } + DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA); + HighlightButtonBorder(context, bounds); +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkBevelButton -- + * + * This is a standalone drawing procedure which draws RoundedBevelButtons + * in the Dark Mode style. + */ + +static void DrawDarkBevelButton( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *faceColor; + + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 5); + + /* + * Fill the button face with the appropriate color. + */ + + bounds = CGRectInset(bounds, 1, 1); + if (state & TTK_STATE_PRESSED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkPressedBevelFace + count: 4]; + } else if ((state & TTK_STATE_DISABLED) || + (state & TTK_STATE_ALTERNATE)) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else if (state & TTK_STATE_SELECTED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkSelectedBevelFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + HighlightButtonBorder(context, bounds); +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkCheckBox -- + * + * This is a standalone drawing procedure which draws Checkboxes in the + * Dark Mode style. + */ + +static void DrawDarkCheckBox( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + CGRect checkbounds = {{0, bounds.size.height / 2 - 8}, {16, 16}}; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *stroke; + CGFloat x, y; + + bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y); + x = bounds.origin.x; + y = bounds.origin.y; + + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 4); + bounds = CGRectInset(bounds, 1, 1); + if (!(state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + GradientFillRoundedRectangle(context, bounds, 3, + darkSelectedGradient, 2); + } else { + GradientFillRoundedRectangle(context, bounds, 3, + darkInactiveGradient, 2); + } + HighlightButtonBorder(context, bounds); + if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + if (state & TTK_STATE_DISABLED) { + stroke = [NSColor disabledControlTextColor]; + } else { + stroke = [NSColor controlTextColor]; + } + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); + } + if (state & TTK_STATE_SELECTED) { + CGContextSetLineWidth(context, 1.5); + CGContextBeginPath(context); + CGPoint check[3] = {{x + 4, y + 8}, {x + 7, y + 11}, {x + 11, y + 4}}; + CGContextAddLines(context, check, 3); + CGContextStrokePath(context); + } else if (state & TTK_STATE_ALTERNATE) { + CGContextSetLineWidth(context, 2.0); + CGContextBeginPath(context); + CGPoint bar[2] = {{x + 4, y + 8}, {x + 12, y + 8}}; + CGContextAddLines(context, bar, 2); + CGContextStrokePath(context); + } +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkRadioButton -- + * + * This is a standalone drawing procedure which draws RadioButtons + * in the Dark Mode style. + */ + +static void DrawDarkRadioButton( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + CGRect checkbounds = {{0, bounds.size.height / 2 - 9}, {18, 18}}; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *fill; + CGFloat x, y; + + bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y); + x = bounds.origin.x; + y = bounds.origin.y; + + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 9); + bounds = CGRectInset(bounds, 1, 1); + if (!(state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + GradientFillRoundedRectangle(context, bounds, 8, + darkSelectedGradient, 2); + } else { + GradientFillRoundedRectangle(context, bounds, 8, + darkInactiveGradient, 2); + } + HighlightButtonBorder(context, bounds); + if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + if (state & TTK_STATE_DISABLED) { + fill = [NSColor disabledControlTextColor]; + } else { + fill = [NSColor controlTextColor]; + } + CGContextSetFillColorWithColor(context, CGCOLOR(fill)); + } + if (state & TTK_STATE_SELECTED) { + CGContextBeginPath(context); + CGRect dot = {{x + 6, y + 6}, {6, 6}}; + CGContextAddEllipseInRect(context, dot); + CGContextFillPath(context); + } else if (state & TTK_STATE_ALTERNATE) { + CGRect bar = {{x + 5, y + 8}, {8, 2}}; + CGContextFillRect(context, bar); + } +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkTab -- + * + * This is a standalone drawing procedure which draws Tabbed Pane + * Tabs in the Dark Mode style. + */ + +static void DrawDarkTab( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *faceColor, *stroke; + CGRect originalBounds = bounds; + + CGContextSetLineWidth(context, 1.0); + CGContextClipToRect(context, bounds); + + /* + * Extend the bounds to one or both sides so the rounded part will be + * clipped off. + */ + + if (!(state & TTK_STATE_FIRST_TAB)) { + bounds.origin.x -= 10; + bounds.size.width += 10; + } + + if (!(state & TTK_STATE_LAST_TAB)) { + bounds.size.width += 10; + } + + /* + * Fill the tab face with the appropriate color or gradient. Use a solid + * color if the tab is not selected, otherwise use a blue or gray + * gradient. + */ + + bounds = CGRectInset(bounds, 1, 1); + if (!(state & TTK_STATE_SELECTED)) { + if (state & TTK_STATE_DISABLED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + + /* + * Draw a separator line on the left side of the tab if it + * not first. + */ + + if (!(state & TTK_STATE_FIRST_TAB)) { + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkTabSeparator + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); + CGContextBeginPath(context); + CGContextMoveToPoint(context, originalBounds.origin.x, + originalBounds.origin.y + 1); + CGContextAddLineToPoint(context, originalBounds.origin.x, + originalBounds.origin.y + originalBounds.size.height - 1); + CGContextStrokePath(context); + CGContextRestoreGState(context); + } + } else { + + /* + * This is the selected tab; paint it blue. If it is first, cover up + * the separator line drawn by the second one. (The selected tab is + * always drawn last.) + */ + + if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) { + bounds.size.width += 1; + } + if (!(state & TTK_STATE_BACKGROUND)) { + GradientFillRoundedRectangle(context, bounds, 4, + darkSelectedGradient, 2); + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkInactiveSelectedTab + count: 4]; + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + } + HighlightButtonBorder(context, bounds); + } +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkSeparator -- + * + * This is a standalone drawing procedure which draws a separator widget + * in Dark Mode. + */ + +static void DrawDarkSeparator( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin) +{ + static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3}; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB + components: fill + count:4]; + + CGContextSetFillColorWithColor(context, CGCOLOR(fillColor)); + CGContextFillRect(context, bounds); +} + +/*---------------------------------------------------------------------- + * +++ DrawDarkFocusRing -- + * + * This is a standalone drawing procedure which draws a focus ring around + * an Entry widget in Dark Mode. + */ + +static void DrawDarkFocusRing( + CGRect bounds, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *strokeColor; + NSColor *fillColor = [NSColor colorWithColorSpace:deviceRGB + components:darkFocusRing + count:4]; + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint topPart[4] = { + {x, y + h}, {x, y + 1}, {x + w - 1, y + 1}, {x + w - 1, y + h} + }; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + CGContextBeginPath(context); + strokeColor = [NSColor colorWithColorSpace: deviceRGB + components: darkFocusRingTop + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor)); + CGContextAddLines(context, topPart, 4); + CGContextStrokePath(context); + strokeColor = [NSColor colorWithColorSpace: deviceRGB + components: darkFocusRingBottom + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor)); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + CGContextSetShouldAntialias(context, true); + CGContextSetFillColorWithColor(context, CGCOLOR(fillColor)); + CGPathRef path = CGPathCreateWithRoundedRect(CGRectInset(bounds, -3, -3), + 4, 4, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextAddRect(context, bounds); + CGContextEOFillPath(context); + CGContextRestoreGState(context); +} +/*---------------------------------------------------------------------- + * +++ DrawDarkFrame -- + * + * This is a standalone drawing procedure which draws various + * types of borders in Dark Mode. + */ + +static void DrawDarkFrame( + CGRect bounds, + CGContextRef context, + HIThemeFrameKind kind) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *stroke; + + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint topPart[4] = { + {x, y + h - 1}, {x, y + 1}, {x + w, y + 1}, {x + w, y + h - 1} + }; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}}; + + switch (kind) { + case kHIThemeFrameTextFieldSquare: + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + CGContextBeginPath(context); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameTop + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); + CGContextAddLines(context, topPart, 4); + CGContextStrokePath(context); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameBottom + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameAccent + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); + CGContextAddLines(context, accent, 2); + CGContextStrokePath(context); + CGContextRestoreGState(context); + break; + default: + break; + } +} + +/*---------------------------------------------------------------------- + * +++ DrawListHeader -- + * + * This is a standalone drawing procedure which draws column + * headers for a Treeview in the Dark Mode. + */ + +static void DrawDarkListHeader( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin, + int state) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *stroke; + + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint top[2] = {{x, y}, {x + w, y}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}}; + + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameBottom + count: 4]; + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); + CGContextBeginPath(context); + CGContextAddLines(context, top, 2); + CGContextStrokePath(context); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + CGContextAddLines(context, separator, 2); + CGContextStrokePath(context); + CGContextRestoreGState(context); + + if (state & TTK_TREEVIEW_STATE_SORTARROW) { + CGRect arrowBounds = bounds; + + arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; + arrowBounds.size.width = 16; + if (state & TTK_STATE_ALTERNATE) { + DrawUpArrow(context, arrowBounds, 3, 8, whiteRGBA); + } else if (state & TTK_STATE_SELECTED) { + DrawDownArrow(context, arrowBounds, 3, 8, whiteRGBA); + } + } +} /*---------------------------------------------------------------------- * +++ Button element: Used for elements drawn with DrawThemeButton. */ /* - * Extra margins to account for drop shadow. + * When Ttk draws the various types of buttons, a pointer to one of these + * is passed as the clientData. */ -static Ttk_Padding ButtonMargins = {2,2,2,2}; - -#define NoThemeMetric 0xFFFFFFFF typedef struct { ThemeButtonKind kind; ThemeMetric heightMetric; } ThemeButtonParams; - static ThemeButtonParams - PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight }, - CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight }, - RadioButtonParams = { kThemeRadioButton, kThemeMetricRadioButtonHeight }, - BevelButtonParams = { kThemeBevelButton, NoThemeMetric }, - PopupButtonParams = { kThemePopupButton, kThemeMetricPopupButtonHeight }, - DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, - ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; - + PushButtonParams = {kThemePushButton, kThemeMetricPushButtonHeight}, + CheckBoxParams = {kThemeCheckBox, kThemeMetricCheckBoxHeight}, + RadioButtonParams = {kThemeRadioButton, kThemeMetricRadioButtonHeight}, + BevelButtonParams = {kThemeRoundedBevelButton, NoThemeMetric}, + PopupButtonParams = {kThemePopupButton, kThemeMetricPopupButtonHeight}, + DisclosureParams = { + kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight +}, + ListHeaderParams = +{kThemeListHeaderButton, kThemeMetricListHeaderHeight}; static Ttk_StateTable ButtonValueTable[] = { - { kThemeButtonMixed, TTK_STATE_ALTERNATE, 0 }, - { kThemeButtonOn, TTK_STATE_SELECTED, 0 }, - { kThemeButtonOff, 0, 0 } -/* Others: kThemeDisclosureRight, kThemeDisclosureDown, kThemeDisclosureLeft */ + {kThemeButtonMixed, TTK_STATE_ALTERNATE, 0}, + {kThemeButtonOn, TTK_STATE_SELECTED, 0}, + {kThemeButtonOff, 0, 0} + + /* + * Others: kThemeDisclosureRight, kThemeDisclosureDown, + * kThemeDisclosureLeft + */ + }; - static Ttk_StateTable ButtonAdornmentTable[] = { - { kThemeAdornmentDefault| kThemeAdornmentFocus, - TTK_STATE_ALTERNATE| TTK_STATE_FOCUS, 0 }, - { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 }, - { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 }, - { kThemeAdornmentNone, 0, 0 } + {kThemeAdornmentDefault | kThemeAdornmentFocus, + TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0}, + {kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0}, + {kThemeAdornmentNone, TTK_STATE_ALTERNATE, 0}, + {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0}, + {kThemeAdornmentNone, 0, 0} }; -/* - * computeButtonDrawInfo -- - * Fill in an appearance manager HIThemeButtonDrawInfo record. +/*---------------------------------------------------------------------- + * +++ computeButtonDrawInfo -- + * + * Fill in an appearance manager HIThemeButtonDrawInfo record. */ + static inline HIThemeButtonDrawInfo computeButtonDrawInfo( - ThemeButtonParams *params, Ttk_State state) + ThemeButtonParams *params, + Ttk_State state, + Tk_Window tkwin) { + + /* + * See ButtonElementDraw for the explanation of why we always draw + * PushButtons in the active state. + */ + + SInt32 HIThemeState; + + HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state); + switch (params->kind) { + case kThemePushButton: + HIThemeState &= ~kThemeStateInactive; + HIThemeState |= kThemeStateActive; + break; + default: + break; + } + const HIThemeButtonDrawInfo info = { .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), + .state = HIThemeState, .kind = params ? params->kind : 0, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; return info; } -static void ButtonElementSizeNoPadding( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +/*---------------------------------------------------------------------- + * +++ Button elements. + */ + +static void ButtonElementMinSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; if (params->heightMetric != NoThemeMetric) { - SInt32 height; + ChkErr(GetThemeMetric, params->heightMetric, minHeight); - ChkErr(GetThemeMetric, params->heightMetric, &height); - *heightPtr = height; + /* + * The theme height does not include the 1-pixel border around + * the button, although it does include the 1-pixel shadow at + * the bottom. + */ + + *minHeight += 2; + + /* + * The minwidth must be 0 to force the generic ttk code to compute the + * correct text layout. For example, a non-zero value will cause the + * text to be left justified, no matter what -anchor setting is used in + * the style. + */ + + *minWidth = 0; } } static void ButtonElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; - const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0); + const HIThemeButtonDrawInfo info = + computeButtonDrawInfo(params, 0, tkwin); static const CGRect scratchBounds = {{0, 0}, {100, 100}}; - CGRect contentBounds; + CGRect contentBounds, backgroundBounds; + int verticalPad; - ButtonElementSizeNoPadding( - clientData, elementRecord, tkwin, - widthPtr, heightPtr, paddingPtr); + ButtonElementMinSize(clientData, elementRecord, tkwin, + minWidth, minHeight, paddingPtr); /* - * To compute internal padding, query the appearance manager - * for the content bounds of a dummy rectangle, then use - * the difference as the padding. + * Given a hypothetical bounding rectangle for a button, HIToolbox will + * compute a bounding rectangle for the button contents and a bounding + * rectangle for the button background. The background bounds are large + * enough to contain the image of the button in any state, which might + * include highlight borders, shadows, etc. The content rectangle is not + * centered vertically within the background rectangle, presumably because + * shadows only appear on the bottom. Nonetheless, when HITools is asked + * to draw a button with a certain bounding rectangle it draws the button + * centered within the rectangle. + * + * To compute the effective padding around a button we request the + * content and bounding rectangles for a 100x100 button and use the + * padding between those. However, we symmetrize the padding on the + * top and bottom, because that is how the button will be drawn. */ + ChkErr(HIThemeGetButtonContentBounds, &scratchBounds, &info, &contentBounds); - - paddingPtr->left = CGRectGetMinX(contentBounds); - paddingPtr->top = CGRectGetMinY(contentBounds); - paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds) + 1; - paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds); - - /* - * Now add a little extra padding to account for drop shadows. - * @@@ SHOULD: call GetThemeButtonBackgroundBounds() instead. - */ - - *paddingPtr = Ttk_AddPadding(*paddingPtr, ButtonMargins); - *widthPtr += Ttk_PaddingWidth(ButtonMargins); - *heightPtr += Ttk_PaddingHeight(ButtonMargins); + ChkErr(HIThemeGetButtonBackgroundBounds, + &scratchBounds, &info, &backgroundBounds); + paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x; + paddingPtr->right = + CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds); + verticalPad = backgroundBounds.size.height - contentBounds.size.height; + paddingPtr->top = paddingPtr->bottom = verticalPad / 2; } static void ButtonElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ThemeButtonParams *params = clientData; - CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins)); - const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); + CGRect bounds = BoxToRect(d, b); + HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin); + + bounds = NormalizeButtonBounds(params->heightMetric, bounds); BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + if (TkMacOSXInDarkMode(tkwin)) { + switch (info.kind) { + case kThemePushButton: + case kThemePopupButton: + DrawDarkButton(bounds, info.kind, state, dc.context); + break; + case kThemeCheckBox: + DrawDarkCheckBox(bounds, state, dc.context); + break; + case kThemeRadioButton: + DrawDarkRadioButton(bounds, state, dc.context); + break; + case kThemeRoundedBevelButton: + DrawDarkBevelButton(bounds, state, dc.context); + break; + default: + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, + HIOrientation, NULL); + } + } else { + + /* + * Apple's PushButton and PopupButton do not change their fill color + * when the window is inactive. However, except in 10.7 (Lion), the + * color of the arrow button on a PopupButton does change. For some + * reason HITheme fills inactive buttons with a transparent color that + * allows the window background to show through, leading to + * inconsistent behavior. We work around this by filling behind an + * inactive PopupButton with a text background color before asking + * HIToolbox to draw it. For PushButtons, we simply draw them in the + * active state. + */ + + if (info.kind == kThemePopupButton && + (state & TTK_STATE_BACKGROUND)) { + CGRect innerBounds = CGRectInset(bounds, 1, 1); + NSColor *whiteRGBA = [NSColor whiteColor]; + SolidFillRoundedRectangle(dc.context, innerBounds, 4, whiteRGBA); + } + + /* + * A BevelButton with mixed value is drawn borderless, which does make + * much sense for us. + */ + + if (info.kind == kThemeRoundedBevelButton && + info.value == kThemeButtonMixed) { + info.value = kThemeButtonOff; + info.state = kThemeStateInactive; + } + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); + } END_DRAWING } static Ttk_ElementSpec ButtonElementSpec = { TK_STYLE_VERSION_2, @@ -223,39 +1419,31 @@ /*---------------------------------------------------------------------- * +++ Notebook elements. */ - /* Tab position logic, c.f. ttkNotebook.c TabState() */ - -#define TTK_STATE_NOTEBOOK_FIRST TTK_STATE_USER1 -#define TTK_STATE_NOTEBOOK_LAST TTK_STATE_USER2 static Ttk_StateTable TabStyleTable[] = { - { kThemeTabFrontInactive, TTK_STATE_SELECTED|TTK_STATE_BACKGROUND}, - { kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND}, - { kThemeTabFrontUnavailable, TTK_STATE_DISABLED|TTK_STATE_SELECTED}, - { kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED}, - { kThemeTabFront, TTK_STATE_SELECTED}, - { kThemeTabNonFrontPressed, TTK_STATE_PRESSED}, - { kThemeTabNonFront, 0} + {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND}, + {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND}, + {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED}, + {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED}, + {kThemeTabFront, TTK_STATE_SELECTED}, + {kThemeTabNonFrontPressed, TTK_STATE_PRESSED}, + {kThemeTabNonFront, 0} }; - static Ttk_StateTable TabAdornmentTable[] = { - { kHIThemeTabAdornmentNone, - TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST}, - {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_NOTEBOOK_FIRST}, - {kHIThemeTabAdornmentNone, TTK_STATE_NOTEBOOK_LAST}, - {kHIThemeTabAdornmentTrailingSeparator, 0 }, + {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, + {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB}, + {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB}, + {kHIThemeTabAdornmentTrailingSeparator, 0}, }; - static Ttk_StateTable TabPositionTable[] = { - { kHIThemeTabPositionOnly, - TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST}, - { kHIThemeTabPositionFirst, TTK_STATE_NOTEBOOK_FIRST}, - { kHIThemeTabPositionLast, TTK_STATE_NOTEBOOK_LAST}, - { kHIThemeTabPositionMiddle, 0 }, + {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, + {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB}, + {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB}, + {kHIThemeTabPositionMiddle, 0}, }; /* * Apple XHIG Tab View Specifications: * @@ -269,11 +1457,12 @@ * Label spacing and fonts: The tab labels should be in a font that’s * proportional to the size of the tab view control. In addition, the label * should be placed so that there are equal margins of space before and after * it. The guidelines below provide the specifications you should use for tab * labels: - * - Regular size: System font. Center in tab, leaving 12 pixels on each side. + * - Regular size: System font. Center in tab, leaving 12 pixels on each + *side. * - Small: Small system font. Center in tab, leaving 10 pixels on each side. * - Mini: Mini system font. Center in tab, leaving 8 pixels on each side. * * Control spacing: Whether you decide to inset a tab view in a window or * extend its edges to the window sides and bottom, you should place the top @@ -283,10 +1472,11 @@ * of the tab view and the sides and bottom of the window (although 16 pixels * is also an acceptable margin-width). If you need to provide controls below * the tab view, leave enough space below the tab view so the controls are 20 * pixels above the bottom edge of the window and 12 pixels between the tab * view and the controls. + * * If you choose to extend the tab view sides and bottom so that they meet the * window sides and bottom, you should leave a margin of at least 20 pixels * between the content in the tab view and the tab-view edges. * * */ static void TabElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)heightPtr); + GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *) minHeight); *paddingPtr = Ttk_MakePadding(0, 0, 0, 2); } static void TabElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); HIThemeTabDrawInfo info = { .version = 1, .style = Ttk_StateTableLookup(TabStyleTable, state), @@ -317,11 +1515,16 @@ .kind = kHIThemeTabKindNormal, .position = Ttk_StateTableLookup(TabPositionTable, state), }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkTab(bounds, state, dc.context); + } else { + ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, + NULL); + } END_DRAWING } static Ttk_ElementSpec TabElementSpec = { TK_STYLE_VERSION_2, @@ -332,35 +1535,50 @@ }; /* * Notebook panes: */ + static void PaneElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_MakePadding(9, 5, 9, 9); } static void PaneElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); - HIThemeTabPaneDrawInfo info = { - .version = 1, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .direction = kThemeTabNorth, - .size = kHIThemeTabSizeNormal, - .kind = kHIThemeTabKindNormal, - .adornment = kHIThemeTabPaneAdornmentNormal, - }; bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + if ([NSApp macMinorVersion] > 8) { + DrawGroupBox(bounds, dc.context, tkwin); + } else { + HIThemeTabPaneDrawInfo info = { + .version = 1, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .direction = kThemeTabNorth, + .size = kHIThemeTabSizeNormal, + .kind = kHIThemeTabKindNormal, + .adornment = kHIThemeTabPaneAdornmentNormal, + }; + bounds.origin.y -= kThemeMetricTabFrameOverlap; + bounds.size.height += kThemeMetricTabFrameOverlap; + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING } static Ttk_ElementSpec PaneElementSpec = { TK_STYLE_VERSION_2, @@ -368,40 +1586,53 @@ TtkNullElementOptions, PaneElementSize, PaneElementDraw }; -/* - * Labelframe borders: - * Use "primary group box ..." - * Quoth DrawThemePrimaryGroup reference: - * "The primary group box frame is drawn inside the specified - * rectangle and is a maximum of 2 pixels thick." - * - * "Maximum of 2 pixels thick" is apparently a lie; - * looks more like 4 to me with shading. - */ +/*---------------------------------------------------------------------- + * +++ Labelframe elements -- + * + * Labelframe borders: Use "primary group box ..." Quoth + * DrawThemePrimaryGroup reference: "The primary group box frame is drawn + * inside the specified rectangle and is a maximum of 2 pixels thick." + * + * "Maximum of 2 pixels thick" is apparently a lie; looks more like 4 to me + * with shading. + */ + static void GroupElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(4); } static void GroupElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); - const HIThemeGroupBoxDrawInfo info = { - .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .kind = kHIThemeGroupBoxKindPrimaryOpaque, - }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); + if ([NSApp macMinorVersion] > 8) { + DrawGroupBox(bounds, dc.context, tkwin); + } else { + const HIThemeGroupBoxDrawInfo info = { + .version = 0, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .kind = kHIThemeGroupBoxKindPrimaryOpaque, + }; + ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING } static Ttk_ElementSpec GroupElementSpec = { TK_STYLE_VERSION_2, @@ -410,60 +1641,122 @@ GroupElementSize, GroupElementDraw }; /*---------------------------------------------------------------------- - * +++ Entry element -- - * 3 pixels padding for focus rectangle - * 2 pixels padding for EditTextFrame + * +++ Entry elements -- + * + * 3 pixels padding for focus rectangle + * 2 pixels padding for EditTextFrame */ typedef struct { - Tcl_Obj *backgroundObj; + Tcl_Obj *backgroundObj; + Tcl_Obj *fieldbackgroundObj; } EntryElement; +#define ENTRY_DEFAULT_BACKGROUND "systemTextBackgroundColor" + static Ttk_ElementOptionSpec EntryElementOptions[] = { - { "-background", TK_OPTION_BORDER, - Tk_Offset(EntryElement,backgroundObj), "white" }, + {"-background", TK_OPTION_BORDER, + offsetof(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND}, + {"-fieldbackground", TK_OPTION_BORDER, + offsetof(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND}, {0} }; static void EntryElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - *paddingPtr = Ttk_UniformPadding(5); + *paddingPtr = Ttk_MakePadding(7, 5, 7, 6); } static void EntryElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { EntryElement *e = elementRecord; - Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); CGRect bounds = BoxToRect(d, inner); - const HIThemeFrameDrawInfo info = { - .version = 0, - .kind = kHIThemeFrameTextFieldSquare, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .isFocused = state & TTK_STATE_FOCUS, - }; - - /* - * Erase w/background color: - */ - XFillRectangle(Tk_Display(tkwin), d, - Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - inner.x,inner.y, inner.width, inner.height); - - BEGIN_DRAWING(d) - ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); - /*if (state & TTK_STATE_FOCUS) { - ChkErr(DrawThemeFocusRect, &bounds, 1); - }*/ - END_DRAWING + NSColor *background; + Tk_3DBorder backgroundPtr = NULL; + static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND; + + if (TkMacOSXInDarkMode(tkwin)) { + BEGIN_DRAWING(d) + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGFloat fill[4]; + GetBackgroundColor(dc.context, tkwin, 1, fill); + + /* + * Lighten the background to provide contrast. + */ + + for (int i = 0; i < 3; i++) { + fill[i] += 9.0 / 255.0; + } + background = [NSColor colorWithColorSpace: deviceRGB + components: fill + count: 4]; + CGContextSetFillColorWithColor(dc.context, CGCOLOR(background)); + CGContextFillRect(dc.context, bounds); + if (state & TTK_STATE_FOCUS) { + DrawDarkFocusRing(bounds, dc.context); + } else { + DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare); + } + END_DRAWING + } else { + const HIThemeFrameDrawInfo info = { + .version = 0, + .kind = kHIThemeFrameTextFieldSquare, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .isFocused = state & TTK_STATE_FOCUS, + }; + + /* + * Earlier versions of the Aqua theme ignored the -fieldbackground + * option and used the -background as if it were -fieldbackground. + * Here we are enabling -fieldbackground. For backwards + * compatibility, if -fieldbackground is set to the default color and + * -background is set to a different color then we use -background as + * -fieldbackground. + */ + + if (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) { + backgroundPtr = + Tk_Get3DBorderFromObj(tkwin, e->fieldbackgroundObj); + } else if (0 != strcmp(Tcl_GetString(e->backgroundObj), defaultBG)) { + backgroundPtr = Tk_Get3DBorderFromObj(tkwin, e->backgroundObj); + } + if (backgroundPtr != NULL) { + XFillRectangle(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + inner.x, inner.y, inner.width, inner.height); + } + BEGIN_DRAWING(d) + if (backgroundPtr == NULL) { + if ([NSApp macMinorVersion] > 8) { + background = [NSColor textBackgroundColor]; + CGContextSetFillColorWithColor(dc.context, CGCOLOR(background)); + } else { + CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0); + } + CGContextFillRect(dc.context, bounds); + } + ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); + END_DRAWING + } } static Ttk_ElementSpec EntryElementSpec = { TK_STYLE_VERSION_2, sizeof(EntryElement), @@ -471,44 +1764,76 @@ EntryElementSize, EntryElementDraw }; /*---------------------------------------------------------------------- - * +++ Combobox: + * +++ Combobox elements -- * * NOTES: - * kThemeMetricComboBoxLargeDisclosureWidth -> 17 - * Padding and margins guesstimated by trial-and-error. + * The HIToolbox has incomplete and inconsistent support for ComboBoxes. + * There is no constant available to get the height of a ComboBox with + * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as + * PopupButtons and PushButtons, but they have no shadow at the bottom. + * As a result, they are drawn 1 pixel above the center of the bounds + * rectangle rather than being centered like the other buttons. One can + * request background bounds for a ComboBox, and it is reported with + * height 23, while the actual button face, including its 1-pixel border + * has height 21. Attempting to request the content bounds returns a 0x0 + * rectangle. Measurement indicates that the arrow button has width 18. + * + * With no help available from HIToolbox, we have to use hard-wired + * constants for the padding. We shift the bounding rectangle downward by + * 1 pixel to account for the fact that the button is not centered. */ -static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 }; -static Ttk_Padding ComboboxMargins = { 3, 3, 4, 4 }; +static Ttk_Padding ComboboxPadding = {4, 2, 20, 2}; static void ComboboxElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - *widthPtr = 0; - *heightPtr = 0; - *paddingPtr = Ttk_AddPadding(ComboboxMargins, ComboboxPadding); + *minWidth = 24; + *minHeight = 23; + *paddingPtr = ComboboxPadding; } static void ComboboxElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { - CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ComboboxMargins)); + CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = kThemeComboBox, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + bounds.origin.y += 1; + if (TkMacOSXInDarkMode(tkwin)) { + bounds.size.height += 1; + DrawDarkButton(bounds, info.kind, state, dc.context); + } else if ([NSApp macMinorVersion] > 8) { + if ((state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { + NSColor *background = [NSColor textBackgroundColor]; + CGRect innerBounds = CGRectInset(bounds, 1, 2); + SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); + } + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); + } END_DRAWING } static Ttk_ElementSpec ComboboxElementSpec = { TK_STYLE_VERSION_2, @@ -516,116 +1841,213 @@ TtkNullElementOptions, ComboboxElementSize, ComboboxElementDraw }; - - - - -/*---------------------------------------------------------------------- - * +++ Spinbuttons. - * - * From Apple HIG, part III, section "Controls", "The Stepper Control": - * there should be 2 pixels of space between the stepper control - * (AKA IncDecButton, AKA "little arrows") and the text field it modifies. +/*---------------------------------------------------------------------- + * +++ Spinbutton elements -- + * + * From Apple HIG, part III, section "Controls", "The Stepper Control": + * there should be 2 pixels of space between the stepper control (AKA + * IncDecButton, AKA "little arrows") and the text field it modifies. + * + * Ttk expects the up and down arrows to be distinct elements but + * HIToolbox draws them as one widget with two different pressed states. + * We work around this by defining them as separate elements in the + * layout, but making each one have a drawing method which also draws the + * other one. The down button does no drawing when not pressed, and when + * pressed draws the entire IncDecButton in its "pressed down" state. + * The up button draws the entire IncDecButton when not pressed and when + * pressed draws the IncDecButton in its "pressed up" state. NOTE: This + * means that when the down button is pressed the IncDecButton will be + * drawn twice, first in unpressed state by the up arrow and then in + * "pressed down" state by the down button. The drawing must be done in + * that order. So the up button must be listed first in the layout. */ -static Ttk_Padding SpinbuttonMargins = {2,0,2,0}; -static void SpinButtonElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0}; + +static void SpinButtonUpElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) +{ + SInt32 s; + + ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); + *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins); + ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); + *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2; +} + +static void SpinButtonUpElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) +{ + CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); + int infoState; + + bounds.size.height *= 2; + if (state & TTK_STATE_PRESSED) { + infoState = kThemeStatePressedUp; + } else { + infoState = Ttk_StateTableLookup(ThemeStateTable, state); + } + const HIThemeButtonDrawInfo info = { + .version = 0, + .state = infoState, + .kind = kThemeIncDecButton, + .value = Ttk_StateTableLookup(ButtonValueTable, state), + .adornment = kThemeAdornmentNone, + }; + BEGIN_DRAWING(d) + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkIncDecButton(bounds, infoState, state, dc.context); + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); + } + END_DRAWING +} + +static Ttk_ElementSpec SpinButtonUpElementSpec = { + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + SpinButtonUpElementSize, + SpinButtonUpElementDraw +}; +static void SpinButtonDownElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); - *widthPtr = s + Ttk_PaddingWidth(SpinbuttonMargins); + *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins); ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); - *heightPtr = s + Ttk_PaddingHeight(SpinbuttonMargins); + *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2; } -static void SpinButtonElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) +static void SpinButtonDownElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); - /* @@@ can't currently distinguish PressedUp (== Pressed) from PressedDown; - * ignore this bit for now [see #2219588] - */ + int infoState = 0; + + bounds.origin.y -= bounds.size.height; + bounds.size.height *= 2; + if (state & TTK_STATE_PRESSED) { + infoState = kThemeStatePressedDown; + } else { + return; + } const HIThemeButtonDrawInfo info = { .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state & ~TTK_STATE_PRESSED), + .state = infoState, .kind = kThemeIncDecButton, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = kThemeAdornmentNone, }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkIncDecButton(bounds, infoState, state, dc.context); + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); + } END_DRAWING } -static Ttk_ElementSpec SpinButtonElementSpec = { +static Ttk_ElementSpec SpinButtonDownElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - SpinButtonElementSize, - SpinButtonElementDraw + SpinButtonDownElementSize, + SpinButtonDownElementDraw }; - /*---------------------------------------------------------------------- * +++ DrawThemeTrack-based elements -- - * Progress bars and scales. (See also: <>) + * + * Progress bars and scales. (See also: <>) + */ + +/* + * Apple does not change the appearance of a slider when the window becomes + * inactive. So we shouldn't either. */ static Ttk_StateTable ThemeTrackEnableTable[] = { - { kThemeTrackDisabled, TTK_STATE_DISABLED, 0 }, - { kThemeTrackInactive, TTK_STATE_BACKGROUND, 0 }, - { kThemeTrackActive, 0, 0 } + {kThemeTrackDisabled, TTK_STATE_DISABLED, 0}, + {kThemeTrackActive, TTK_STATE_BACKGROUND, 0}, + {kThemeTrackActive, 0, 0} /* { kThemeTrackNothingToScroll, ?, ? }, */ }; -typedef struct { /* TrackElement client data */ - ThemeTrackKind kind; - SInt32 thicknessMetric; +typedef struct { /* TrackElement client data */ + ThemeTrackKind kind; + SInt32 thicknessMetric; } TrackElementData; static TrackElementData ScaleData = { kThemeSlider, kThemeMetricHSliderHeight }; - typedef struct { - Tcl_Obj *fromObj; /* minimum value */ - Tcl_Obj *toObj; /* maximum value */ - Tcl_Obj *valueObj; /* current value */ - Tcl_Obj *orientObj; /* horizontal / vertical */ + Tcl_Obj *fromObj; /* minimum value */ + Tcl_Obj *toObj; /* maximum value */ + Tcl_Obj *valueObj; /* current value */ + Tcl_Obj *orientObj; /* horizontal / vertical */ } TrackElement; static Ttk_ElementOptionSpec TrackElementOptions[] = { - { "-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,fromObj) }, - { "-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,toObj) }, - { "-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,valueObj) }, - { "-orient", TK_OPTION_STRING, Tk_Offset(TrackElement,orientObj) }, - {0,0,0} + {"-from", TK_OPTION_DOUBLE, offsetof(TrackElement, fromObj)}, + {"-to", TK_OPTION_DOUBLE, offsetof(TrackElement, toObj)}, + {"-value", TK_OPTION_DOUBLE, offsetof(TrackElement, valueObj)}, + {"-orient", TK_OPTION_STRING, offsetof(TrackElement, orientObj)}, + {0, 0, 0} }; - static void TrackElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { TrackElementData *data = clientData; - SInt32 size = 24; /* reasonable default ... */ + SInt32 size = 24; /* reasonable default ... */ ChkErr(GetThemeMetric, data->thicknessMetric, &size); - *widthPtr = *heightPtr = size; + *minWidth = *minHeight = size; } static void TrackElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { TrackElementData *data = clientData; TrackElement *elem = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; double from = 0, to = 100, value = 0, factor; @@ -642,24 +2064,39 @@ .bounds = BoxToRect(d, b), .min = from * factor, .max = to * factor, .value = value * factor, .attributes = kThemeTrackShowThumb | - (orientation == TTK_ORIENT_HORIZONTAL ? - kThemeTrackHorizontal : 0), + (orientation == TTK_ORIENT_HORIZONTAL ? + kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), .trackInfo.progress.phase = 0, }; if (info.kind == kThemeSlider) { info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ? - kThemeThumbPressed : 0; - info.trackInfo.slider.thumbDir = kThemeThumbPlain; + kThemeThumbPressed : 0; + if (state & TTK_STATE_ALTERNATE) { + info.trackInfo.slider.thumbDir = kThemeThumbDownward; + } else { + info.trackInfo.slider.thumbDir = kThemeThumbPlain; + } } - - BEGIN_DRAWING(d) + if (TkMacOSXInDarkMode(tkwin)) { + CGRect bounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB + components: darkTrack + count: 4]; + if (orientation == TTK_ORIENT_HORIZONTAL) { + bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 2); + } else { + bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 2); + } + SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor); + } ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec TrackElementSpec = { @@ -668,25 +2105,28 @@ TrackElementOptions, TrackElementSize, TrackElementDraw }; -/* - * Slider element -- <> +/*---------------------------------------------------------------------- + * Slider elements -- <> + * * Has geometry only. The Scale widget adjusts the position of this element, * and uses it for hit detection. In the Aqua theme, the slider is actually * drawn as part of the trough element. * - * Also buggy: The geometry here is a Wild-Assed-Guess; I can't - * figure out how to get the Appearance Manager to tell me the - * slider size. */ + static void SliderElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - *widthPtr = *heightPtr = 24; + *minWidth = *minHeight = 24; } static Ttk_ElementSpec SliderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), @@ -694,52 +2134,59 @@ SliderElementSize, TtkNullElementDraw }; /*---------------------------------------------------------------------- - * +++ Progress bar element (new): + * +++ Progress bar elements -- * * @@@ NOTE: According to an older revision of the Aqua reference docs, * @@@ the 'phase' field is between 0 and 4. Newer revisions say * @@@ that it can be any UInt8 value. */ typedef struct { - Tcl_Obj *orientObj; /* horizontal / vertical */ - Tcl_Obj *valueObj; /* current value */ - Tcl_Obj *maximumObj; /* maximum value */ - Tcl_Obj *phaseObj; /* animation phase */ - Tcl_Obj *modeObj; /* progress bar mode */ + Tcl_Obj *orientObj; /* horizontal / vertical */ + Tcl_Obj *valueObj; /* current value */ + Tcl_Obj *maximumObj; /* maximum value */ + Tcl_Obj *phaseObj; /* animation phase */ + Tcl_Obj *modeObj; /* progress bar mode */ } PbarElement; static Ttk_ElementOptionSpec PbarElementOptions[] = { - { "-orient", TK_OPTION_STRING, - Tk_Offset(PbarElement,orientObj), "horizontal" }, - { "-value", TK_OPTION_DOUBLE, - Tk_Offset(PbarElement,valueObj), "0" }, - { "-maximum", TK_OPTION_DOUBLE, - Tk_Offset(PbarElement,maximumObj), "100" }, - { "-phase", TK_OPTION_INT, - Tk_Offset(PbarElement,phaseObj), "0" }, - { "-mode", TK_OPTION_STRING, - Tk_Offset(PbarElement,modeObj), "determinate" }, - {0,0,0,0} + {"-orient", TK_OPTION_STRING, + offsetof(PbarElement, orientObj), "horizontal"}, + {"-value", TK_OPTION_DOUBLE, + offsetof(PbarElement, valueObj), "0"}, + {"-maximum", TK_OPTION_DOUBLE, + offsetof(PbarElement, maximumObj), "100"}, + {"-phase", TK_OPTION_INT, + offsetof(PbarElement, phaseObj), "0"}, + {"-mode", TK_OPTION_STRING, + offsetof(PbarElement, modeObj), "determinate"}, + {0, 0, 0, 0} }; - static void PbarElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - SInt32 size = 24; /* @@@ Check HIG for correct default */ + SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); - *widthPtr = *heightPtr = size; + *minWidth = *minHeight = size; } static void PbarElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { PbarElement *pbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL, phase = 0; double value = 0, maximum = 100, factor; @@ -749,24 +2196,39 @@ Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase); factor = RangeToFactor(maximum); HIThemeTrackDrawInfo info = { .version = 0, - .kind = (!strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) && value) ? - kThemeIndeterminateBar : kThemeProgressBar, + .kind = + (!strcmp("indeterminate", + Tcl_GetString(pbar->modeObj)) && value) ? + kThemeIndeterminateBar : kThemeProgressBar, .bounds = BoxToRect(d, b), .min = 0, .max = maximum * factor, .value = value * factor, .attributes = kThemeTrackShowThumb | - (orientation == TTK_ORIENT_HORIZONTAL ? - kThemeTrackHorizontal : 0), + (orientation == TTK_ORIENT_HORIZONTAL ? + kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), .trackInfo.progress.phase = phase, }; BEGIN_DRAWING(d) + if (TkMacOSXInDarkMode(tkwin)) { + CGRect bounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB + components: darkTrack + count: 4]; + if (orientation == TTK_ORIENT_HORIZONTAL) { + bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 3); + } else { + bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 1); + } + SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor); + } ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec PbarElementSpec = { @@ -774,39 +2236,309 @@ sizeof(PbarElement), PbarElementOptions, PbarElementSize, PbarElementDraw }; + +/*---------------------------------------------------------------------- + * +++ Scrollbar elements + */ + +typedef struct +{ + Tcl_Obj *orientObj; +} ScrollbarElement; + +static Ttk_ElementOptionSpec ScrollbarElementOptions[] = { + {"-orient", TK_OPTION_STRING, + offsetof(ScrollbarElement, orientObj), "horizontal"}, + {0, 0, 0, 0} +}; +static void TroughElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + SInt32 thickness = 15; + + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); + if (orientation == TTK_ORIENT_HORIZONTAL) { + *minHeight = thickness; + if ([NSApp macMinorVersion] > 7) { + *paddingPtr = Ttk_MakePadding(4, 4, 4, 3); + } + } else { + *minWidth = thickness; + if ([NSApp macMinorVersion] > 7) { + *paddingPtr = Ttk_MakePadding(4, 4, 3, 4); + } + } +} + +static CGFloat lightTrough[4] = {250.0 / 255, 250.0 / 255, 250.0 / 255, 1.0}; +static CGFloat darkTrough[4] = {45.0 / 255, 46.0 / 255, 49.0 / 255, 1.0}; +static CGFloat lightInactiveThumb[4] = { + 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0 +}; +static CGFloat lightActiveThumb[4] = { + 133.0 / 255, 133.0 / 255, 133.0 / 255, 1.0 +}; +static CGFloat darkInactiveThumb[4] = { + 116.0 / 255, 117.0 / 255, 118.0 / 255, 1.0 +}; +static CGFloat darkActiveThumb[4] = { + 158.0 / 255, 158.0 / 255, 159.0 / 255, 1.0 +}; +static void TroughElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + CGRect bounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *troughColor; + CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough; + + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + if (orientation == TTK_ORIENT_HORIZONTAL) { + bounds = CGRectInset(bounds, 0, 1); + } else { + bounds = CGRectInset(bounds, 1, 0); + } + troughColor = [NSColor colorWithColorSpace: deviceRGB + components: rgba + count: 4]; + BEGIN_DRAWING(d) + if ([NSApp macMinorVersion] > 8) { + CGContextSetFillColorWithColor(dc.context, CGCOLOR(troughColor)); + } else { + ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL, + dc.context, HIOrientation); + } + CGContextFillRect(dc.context, bounds); + END_DRAWING +} + +static Ttk_ElementSpec TroughElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + TroughElementSize, + TroughElementDraw +}; +static void ThumbElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + if (orientation == TTK_ORIENT_VERTICAL) { + *minHeight = 18; + *minWidth = 8; + } else { + *minHeight = 8; + *minWidth = 18; + } +} + +static void ThumbElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + + /* + * In order to make ttk scrollbars work correctly it is necessary to be + * able to display the thumb element at the size and location which the ttk + * scrollbar widget requests. The algorithm that HIToolbox uses to + * determine the thumb geometry from the input values of min, max, value + * and viewSize is undocumented. A seemingly natural algorithm is + * implemented below. This code uses that algorithm for older OS versions, + * because using HITools also handles drawing the buttons and 3D thumb used + * on those systems. For newer systems the cleanest approach is to just + * draw the thumb directly. + */ + + if ([NSApp macMinorVersion] > 8) { + CGRect thumbBounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *thumbColor; + CGFloat *rgba; + if ((orientation == TTK_ORIENT_HORIZONTAL && + thumbBounds.size.width >= Tk_Width(tkwin) - 8) || + (orientation == TTK_ORIENT_VERTICAL && + thumbBounds.size.height >= Tk_Height(tkwin) - 8)) { + return; + } + int isDark = TkMacOSXInDarkMode(tkwin); + if ((state & TTK_STATE_PRESSED) || + (state & TTK_STATE_HOVER)) { + rgba = isDark ? darkActiveThumb : lightActiveThumb; + } else { + rgba = isDark ? darkInactiveThumb : lightInactiveThumb; + } + thumbColor = [NSColor colorWithColorSpace: deviceRGB + components: rgba + count: 4]; + BEGIN_DRAWING(d) + SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); + END_DRAWING + } else { + double thumbSize, trackSize, visibleSize, factor, fraction; + MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); + CGRect troughBounds = {{macWin->xOff, macWin->yOff}, + {Tk_Width(tkwin), Tk_Height(tkwin)}}; + + /* + * The info struct has integer fields, which will be converted to + * floats in the drawing routine. All of values provided in the info + * struct, namely min, max, value, and viewSize are only defined up to + * an arbitrary scale factor. To avoid roundoff error we scale so + * that the viewSize is a large float which is smaller than the + * largest int. + */ + + HIThemeTrackDrawInfo info = { + .version = 0, + .bounds = troughBounds, + .min = 0, + .attributes = kThemeTrackShowThumb | + kThemeTrackThumbRgnIsNotGhost, + .enableState = kThemeTrackActive + }; + factor = RangeToFactor(100.0); + if (orientation == TTK_ORIENT_HORIZONTAL) { + trackSize = troughBounds.size.width; + thumbSize = b.width; + fraction = b.x / trackSize; + } else { + trackSize = troughBounds.size.height; + thumbSize = b.height; + fraction = b.y / trackSize; + } + visibleSize = (thumbSize / trackSize) * factor; + info.max = factor - visibleSize; + info.trackInfo.scrollbar.viewsize = visibleSize; + if ([NSApp macMinorVersion] < 8 || + orientation == TTK_ORIENT_HORIZONTAL) { + info.value = factor * fraction; + } else { + info.value = info.max - factor * fraction; + } + if ((state & TTK_STATE_PRESSED) || + (state & TTK_STATE_HOVER)) { + info.trackInfo.scrollbar.pressState = kThemeThumbPressed; + } else { + info.trackInfo.scrollbar.pressState = 0; + } + if (orientation == TTK_ORIENT_HORIZONTAL) { + info.attributes |= kThemeTrackHorizontal; + } else { + info.attributes &= ~kThemeTrackHorizontal; + } + BEGIN_DRAWING(d) + HIThemeDrawTrack(&info, 0, dc.context, kHIThemeOrientationNormal); + END_DRAWING + } +} + +static Ttk_ElementSpec ThumbElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + ThumbElementSize, + ThumbElementDraw +}; +static void ArrowElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) +{ + if ([NSApp macMinorVersion] < 8) { + *minHeight = *minWidth = 14; + } else { + *minHeight = *minWidth = -1; + } +} + +static Ttk_ElementSpec ArrowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + ArrowElementSize, + TtkNullElementDraw +}; /*---------------------------------------------------------------------- * +++ Separator element. * - * DrawThemeSeparator() guesses the orientation of the line from - * the width and height of the rectangle, so the same element can - * can be used for horizontal, vertical, and general separators. + * DrawThemeSeparator() guesses the orientation of the line from the width + * and height of the rectangle, so the same element can can be used for + * horizontal, vertical, and general separators. */ static void SeparatorElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - *widthPtr = *heightPtr = 1; + *minWidth = *minHeight = 1; } static void SeparatorElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, unsigned int state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) { CGRect bounds = BoxToRect(d, b); const HIThemeSeparatorDrawInfo info = { .version = 0, - /* Separator only supports kThemeStateActive, kThemeStateInactive */ - .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), + /* Separator only supports kThemeStateActive, kThemeStateInactive */ + .state = Ttk_StateTableLookup(ThemeStateTable, + state & TTK_STATE_BACKGROUND), }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkSeparator(bounds, dc.context, tkwin); + } else { + ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, + HIOrientation); + } END_DRAWING } static Ttk_ElementSpec SeparatorElementSpec = { TK_STYLE_VERSION_2, @@ -815,18 +2547,23 @@ SeparatorElementSize, SeparatorElementDraw }; /*---------------------------------------------------------------------- - * +++ Size grip element. + * +++ Size grip elements -- (obsolete) */ + static const ThemeGrowDirection sizegripGrowDirection - = kThemeGrowRight|kThemeGrowDown; + = kThemeGrowRight | kThemeGrowDown; static void SizegripElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { HIThemeGrowBoxDrawInfo info = { .version = 0, .state = kThemeStateActive, .kind = kHIThemeGrowBoxKindNormal, @@ -834,30 +2571,36 @@ .size = kHIThemeGrowBoxSizeNormal, }; CGRect bounds = CGRectZero; ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds); - *widthPtr = bounds.size.width; - *heightPtr = bounds.size.height; + *minWidth = bounds.size.width; + *minHeight = bounds.size.height; } static void SizegripElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, unsigned int state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) { CGRect bounds = BoxToRect(d, b); HIThemeGrowBoxDrawInfo info = { .version = 0, - /* Grow box only supports kThemeStateActive, kThemeStateInactive */ - .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), + /* Grow box only supports kThemeStateActive, kThemeStateInactive */ + .state = Ttk_StateTableLookup(ThemeStateTable, + state & TTK_STATE_BACKGROUND), .kind = kHIThemeGrowBoxKindNormal, .direction = sizegripGrowDirection, .size = kHIThemeGrowBoxSizeNormal, }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, HIOrientation); + ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, + HIOrientation); END_DRAWING } static Ttk_ElementSpec SizegripElementSpec = { TK_STYLE_VERSION_2, @@ -866,54 +2609,106 @@ SizegripElementSize, SizegripElementDraw }; /*---------------------------------------------------------------------- - * +++ Background and fill elements. - * - * This isn't quite right: In Aqua, the correct background for - * a control depends on what kind of container it belongs to, - * and the type of the top-level window. - * - * Also: patterned backgrounds should be aligned with the coordinate - * system of the top-level window. If we're drawing into an - * off-screen graphics port this leads to alignment glitches. + * +++ Background and fill elements -- + * + * Before drawing any ttk widget, its bounding rectangle is filled with a + * background color. This color must match the background color of the + * containing widget to avoid looking ugly. The need for care when doing + * this is exacerbated by the fact that ttk enforces its "native look" by + * not allowing user control of the background or highlight colors of ttk + * widgets. + * + * This job is made more complicated in recent versions of macOS by the + * fact that the Appkit GroupBox (used for ttk LabelFrames) and + * TabbedPane (used for the Notebook widget) both place their content + * inside a rectangle with rounded corners that has a color which + * contrasts with the dialog background color. Moreover, although the + * Apple human interface guidelines recommend against doing so, there are + * times when one wants to nest these widgets, for example placing a + * GroupBox inside of a TabbedPane. To have the right contrast, each + * level of nesting requires a different color. + * + * Previous Tk releases used the HIThemeDrawGroupBox routine to draw + * GroupBoxes and TabbedPanes. This meant that the best that could be + * done was to set the GroupBox to be of kind + * kHIThemeGroupBoxKindPrimaryOpaque, and set its fill color to be the + * system background color. If widgets inside the box were drawn with + * the system background color the backgrounds would match. But this + * produces a GroupBox with no contrast, the only visual clue being a + * faint highlighting around the top of the GroupBox. Moreover, the + * TabbedPane does not have an Opaque version, so while it is drawn + * inside a contrasting rounded rectangle, the widgets inside the pane + * needed to be enclosed in a frame with the system background + * color. This added a visual artifact since the frame's background color + * does not match the Pane's background color. That code has now been + * replaced with the standalone drawing procedure macOSXDrawGroupBox, + * which draws a rounded rectangle with an appropriate contrasting + * background color. + * + * Patterned backgrounds, which are now obsolete, should be aligned with + * the coordinate system of the top-level window. Apparently failing to + * do this used to cause graphics anomalies when drawing into an + * off-screen graphics port. The code for handling this is currently + * commented out. */ static void FillElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); - ThemeBrush brush = (state & TTK_STATE_BACKGROUND) + + if ([NSApp macMinorVersion] > 8) { + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *bgColor; + CGFloat fill[4]; + BEGIN_DRAWING(d) + GetBackgroundColor(dc.context, tkwin, 0, fill); + bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill + count: 4]; + CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); + CGContextSetFillColorWithColor(dc.context, CGCOLOR(bgColor)); + CGContextFillRect(dc.context, bounds); + END_DRAWING + } else { + ThemeBrush brush = (state & TTK_STATE_BACKGROUND) ? kThemeBrushModelessDialogBackgroundInactive : kThemeBrushModelessDialogBackgroundActive; - - BEGIN_DRAWING(d) - ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); - //QDSetPatternOrigin(PatternOrigin(tkwin, d)); - CGContextFillRect(dc.context, bounds); - END_DRAWING + BEGIN_DRAWING(d) + ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); + //QDSetPatternOrigin(PatternOrigin(tkwin, d)); + CGContextFillRect(dc.context, bounds); + END_DRAWING + } } static void BackgroundElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, unsigned int state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) { - FillElementDraw( - clientData, elementRecord, tkwin, - d, Ttk_WinBox(tkwin), state); + FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin), + state); } static Ttk_ElementSpec FillElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, TtkNullElementSize, FillElementDraw }; - static Ttk_ElementSpec BackgroundElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, TtkNullElementSize, @@ -921,23 +2716,28 @@ }; /*---------------------------------------------------------------------- * +++ ToolbarBackground element -- toolbar style for frames. * - * This is very similar to the normal background element, but uses a - * different ThemeBrush in order to get the lighter pinstripe effect - * used in toolbars. We use SetThemeBackground() rather than - * ApplyThemeBackground() in order to get the right style. - * - * + * This is very similar to the normal background element, but uses a + * different ThemeBrush in order to get the lighter pinstripe effect + * used in toolbars. We use SetThemeBackground() rather than + * ApplyThemeBackground() in order to get the right style. + * + * * */ + static void ToolbarBackgroundElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ThemeBrush brush = kThemeBrushToolbarBackground; CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin)); BEGIN_DRAWING(d) @@ -954,34 +2754,125 @@ TtkNullElementSize, ToolbarBackgroundElementDraw }; /*---------------------------------------------------------------------- - * +++ Treeview header - * Redefine the header to use a kThemeListHeaderButton. + * +++ Field elements -- + * + * Used for the Treeview widget. This is like the BackgroundElement + * except that the fieldbackground color is configureable. + */ + +typedef struct { + Tcl_Obj *backgroundObj; +} FieldElement; + +static Ttk_ElementOptionSpec FieldElementOptions[] = { + {"-fieldbackground", TK_OPTION_BORDER, + offsetof(FieldElement, backgroundObj), "white"}, + {NULL, 0, 0, NULL} +}; + +static void FieldElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) +{ + FieldElement *e = elementRecord; + Tk_3DBorder backgroundPtr = + Tk_Get3DBorderFromObj(tkwin, e->backgroundObj); + + XFillRectangle(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + b.x, b.y, b.width, b.height); +} + +static Ttk_ElementSpec FieldElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + TtkNullElementSize, + FieldElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Treeview headers -- + * + * On systems older than 10.9 The header is a kThemeListHeaderButton drawn + * by HIToolbox. On newer systems those buttons do not match the Apple + * buttons, so we draw them from scratch. */ -#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 static Ttk_StateTable TreeHeaderValueTable[] = { - { kThemeButtonOn, TTK_STATE_ALTERNATE}, - { kThemeButtonOn, TTK_STATE_SELECTED}, - { kThemeButtonOff, 0} + {kThemeButtonOn, TTK_STATE_ALTERNATE}, + {kThemeButtonOn, TTK_STATE_SELECTED}, + {kThemeButtonOff, 0} }; + static Ttk_StateTable TreeHeaderAdornmentTable[] = { - { kThemeAdornmentHeaderButtonSortUp, - TTK_STATE_ALTERNATE|TTK_TREEVIEW_STATE_SORTARROW}, - { kThemeAdornmentDefault, - TTK_STATE_SELECTED|TTK_TREEVIEW_STATE_SORTARROW}, - { kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE}, - { kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED}, - { kThemeAdornmentFocus, TTK_STATE_FOCUS}, - { kThemeAdornmentNone, 0} + {kThemeAdornmentHeaderButtonSortUp, + TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW}, + {kThemeAdornmentDefault, + TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW}, + {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE}, + {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED}, + {kThemeAdornmentFocus, TTK_STATE_FOCUS}, + {kThemeAdornmentNone, 0} +}; + +static void TreeAreaElementSize ( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) +{ + + /* + * Padding is needed to get the heading text to align correctly, since the + * widget expects the heading to be the same height as a row. + */ + + if ([NSApp macMinorVersion] > 8) { + paddingPtr->top = 4; + } +} + +static Ttk_ElementSpec TreeAreaElementSpec = { + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + TreeAreaElementSize, + TtkNullElementDraw }; +static void TreeHeaderElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) +{ + if ([NSApp macMinorVersion] > 8) { + *minHeight = 24; + } else { + ButtonElementSize(clientData, elementRecord, tkwin, minWidth, + minHeight, paddingPtr); + } +} static void TreeHeaderElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, @@ -990,60 +2881,87 @@ .value = Ttk_StateTableLookup(TreeHeaderValueTable, state), .adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state), }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + if ([NSApp macMinorVersion] > 8) { + + /* + * Compensate for the padding added in TreeHeaderElementSize, so + * the larger heading will be drawn at the top of the widget. + */ + + bounds.origin.y -= 4; + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkListHeader(bounds, dc.context, tkwin, state); + } else { + DrawListHeader(bounds, dc.context, tkwin, state); + } + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); + } END_DRAWING } static Ttk_ElementSpec TreeHeaderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - ButtonElementSizeNoPadding, + TreeHeaderElementSize, TreeHeaderElementDraw }; -/* - * Disclosure triangle: +/*---------------------------------------------------------------------- + * +++ Disclosure triangles -- */ -#define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 -#define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 + +#define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 +#define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 static Ttk_StateTable DisclosureValueTable[] = { - { kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0 }, - { kThemeDisclosureRight, 0, 0 }, + {kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0}, + {kThemeDisclosureRight, 0, 0}, }; - static void DisclosureElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s); - *widthPtr = s; + *minWidth = s; ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s); - *heightPtr = s; + *minHeight = s; } static void DisclosureElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { if (!(state & TTK_TREEVIEW_STATE_LEAF)) { + int triangleState = TkMacOSXInDarkMode(tkwin) ? + kThemeStateInactive : kThemeStateActive; CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), + .state = triangleState, .kind = kThemeDisclosureTriangle, .value = Ttk_StateTableLookup(DisclosureValueTable, state), .adornment = kThemeAdornmentDrawIndicatorOnly, }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); END_DRAWING } } static Ttk_ElementSpec DisclosureElementSpec = { @@ -1053,78 +2971,104 @@ DisclosureElementSize, DisclosureElementDraw }; /*---------------------------------------------------------------------- - * +++ Widget layouts. + * +++ Widget layouts -- */ TTK_BEGIN_LAYOUT_TABLE(LayoutTable) TTK_LAYOUT("Toolbar", TTK_NODE("Toolbar.background", TTK_FILL_BOTH)) TTK_LAYOUT("TButton", TTK_GROUP("Button.button", TTK_FILL_BOTH, - TTK_GROUP("Button.padding", TTK_FILL_BOTH, - TTK_NODE("Button.label", TTK_FILL_BOTH)))) + TTK_GROUP("Button.padding", TTK_FILL_BOTH, + TTK_NODE("Button.label", TTK_FILL_BOTH)))) TTK_LAYOUT("TRadiobutton", TTK_GROUP("Radiobutton.button", TTK_FILL_BOTH, - TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, - TTK_NODE("Radiobutton.label", TTK_PACK_LEFT)))) + TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, + TTK_NODE("Radiobutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TCheckbutton", TTK_GROUP("Checkbutton.button", TTK_FILL_BOTH, - TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, - TTK_NODE("Checkbutton.label", TTK_PACK_LEFT)))) + TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, + TTK_NODE("Checkbutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TMenubutton", TTK_GROUP("Menubutton.button", TTK_FILL_BOTH, - TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH, - TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) + TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH, + TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TCombobox", - TTK_GROUP("Combobox.button", TTK_PACK_TOP|TTK_FILL_X, - TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, - TTK_NODE("Combobox.textarea", TTK_FILL_X)))) + TTK_GROUP("Combobox.button", TTK_FILL_BOTH, + TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, + TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))) /* Notebook tabs -- no focus ring */ TTK_LAYOUT("Tab", TTK_GROUP("Notebook.tab", TTK_FILL_BOTH, - TTK_GROUP("Notebook.padding", TTK_EXPAND|TTK_FILL_BOTH, - TTK_NODE("Notebook.label", TTK_EXPAND|TTK_FILL_BOTH)))) + TTK_GROUP("Notebook.padding", TTK_EXPAND | TTK_FILL_BOTH, + TTK_NODE("Notebook.label", TTK_EXPAND | TTK_FILL_BOTH)))) + +/* Spinbox -- buttons 2px to the right of the field. */ +TTK_LAYOUT("TSpinbox", + TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT, + TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP | TTK_STICK_E) + TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM | TTK_STICK_E)) + TTK_GROUP("Spinbox.field", TTK_EXPAND | TTK_FILL_X, + TTK_NODE("Spinbox.textarea", TTK_EXPAND | TTK_FILL_X))) /* Progress bars -- track only */ -TTK_LAYOUT("TSpinbox", - TTK_NODE("Spinbox.spinbutton", TTK_PACK_RIGHT|TTK_STICK_E) - TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X, - TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X))) - TTK_LAYOUT("TProgressbar", - TTK_NODE("Progressbar.track", TTK_EXPAND|TTK_FILL_BOTH)) + TTK_NODE("Progressbar.track", TTK_EXPAND | TTK_FILL_BOTH)) + +/* Treeview -- no border. */ +TTK_LAYOUT("Treeview", + TTK_GROUP("Treeview.field", TTK_FILL_BOTH, + TTK_GROUP("Treeview.padding", TTK_FILL_BOTH, + TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) /* Tree heading -- no border, fixed height */ TTK_LAYOUT("Heading", - TTK_NODE("Treeheading.cell", TTK_FILL_X) + TTK_NODE("Treeheading.cell", TTK_FILL_BOTH) TTK_NODE("Treeheading.image", TTK_PACK_RIGHT) - TTK_NODE("Treeheading.text", 0)) + TTK_NODE("Treeheading.text", TTK_PACK_TOP)) /* Tree items -- omit focus ring */ TTK_LAYOUT("Item", TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH, - TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) - TTK_NODE("Treeitem.image", TTK_PACK_LEFT) - TTK_NODE("Treeitem.text", TTK_PACK_LEFT))) + TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) + TTK_NODE("Treeitem.image", TTK_PACK_LEFT) + TTK_NODE("Treeitem.text", TTK_PACK_LEFT))) + +/* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */ + +TTK_LAYOUT("Vertical.TScrollbar", + TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y, + TTK_NODE("Vertical.Scrollbar.thumb", + TTK_PACK_TOP | TTK_EXPAND | TTK_FILL_BOTH) + TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM) + TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM))) + +TTK_LAYOUT("Horizontal.TScrollbar", + TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X, + TTK_NODE("Horizontal.Scrollbar.thumb", + TTK_PACK_LEFT | TTK_EXPAND | TTK_FILL_BOTH) + TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT) + TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT))) TTK_END_LAYOUT_TABLE /*---------------------------------------------------------------------- - * +++ Initialization. + * +++ Initialization -- */ -static int AquaTheme_Init(Tcl_Interp *interp) +static int AquaTheme_Init( + Tcl_Interp *interp) { Ttk_Theme themePtr = Ttk_CreateTheme(interp, "aqua", NULL); if (!themePtr) { return TCL_ERROR; @@ -1131,12 +3075,15 @@ } /* * Elements: */ - Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, 0); + + Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, + 0); Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Toolbar.background", &ToolbarBackgroundElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Button.button", &ButtonElementSpec, &PushButtonParams); @@ -1146,62 +3093,94 @@ &ButtonElementSpec, &RadioButtonParams); Ttk_RegisterElementSpec(themePtr, "Toolbutton.border", &ButtonElementSpec, &BevelButtonParams); Ttk_RegisterElementSpec(themePtr, "Menubutton.button", &ButtonElementSpec, &PopupButtonParams); - Ttk_RegisterElementSpec(themePtr, "Spinbox.spinbutton", - &SpinButtonElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.uparrow", + &SpinButtonUpElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.downarrow", + &SpinButtonDownElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Combobox.button", &ComboboxElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator", &DisclosureElementSpec, &DisclosureParams); Ttk_RegisterElementSpec(themePtr, "Treeheading.cell", &TreeHeaderElementSpec, &ListHeaderParams); + Ttk_RegisterElementSpec(themePtr, "Treeview.treearea", + &TreeAreaElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "Labelframe.border",&GroupElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "Entry.field",&EntryElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "Spinbox.field",&EntryElementSpec,0); - - Ttk_RegisterElementSpec(themePtr, "separator",&SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "hseparator",&SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "vseparator",&SeparatorElementSpec,0); - - Ttk_RegisterElementSpec(themePtr, "sizegrip",&SizegripElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec, + 0); + Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec, 0); + + Ttk_RegisterElementSpec(themePtr, "separator", &SeparatorElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "hseparator", &SeparatorElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "vseparator", &SeparatorElementSpec, 0); + + Ttk_RegisterElementSpec(themePtr, "sizegrip", &SizegripElementSpec, 0); /* * <> - * The Progressbar widget adjusts the size of the pbar element. - * In the Aqua theme, the appearance manager computes the bar geometry; - * we do all the drawing in the ".track" element and leave the .pbar out. + * In some themes the Layouts for a progress bar has a trough element and a + * pbar element. But in our case the appearance manager draws both parts + * of the progress bar, so we just have a single element called ".track". + */ + + Ttk_RegisterElementSpec(themePtr, "Progressbar.track", &PbarElementSpec, + 0); + + Ttk_RegisterElementSpec(themePtr, "Scale.trough", &TrackElementSpec, + &ScaleData); + Ttk_RegisterElementSpec(themePtr, "Scale.slider", &SliderElementSpec, 0); + + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.trough", + &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.thumb", + &ThumbElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.trough", + &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.thumb", + &ThumbElementSpec, 0); + + /* + * If we are not in Snow Leopard or Lion the arrows won't actually be + * displayed. */ - Ttk_RegisterElementSpec(themePtr,"Scale.trough", - &TrackElementSpec, &ScaleData); - Ttk_RegisterElementSpec(themePtr,"Scale.slider",&SliderElementSpec,0); - Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0); + + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.uparrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.downarrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.leftarrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.rightarrow", + &ArrowElementSpec, 0); /* * Layouts: */ + Ttk_RegisterLayouts(themePtr, LayoutTable); Tcl_PkgProvide(interp, "ttk::theme::aqua", TTK_VERSION); return TCL_OK; } MODULE_SCOPE -int Ttk_MacOSXPlatformInit(Tcl_Interp *interp) +int Ttk_MacOSXPlatformInit( + Tcl_Interp *interp) { return AquaTheme_Init(interp); } - + /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ - Index: tests/arc.tcl ================================================================== --- tests/arc.tcl +++ tests/arc.tcl @@ -97,11 +97,11 @@ set curx %x set cury %y } bind .t.c { - .t.c move circle [expr %x-$curx] [expr %y-$cury] + .t.c move circle [expr {%x-$curx}] [expr {%y-$cury}] set curx %x set cury %y } # The binding below flashes the closest item to the mouse. @@ -125,11 +125,11 @@ if {$i <= 5} { set delta 5 } incr i $delta c -start $i - c -extent [expr 360-2*$i] + c -extent [expr {360-2*$i}] after 20 update } } Index: tests/bell.test ================================================================== --- tests/bell.test +++ tests/bell.test @@ -13,11 +13,11 @@ test bell-1.1 {bell command} -body { bell a } -returnCodes {error} -result {bad option "a": must be -displayof or -nice} test bell-1.2 {bell command} -body { - bell a b + bell a b } -returnCodes {error} -result {bad option "a": must be -displayof or -nice} test bell-1.3 {bell command} -body { bell -displayof gorp } -returnCodes {error} -result {bad window path name "gorp"} Index: tests/bind.test ================================================================== --- tests/bind.test +++ tests/bind.test @@ -5918,11 +5918,11 @@ } -cleanup { destroy .t.f } -result {X x {keysym X}} -test bind-29.1 {Tk_BackgroundError procedure} -setup { +test bind-29.1 {Tcl_BackgroundError procedure} -setup { proc bgerror msg { global x errorInfo set x [list $msg $errorInfo] } frame .t.f -class Test -width 150 -height 100 @@ -5942,11 +5942,11 @@ } -result {{This is a test} {This is a test while executing "error "This is a test"" (command bound to event)}} -test bind-29.2 {Tk_BackgroundError procedure} -setup { +test bind-29.2 {Tcl_BackgroundError procedure} -setup { proc do {} { event generate .t.f